テクスチャマッピングは、テクスチャ (ビットマップ) を 3D オブジェクトの表面、すなわち 3 角形のメッシュに貼り付ける作業です。Photoshop 等で加工した画像を使って、オブジェクト表面に質感を与えることができます。
今回は、Stage3D でテクスチャマッピングを行う方法をご紹介します。
UV 座標
テクスチャマッピングの処理は、大雑把に表現すると、3 角形の上にビットマップを重ねて、3 角形内部の各ピクセルの色を、その上に位置するピクセルの色とする、というイメージです。
その際、ビットマップのどのあたりが 3 角形の上に重なるのか、という情報が必要になります。そこで、ビットマップ内の位置を指定するのに用いられる 2 次元座標が UV 座標です。
UV 座標では、ビットマップの左下が基準点として使われ、U は横方向、V は縦方向の座標です。UV 座標が (0, 0) なら左下の角、(1, 1) なら右上の角の指定になります。
UV 座標の指定は 3 角形の頂点ごとに行います。つまり、この頂点の上に来るのはビットマップのこの位置、という指定をするわけです。なので、当然、UV 座標は頂点バッファ内に指定されることになります。 (この辺りの詳細は Stage3D と 2 つのシェーダと頂点情報)
例えば、x, y, z, の座標値と UV 座標の価を持つ頂点バッファを作成するための情報は、以下のような形になります。各行の最後の 2 つが UV 座標の値です。
var vertices:Vector.<Number> = Vector.<Number> ([ // x, y, z, u, vを指定 -0.3, -0.3, 0, 1, 0, -0.3, 0.3, 0, 0, 1, 0.3, 0.3, 0, 1, 1 ]);
頂点バッファ内の UV 座標は、頂点シェーダに頂点属性として渡されます。頂点シェーダは、 UV 座標を受け取ると、色情報の場合と同様に、後の処理に引き渡します。
テクスチャ関連の Stage3D API
Stage3D でテクスチャを扱う際は Texture クラスを利用します。Texture のインスタンスは context3D.createTexture() メソッドで取得できます。
テクスチャは、シェーダや頂点バッファと同様、事前に GPU にアップロードします。そのため Texture クラスには BitmapData や ByteArray をアップロードするメソッドが提供されています。
下は、Texture クラスの機能を使って BitmapData を GPU にアップロードするサンプルです。
[Embed(source = "MyTexture.jpg" )] var MyTextureBitmap:Class; var bitmap:Bitmap = new MyTextureBitmap(); // Texture のインスタンス生成 var texture:Texture = context3D.createTexture(bitmap.bitmapData.width, bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false); // 埋め込まれたビットマップをGPUにアップロード texture.uploadFromBitmapData(bitmap.bitmapData);
context3D.createTexture() の第 1 引数はテクスチャの幅、第 2 引数は高さです。第 3 引数はデータのフォーマットで、指定できる値は Context3DTextureFormat クラスに定義されています。ビットマップデータの場合は、上のサンプルの様に BGRA を使います。最後の引数は、アップロードしたテクスチャに描画する場合は true にしますが、通常は false で問題ないと思います。
Texture のインスタンスが生成されたら、データを GPU にアップロードします。上のサンプルでは、埋め込まれたビットマップデータを uploadFromBitmapData() メソッドを使ってアップロードしています。
シェーダ内では、アップロードしたテクスチャ用に、サンプラーレジスタという専用のレジスタが使われます。そこで、シェーダを実行する前に、アップロードしたテクスチャに対応するサンプラーレジスタの番号を指定しておきます。 (レジスタについては Stage3D のシェーダのアップロードと AGAL の基本情報)
使用するメソッドは context3D.setTextureAt() です。ここで指定する番号は、シェーダが参照するレジスタの番号と同じものにします。
// サンプラーレジスタの0番にアップロードしたテクスチャを設定 context3D.setTextureAt(0, texture);
context3D.setTextureAt() の第 1 引数は、利用するサンプラーレジスタの番号です。指定できる値は 0 から 7 の何れかです。第 2 引数は、サンプラーレジスタに設定するテクスチャです。
テクスチャを使用する場合のシェーダ
テクスチャを使用する際は、UV 座標が色情報の代わりに頂点シェーダに渡されます。頂点シェーダから見て、色情報を渡された時との違いは、属性レジスタに設定された値の種類だけです。
なので、頂点シェーダに関しては、テクスチャマッピングを行う場合も、以前の記事で紹介したサンプルがそのまま使えます。
m44 op, va0, vc0 mov v0, va1
2 行目で、頂点シェーダは、属性レジスタ va1 に設定された UV 座標をそのまま出力レジスタである v0 に代入して、次の処理に渡しています。
UV 座標はラスタライズの際に補間され、各断片に割り振られます。断片シェーダは、割り当てられた UV 座標に対応するテクスチャのピクセル (テクセルと言うとか) を参照して、サンプリングを行います。
サンプリングに使われるオプコードは tex です。tex は、ソース 2 の位置 (オプコードから 3 番目) にサンプラーレジスタを指定する点と、その後にオプションを指定するフラグを列挙する点が特徴です。
下は、テクスチャーマッピングを行う断片シェーダの例です。
tex ft1, v0, fs0 <2d,linear> mov oc, ft1
1 行目で、テクスチャのサンプリングを行っています。v0 が補間された UV 座標、fs0 がアップロードされたテクスチャのレジスタです。サンプラーレジスタの番号 (上の例では 0) は、context3D.setTextureAt() の第 1 引数で指定した数値と同じでないと期待通りに動作しません。
1 行目の最後、サンプラーレジスタの右に記述されているのがフラグです。フラグは複数記述することができます。指定できるフラグには以下のものがあるようです。
- テクスチャの次元: 2d, cube
- ミップマップのオプション: nomip , mipnearest, miplinear
- テクスチャフィルタのオプション: nearest, linear
- テクスチャの繰り返しのオプション: repeat, wrap, clamp
テクスチャからサンプリングされたデータは、一時レジスタ ft1 に格納され、2 行目で出力レジスタに書き込まれています。
以上で、Stage3D でテクスチャを利用できる様になります。
とはいえ、AGAL でシェーダを書きたい人は少ないと思うので、次回は Pixelbender 3D をご紹介する予定です。
コメントする