TypeScript」ライブラリとして進められています。TypeScriptを使った3次元空間のアニメーションで、燃える炎を表現してみました(サンプル001)。このサンプルの床にテクスチャを与え、さらに凹凸や反射の表現も加えてみましょう。Examples」のディレクトリbin/assets/に納められているfloor_diffuse.jpgを用います。パーティクルのアニメーション」09「パーティクルの素材にテクスチャを与える」でご説明しましたので、詳しくはこのノートをご参照ください。パーティクルのアニメーション」のコード005「3次元空間のカメラをマウス操作に合わせてパンおよびチルトさせる」をもとに、JavaScriptコードを書き加えていきます。でき上がったscript要素は、後にコード001としてまとめました。その中の床にテクスチャを与える処理は、以下に抜書きしたとおりです。読込む画像ファイルはこの後も増えるので、URLは変数(imageDiffuseとimageParticle)にとりました(第36〜37行目)。ロードの関数(loadAsset())にそのURLを渡して読込みます(第45〜46行目)。床の平面をつくる関数(createPlane())は、そのマテリアルには後でテクスチャを与えるので、オブジェクトをつくるTriangleMethodMaterial()コンストラクタは引数なしに呼出します(第62行目)。素材が読込まれたとき(AssetLibraryBundle.resourceCompleteイベントで)呼出されるリスナー関数(onResourceComplete())は、扱う画像ファイルが複数になったのでその判定をしなければなりません。引数のイベントオブジェクト(eventObject)から素材の配列(assetsプロパティ)とURL(urlプロパティ)を得て、case文で配列エレメントの素材(asset)をURLに対応したマテリアルのテクスチャに与えます(第187〜195行目)。パーティクルのアニメーション」の注[*3]をご参照ください。{loadAsset(eventObject.url);}}これで、床の平面にテクスチャが与えられました(図002)。表面が滑らかに見えるので、敷石のようなテクスチャではあるものの、質感は模様が入ったプラスチックシートのようです。参照しやすいように、ここまでのscript要素をコード001にまとめました。テクスチャに凹凸と反射の質感を加える均一な平面のテクスチャに凹凸と反射の違いを加えると、質感が大きく変わります。3次元のオブジェクトのかたちそのものに細かな凹凸を加えたら、負荷が上がるばかりです。それに細かいところはこだわらなくても、それらしく見えれば済みます。そこで、テクスチャに与えるマップで、光の反射の仕方を変えてみます。マップはふたつ使います。第1は、法線マップです。map)とも呼ばれます。"normal"は「普通」ではなく、面に垂直な「法線」を意味します。テクスチャのピクセルごとの面の向きを示すのです[*1]。テクスチャの画素は「テクセル」ということもあります。法線マップの画像は、各ピクセルの法線のxyz座標値をRGBチャネルの値で表します(図003左)[*2]。第2に用いるのが、スペキュラマップです。ピクセルごとの反射の強さを示します。光を反射しやすいかしにくいかによって、テクスチャの質感はかなり変わります。カラーが白に近いほど光の反射は強く、黒に近づけると光を吸収します(図003右)[*3]。これらふたつのマップ画像として、サンプルのfloor_normal.jpgとfloor_specular.jpgを用いました。図003■法線マップとスペキュラマップ法線マップスペキュラマップ画像としてつくった法線とスペキュラのマップをマテリアルに与えるには、それぞれTriangleMethodMaterial.normalMapとTriangleMethodMaterial.specularMapプロパティに定めます(表001)。画像ファイルの読込みと、ロードした素材のプロパティへの割当は、以下の抜書きのようにテクスチャに用いたふたつの関数(loadAsset()とonResourceComplete())で扱います。法線マップとするテクスチャ。ピクセル(テクセル)ごとの面の向きを示し、陰影を与える。スペキュラマップとするテクスチャ。ピクセル(テクセル)ごとの光の反射の強さを示す。asset;break;}}}法線マップにより敷石の凹凸が示され、それらの境目は反射がなくなりました(図004)。もとののっぺりとしたテクスチャに、細かな質感が加わっています。マウスドラッグでパン・チルトすると、違いがよくわかるでしょう。ここまで手を加えたJavaScriptは、コード002にまとめました。クラス(FireObject)の定めは変えていないので省いています。ご参考までに、jsdo.itにもサンプル002のコードを掲げました。(14)「微細凹凸表現の基本形『法線マップ』(1)」をご参照ください。画面に対して左右が赤、上下は緑、前後が青で示されます。「GLSLでバンプマッピング」をご参照ください。スペキュラマップは厳密には、赤チャネルが反射の強さ、緑チャンネルで光沢を定めます。ふたつを分けて決めなくてもよい場合には、グレースケールで与えて構いません。fire」です(図001)。仕上げに、炎の数を同じように増やしてみます。炎をつくる関数(createParticles())は、初期化の関数(initialize())から呼出しました。呼出す関数に渡す第1引数が、つくる炎の数を決めますので、この数値を大きくすればよいでしょう(第23行目)。scene);}ところが、ブラウザで確かめてみると、炎がすべて表示される前にオブジェクトがみな消え去って、真っ黒な背景しかが残りません。overflow!」のエラーが示されます(図005)[*4]。これは、Away3Dのレンダラの処理能力が追いつかないために起こるエラーです。Xのエラーコンソールに示されたメッセージこの問題を解決するには、TriangleMethodMaterial.materialModeプロパティを定数TriangleMaterialMode.MULTI_PASSに定めます(デフォルト値はTriangleMaterialMode.SINGLE_PASS)。後に掲げたでき上がりのコード003は、つぎの抜書きように床の平面をつくる関数(createPlane())で、マテリアル(material)にこのプロパティ値を定めました(第46行目)。away.materials.TriangleMaterialMode.MULTI_PASS;}これで、床のテクスチャに凹凸や反射が加わったうえ、燃え上がる炎のパーティクルの数も増えました(図006)。fire」とほぼ同じ表現です。スクリプトの組立て方は、筆者がよりわかりやすいと考えるスタイルにしてあります(コード003)。でき上がったコードは、サンプル003としてjsdo.itにも掲げました。2014年8月26日付ビルドでは、このエラーは起こらなくなりました。修正・改善の中身が明らかにされてないため、本文の記述はそのまま残すことにしました。overflow!"のエラーは、RegisterPool.requestFreeVectorReg()メソッドから投げられていたようです。TypeScriptライブラリを使う」参照)。