読者です 読者をやめる 読者になる 読者になる

ActionScriptでジオメトリブレンディング+AGALで金属光沢シェーダ

ActionScript3 wonderfl Stage3D


Metallic Soft Cube | Si+ (wonderfl.net)


ついにwonderflが、FlashPlayer11に対応しましたね。
3Dライブラリ系のFlashPlayer11対応版へのアップデートはまだなので(というか、既存3Dライブラリって過去との互換性を保ちながらアップデート可能なんだろうか?)、本格的に盛り上がるのはもう少し先かなと思ってますが、せっかく使えるようになったことだし、早速1本投稿してみました。


ついでにモルヒル時代に(wonderfl上では動かないけど)投稿してた作品も、無事動くようになったので再コンパイルしました。技術解説的なものは、ActionScript で屈折レンダリング+Molehill雑感 - Simple Inspirationあたりに書いてますので、ご参考ください。
Clear Water with refraction rendering | Si+ (wonderfl.net)

さて、今回の投稿ですが、ジオメトリブレンディングした立体を、基本的なグローシェーディング+擬似環境マッピングレンダリングしただけの非常にシンプルなデモです。シンプルですが、デモシーンでよく使われる定番のひとつで、これをベースに応用を利かせれば実はかなり色々なことができます。立体の選び方やカメラワーク等、工夫次第で最新のデモシーンでも問題なく使っていけるような汎用性の高い手法ですので、簡単に概要を書いておきます(さすがに最新シーンでグローシェーディング+擬似環境マッピングのみって事はあまりありませんが)。


まずジオメトリブレンディングについてですが、やってることはwonderflで3D 【Flat shading】 - wonderfl build flash onlineと同じです。

  • 各面を適当に分割(今回は14分割)した立方体を作成
  • それぞれの頂点と立体の中心を結んだ直線上に、中心から同距離の頂点を作成
  • (中心から同距離の頂点郡なのでこれは球面上に配置される)
  • この二つの頂点座標をブレンド値で内分(外分)した頂点で立体描画

あとはこのブレンド値をどう計算するかで、さまざまな立体に変化します。wonderflで3D 【Flat shading】 - wonderfl build flash onlineでは全頂点に同じブレンド値を適用しているため、立方体8頂点が引っ張られたり縮んだりするような変化をします。今回は、立方体8頂点からの距離を各ブレンド値への影響度として計算することで、立方体8頂点がそれぞれ独立して伸張できるようになっていて、それらを位相をずらしたサインカーブで動かすことで今回のようなグニャグニャ変形を行っています。デモシーンにおけるサインカーブの汎用性の高さは異常。
...とまぁ、言葉で説明するには限界がありますので、変形元立体の頂点計算やブレンディング値の重み計算はline82からとline138から、ブレンド値計算はline183からを参照してみてください。
今回ブレンドした立方体と球は、単純に計算しやすいという理由で選んでます。ブレンドする立体の種類、ブレンド値の選択によって実にさまざまな変化をしますので、色々試してみると面白いと思います。というか、いろいろな立体のブレンド結果を見てみたい。


次に金属光沢シェーダについてです。グローシェーディング+擬似環境マッピングなので、何にも面白いことは無いんですが、簡単かつ見栄えが良いのでよく使われる定番シェーダです。車のボディの表現とかでおなじみですね。技術デモだと擬似環境マッピングだけでもきれいなのでそこで満足して終わってしまうものが多いんですが、個人的にはグローシェーディングと組み合わせてこそ真価を発揮すると思ってます。しかしFlashPlayer10の偽3Dでは両方レンダリングしようとすると非常に重くなってしまうので、この表現ができるのはFlashPlayer11の恩恵の1つです。
さてこの金属光沢シェーダ、定番ではありますが、非常に多くの工夫の余地がある面白い題材です。基本的には環境光(ambient)、拡散光(diffuse)、光沢(specular)、反射(reflection)の4つの光を合成するシェーダということになりますが、

  • どこまでソフトウェア(ActionScript)で計算してどこからシェーダに任せるか
  • どこを予め計算したテーブルに置き換えるか
  • どのベクトル計算を近似に置き換えるか

といった部分が工夫のしどころとなります。用途によってはかなり大胆に端折ることもできるので、用途、品質、パフォーマンスを見ながら都度最適化していくのが理想だと思います。残念ながら、ここら辺を解説できるほど十分なノウハウを持ってないのでここで細かい事は書けませんが、ある程度ノウハウがたまってきたところで、もう一度記事にしてみたいな、と思っています。
とりあえず今回のデモで使用した金属光沢シェーダでは、シェーダで頂点法線の正規化を行う、光沢を予め計算したテクスチャから取得する、反射計算の際の視線ベクトルを画面に対して垂直と仮定する、ハードライト合成で近似を使う、あたりが特殊だと思います。

どちらも汎用性の高い手法なので、既存3Dライブラリでも結構簡単にできるんじゃないかと思いますが、一度ネイティブでトライしてみると3Dへの見識が深まるかもしれません。