fc2ブログ

9ballsyndrome

Molehill Stage3D API AGAL言語について2

Molehill Stage3D APIでシェーダとして使用するAGAL言語について。

 

前回に引き続き、iFlash3D "My Name is AGAL, and I Come from Adobe – Part2"の拙訳を。

 


 

---

Part1ではAGALのメインコンセプトについて話した。

AGALはとりあえず、資料の少ない、しかし強力な"ちょっと"わけのわからない言語になっただろう。

Flashの歴史上初めて、我々は機械語のフルパワーを発揮できるようになった。これは「Flashだろ。遅いじゃん」とかいったものではない。AGALはGPUと同じ速度で実行できるのだ。

問題はAGALがアセンブリ言語であることだ。ゆえに我々が今まで書いてきた、慣れ親しんだ素晴らしいActionScriptとは違ってとても難しく、直感的でない。

初見ではAGALはヒエログリフの一種かと思うだろう。Part1を読んで少しでも理解を深めてもらえることを願う。これを読んだならオペコードとレジスタについて理解し、多少は親しめていることだろう。

しかしちょっと地球外文明、異なった文化の言語に触れることを考えてみてほしい。彼らとコミュニケートするには何が足りないだろうか。

そう。交信する窓口、スターゲイトだ。

我々の言語はActionScript。彼らの言語はAGAL。そしてスターゲイトとはMoleHill APIだ。

銀河間コーディングへようこそ!

 

ActionScript側でのシェーダ

Molehillの全てのレンダリングはシェーダが重要だ。シェーダなしではレンダリングすることはできない。 Molehill APIのセットアップはシェーダが実行できるようにするために行われる。AGALとシェーダがMoleHillにおいてどれだけ重要かということだ。

Part1の最もシンプルなシェーダはこうだった。

//vertex shader
m44 op, va0, vc0 // pos to clipspace
mov v0, va1 // copy uv
 
//pixel shader
tex ft1, v0, fs0 <2d,linear,nomip>
mov oc, ft1

これをActionScriptから実行したい。

まず最初は、頂点を通してジオメトリを定義しなくてはならない。

4つの頂点で作られた四角形をディスプレイに出力したいとしよう。

var vertices:Vector.<Number> = Vector.<Number>([
-0.5,-0.5,0, 0, 0, // x, y, z, u, v
-0.5, 0.5, 0, 0, 1,
0.5, 0.5, 0, 1, 1,
0.5, -0.5, 0, 1, 0]);

各頂点はx,y,z座標とu,vテクスチャ座標からなる。

この頂点はVertexBuffer3Dに保持される。

// 4 vertices, of 5 Numbers each
var vertexbuffer:VertexBuffer3D = context3D.createVertexBuffer(4, 5);

これはcontext3Dを通してGPUにアップロードされる。

vertexbuffer.uploadFromVector(vertices, 0, 4);

次に三角形を定義する必要がある。これはindex bufferで行う。

// total of 6 indices. 2 triangles by 3 vertices each
var indexbuffer:IndexBuffer3D = context3D.createIndexBuffer(6);

このindex bufferでは2つの三角形を定義する。1つめは頂点0,1,2から、2つめは頂点2,3,0からなる。

vertex bufferと同じようにindex bufferも使う前にGPUにアップロードしなくてはならない。

// offset 0, count 6
indexbuffer.uploadFromVector (Vector.<uint>([0, 1, 2, 2, 3, 0]), 0, 6);

テクスチャも必要だ。これはswfに埋め込んだjpg(もしくは外部から読み込んだ画像でも良い)を使い、GPUに送る。

var bitmap:Bitmap = new TextureBitmap();
var texture:Texture = context3D.createTexture(bitmap.bitmapData.width,
bitmap.bitmapData.height, Context3DTextureFormat.BGRA, false);
texture.uploadFromBitmapData(bitmap.bitmapData);

最後にAGALシェーダプログラムだ。まずAGALMiniAssemblerでコンパイルする必要がある。

var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
"m44 op, va0, vc0\n" + // pos to clipspace
"mov v0, va1" // copy uv
);
var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
"tex ft1, v0, fs0 <2d,linear, nomip>;\n" +
"mov oc, ft1"
);

そして頂点、ピクセルシェーダプログラムをGPUにアップロードする。

var program:Program3D = context3D.createProgram();
program.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);

 

準備ができたのでレンダリング

では全てアップロードされ、準備ができたのでついにレンダリングすることができる。

まず、viewportを好きな背景色でクリアする

context3D.clear ( 1, 1, 1, 1 );

そして、この描画に使うvertex bufferとindex bufferとテクスチャとシェーダプログラムを指定する。

// vertex position to attribute register 0
context3D.setVertexBufferAt (0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
// uv coordinates to attribute register 1
context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);
// assign texture to texture sampler 0
context3D.setTextureAt( 0, texture );
// assign shader program
context3D.setProgram( program );

頂点座標とuv座標、2つのvertex buffer streamをどのように2つのattributeレジスタに割り当てるのかに注意してほしい。テクスチャは特定のtexture samplerに割り当てられる。

次に変換行列をシェーダに渡さなくてはならない。ここではすごい3D投影はせず、普通の変換行列にしよう。

var m:Matrix3D = new Matrix3D();
m.appendRotation(getTimer()/50, Vector3D.Z_AXIS);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);

ここでは行列は頂点シェーダで使えるようcontantレジスタ0にいれられる。

レンダリングするにはindex bufferを渡してdrawTrianglesを呼ぶだけだ。

context3D.drawTriangles( indexBuffer);

フレーム内で他のジオメトリを描画するにはdrawTrianglesを複数回呼べばいい。そして最後にフレームに実際にレンダリングするためにpresent()を呼ぶ。

context3D.present();

---

 

 

 

実行した結果とソースコードは元記事にリンクがある。テクスチャ貼られた四角形が回転するものだ。

 

1つのジオメトリに対して1つのvertex bufferとindex bufferを用意してdrawTriangles()するということなのかな。

テクスチャレジスタfsが8つまでなのもジオメトリを複数にすれば解決できるもんね。

ジオメトリの数だけdrawTriangles()読んだら大変なことにならんのかな。

 

 

スポンサーサイト



  1. 2011/07/16(土) 13:56:47|
  2. Molehill Stage3D
  3. | トラックバック:0
  4. | コメント:0
<<Molehill Stage3D API 入門2 | ホーム | Molehill Stage3D API viewPortについて(暫定)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://9ballsyndrome.blog.fc2.com/tb.php/25-ebc24fb8
この記事にトラックバックする(FC2ブログユーザー)