皆様こんにちわ。
ふむふむソフト代表取締役の飯島です。
ひさびさに地味な研究結果を発表したいと思います。
今回はSilverlight3から搭載されたWriteableBitmapについてです。
WriteableBitmapとは簡単にいえば「書き換え可能なビットマップ」です。
WPFには以前から搭載されていたようですが、Silverlightにも3から搭載されました。
さて、このクラスを使うメリットは「ピクセルを直に触れる」ことにあります。
本来であれば、XAMLの高度な描画メソッドを使ってバリバリ描画していくのがSilverlightのあるべき姿なんでしょうが、ピクセルが触れるとなれば黙っていられないのがVGA(DOS)時代のPCゲームにヤラレちゃってた人間の性なのです。
私の場合、DirectDrawはもちろん、WinGの時からそうだったのですから仕方がありません。
話を戻しましょう。
このSilverlight3のWriteableBitmapは、ピクセルがint型の配列になっています(pixelsメンバ)。
(この時点でVGAの13hモードのVRAMを思いだして胸が熱くなります)
この配列のintの値は「ARGB(各8bit)」になっており、配列の長さが「ビットマップの幅×高さ」になっています。
ちゃんとαチャンネルの値を保持できる辺りも嬉しい限りです。
この配列に対して、シフト演算子でARGBの値を使ってint型を作って、「幅×y座標 + x座標」みたいな感じでpixels配列にセットすればその部分のピクセルの色が変わる、というある種の方々には大変直観的な設計になっています。
が、タダの配列とはいえ、細々とアクセスをしていると「?」となるくらい遅くなる時がありました。
そこで、モノは試しで「ダブルバッファ」をやってみたのがこのサンプルです。
Silverlight3 + WriteableBitmapのダブルバッファサンプル
(※動作にはSilverlight3が必要です)
ソースコードはコチラ
(要Visual Studio 2008 + Silverlight3 SDK)
やっている事は「600×400ピクセルのWriteableBitmapに同じ色をセットする」という処理なのですが、二通りの方法でテストしています。
まず、通常(赤)と書いてある方が、ループでピクセル(赤)をセットする方法です。
そしてダブルバッファ(緑)という方が
・pixelsと同サイズのint型の配列を作る
・その配列に対して同じくint型のピクセル(緑)をセット
・配列の「CopyTo()」を使って、pixelsに一気にCopy
という手順を行っています。
どちらも画面更新(Invalidate())のタイミングに違いはありません。
見た眼は死ぬほど地味(色は派手)ですので、興味が無い人には全くもってアピールのないサンプルですが、注目して頂きたいのはそれぞれの処理を行っている時のフレームレートです。
私の環境では、
・通常(赤) : 150fps前後
・ダブルバッファ(緑) : 180~190fps前後
となっています。
一見余計な手順を踏んでいる後者の方が、30~40fps(20~25%)ほど速いのです。
一応、弊社内の色々なPCで試してみましたが、大体
・緑の方が速い
・赤と緑で差が無い
というケースに分かれ、(本来そうなりそうなものなのですが)少なくとも緑の方が遅くなる、というケースは見受けられませんでした。
皆様の環境での差も教えて頂きたいところです。
なぜこのような差が発生するのか理由は不明ですが、「pixelsってアクセス時に何がしかのチェックロジックが走る」という事なのでしょうか…?
なんにせよ「やっておくと多少速くなる『かも』」なテクニックとして試して頂ければと思います。
なお、今回のサンプルコードでは、フレームレート処理部分にblog.sph62.net様の「SilverlightでFlash的なパーティクル(サンプル)」という記事からコードを拝借いたしました。
それでは失礼いたします。