Windows 7 での滑らかなアニメーションの実現 (1)

# だんだんULWが関係なくなってきたので、タイトルを変更した。

こんなポストを見つけた。やっぱり困ってる人がいたらしい。

万一消えるともったいないので引用しておこう。

I have a WPF app that requires smooth scrolling text.  No matter what I do, I seem to get jumpy animation.  I have a background in games development so I am very familiar with the technique of locking framerate to the monitor v-sync as a method for assuring smooth animation.  There seems to be no way to accomplish this in WPF, which is astonishing for a platform that claims to be graphics and animation oriented.  I have read that on Vista and SOME XP machines, it does synchronize to the monitor v-sync to eliminate tearing, however I want it to LOCK the framerate at say 30fps (even though 60fps may be possible most of the time) so that there are never any hitches in the scrolling.

I have spent days searching the web for answers and experimenting with code.  I found this post from 2007 where someone has the same problem.  The only answer was to try using Storyboard animations instead of using CompositionTarget.Rendering.  I have tried this and it makes no difference.  Furthermore, I need to do custom animation that is dynamic and not pre-defined, so Storyboard animation doesn't really fit my needs in this case.

I have also found this post where people have had the exact same problem but in relation to achieving smooth video playback.  The unanimous solution there seems to be to bypass WPF and use DirectShow with a Win32 solution to render the video.  It looks like I am going to have to attempt this as well.  It is very disappointing,  however, as WPF and C# are so much easier to use.  I am very surprised that the WPF team seems to have completely overlooked this fundamental requirement in the design of the WPF architecture.  It basically makes WPF completely unsusable for any commercial application that demands smooth, game-quality animation.

Before I throw in the towel on WPF and resort to Win32, does anyone have any final suggestions?

回答ポストに対する返信も。

Yes, I tried that.  Setting the DesiredFrameRate property only applies if you are doing Storyboard animations, as I understand.  I am using CompositionTarget.Rendering to update the transform.  Even with Storyboard animations and this property set (to 30fps for example), I still don't get even lengthed frames and the animation is jumpy.

I'm guessing that WPF is quantizing the double buffer flip to be an even multiple of the monitor v-sync. So if the monitor is at 60fps, it will update the display at either 60, 30, or 15 fps.  It is the fact that every frame is of different duration that I'm having this problem.

I want to lock the frame rate at 30 so that it doesn't jump back and forth between 30 and 60 every frame.  You can do a simple test to see what I'm talking about.  Just measure the time difference between each call to CompositionTarget.Rendering and you will see that it fluctuations between 14.9 and 29.8 milliseconds, or some similiar pair where A = 2*B.

上の方の調査や、私の実験の結果などを総合して考察すると、どうもこんな感じらしい:

  1. WPFでアニメーションする場合は、StoryboardなどTimelineから派生したクラスを使うのが良い。CompositionTarget.Rendering や、フレーム更新スレッドなどを利用して安定したフレーム描画を行うことは難しい。
  2. Storyboardを利用した場合でも、厳密にディスプレイの更新には同期していない。したがって、DWMとのずれによってはコマ落ちが起こる。このせいで、”commercial quality” or “game-quality” のアニメーション品質を得ることは非常に難しい。

なんか、えーって感じ。ちなみにXNAを使うとゲーム品質のアニメーションが手に入るらしいが、、、