2012/05/13

cocos2dでパレットっぽいことをしてみたい その2

以前書いていたエントリーの続きです。その時はシェーダープログラムが全くわからない状態だったので試さなかったのですが、cocos2d 2.0がRC1になったこともありますので、シェーダーに手を出してみました。ここ最近やってるUnityでのシェーダー入門がうまく役に立っているってのもありますね。ちなみにシェーダー入門にUnityは向いているような気がします。すぐに絵を出せますからシェーダーコードに注力できます。とはいえShaderLabという特殊な記述方法となるのでOpenGL ESでGLSLを使うのとは若干違いますけど。まぁ考え方は一緒です。

●以前のアイデア
1,テクスチャ書き換え
2,白い素材を用意し、マテリアル色指定
3,シェーダーでリアルタイム書き換え

 というアイデアを出していました。2までは前回達成しています。1はバッチが効かず、メモリ圧迫も多いため事実上使わないほうがよい手法でした。2については前回のレベルでは限界値で、ぎりぎり実用レベルだった感じです。
 さて、今回は3を実装しました。

●前回の評価を考えなおす
 前回は以下のように3を評価していました。

 利点:テクスチャが共通なので省メモリ
 欠点:僕はシェーダー作ったこと無い。OpenGLES2に対応したcocos2d2.0のベータ版を使わないとならない。描画が遅いかもしれない。シェーダーに渡すパラメータが色ごとに変化するので、CCSpriteBatchNodeで処理させるには難しいかも?

 最初の欠点は今では問題ないです。個人的に。
 2番目はcocos2d 2.0 RC1となったので問題ないでしょう。
 3番目はやってみないとわからない。
 4番目はバッチ処理するためのいい方法を考えましたので、次項で説明します。

●バッチ処理のために
 cocos2d 2.0のソースを見ていると、cocos2dの描画に必要な基本的なシェーダーが全部用意されています。その中身を読んでいくとスプライトの色を設定してもバッチ描画を可能にするための技を確認できました。
 通常OpenGL等では、いわゆるマテリアル(テクスチャ)が違うものはバッチ処理ができないものですが、頂点座標、頂点カラー、頂点UV値、オブジェクトのTransform情報については違っていても1つのDrawコマンドで描画することができます。Transform情報についてはcocos2dの内部で1オブジェクトとなるようにバッチノードに登録されたすべてのスプライトを1つのバッファに入れ込んで参照しているからですね。その他のパラメータは頂点に備わっている情報なので、1つながりのバッファにしてしまえば1度に送れます。
 というわけで、cocos2dでは1.0の時からそうだったようですが、スプライトの色は頂点カラーへセットすることでバッチ描画を可能にしてたんですね。これを使わない手はありません。
 シェーダーでパレットチェンジするための色変化情報は頂点カラーへもたせましょう。頂点カラーはRGBAの4チャンネルしかないので1枚のスプライトのなかに持てるパレットインデックスは4種類しか持てなさそうです。その中でアルファにはスプライトの透明度が入っているので使えないでしょう。ということでRGBのチャンネルに色変化情報を与えてやって1枚のテクスチャにつき3色変更可能というようにしました。

●パレット処理の仕様
・テクスチャのRGBをそれぞれ好きな色に変更可能
・変更後の色は頂点カラーRGBへ3色セットする(Rが1色目、Gが2色目、Bが3色目)
・セットする色はビット圧縮をかけて入れる(RGB=3:3:2bit)
 ビット圧縮で8bitに収めたのはccColor3BでCCSpriteを継承したクラスに色をセットしたり、cocos2d通常の描画ルーチンを流用するためです。ビット圧縮はHSVとかYUVを使った方が色の再現性がいいかもです。そのうちやってみます。

●パフォーマンスはどうかな?
上:cocos2d 1.0 白テクスチャに色設定して重ねたもの


左:cocos2d 2.0 白テクスチャに色設定して重ねたもの
右:cocos2d 2.0 でシェーダーで色変化させたもの

 3つテストしました。
 前回作成した上のものは、アイドル時には60FPSが出ることもありましたが、画面がスクロールすると描画される頂点数が変化して頂点バッファを作り直すのに時間がかかるようで、最低では25FPSまで下がるようです。
 左のものは、同じソースをcocos2d 2.0で動作させたものです。60FPSから落ちることなくスイスイ動いています。これでいいんじゃないかという気もします。cocos2d 2.0からはフレームレート表示に上から、ドローコマンド数、処理時間、FPSの3つが表示されます。バッチが効いているのでドローは3(背景、キャラたち、ラスター線)です。処理時間はアイドル時0.007で、画面スクロール時には0.017までかかります。
 右のものは、パレットチェンジシェーダーで表示したものです。これも60FPSから落ちることはありません。バッチ描画ができているのでドロー数もかわりません。処理時間はアイドル時0.004で、画面スクロール時には0.017までかかります。
 というわけで、なかなかの好成績です。結論から言うと通常描画が速いのでシェーダーでやらなくてもいいかもという気もしなくもないですw cocos2d 2.0は描画が速いですね。

 今回は以上です。
 今度6/21に行われる予定のcocos2d bootcampでcocos2d 2.0のシェーダーについてのLTをたぶんやるとおもいますので、もしよろしければ聞いてください。

0 件のコメント:

コメントを投稿