前に触れた(id:ABA:20060815#p1)Xbox 360用のゲームが作れるXNAフレームワークのベータ版が公開された。まだ360実機で動作させる方法は不明だが、とりあえずWindows上でどんな感じで書けばいいのかを試すことはできる。
あちこちでXNA用のサンプルプログラムとして挙げられているものは、たいていビットマップをスプライトとして表示してみましょう、とかいう内容なのだが、正直私にとってそれはどうでもいい。なぜなら私はビットマップが書けないからさ!悲しい。
なので私が知りたいのはアルファ付きの3Dプリミティブを書く方法だ。3Dの三角形さえ書ければとりあえずはなんとかなる。なのでその方法を探したのだが……よくわからん。そもそも私はDirectXを大昔に挫折した人間なので、その内容をまったく知らんのだ。まあ私が挫折した10年近く前のDirectXと今のManagedなDirectXはぜんぜん別物らしいが。XNAに付属するAPIドキュメントはそれなりに充実しているが、どこを見ればいいのか分からんし。
でもいろいろあさってたら以下のサンプルを見つけた。
- 3D vertex and pixel shader example(http://www.xnaspot.com/Sample_ShaderExample.aspx)
おおこの三角形こそ私の求めていたものだ……なんとかshaderとか書いてあるけど、まあそんな高級なものに触らんでもなんとかなるだろう。とりあえずワールド座標系の扱い方でも見てみようか。
CompiledEffect compiledEffect = Effect.CompileEffectFromFile (@"..\..\shaders\simple.fx", null, null, CompilerOptions.None, TargetPlatform.Windows); effect = new Effect(graphics.GraphicsDevice, compiledEffect.GetShaderCode(), CompilerOptions.None, null); worldViewProjParam = effect.Parameters["worldViewProj"];
???……'compiledEffect.GetShaderCode'してエフェクトを作ってパラメタを取って?
worldViewProjParam.SetValue(worldMatrix * viewMatrix * projMatrix); effect.CommitChanges();
マトリクスを設定して'effect.CommitChanges'?なんじゃこりゃ。私シェーダに関しては何も知らないのですが……なんかいやな予感がするが、'simple.fx'を見てみよう。
// VERTEX SHADER void vs(in a2v IN, out v2p OUT) { OUT.position = mul(IN.position, worldViewProj); OUT.color = IN.color; }
バーテックスシェーダで、設定したマトリクスを適用して出力している……えー、わざわざこんなことしないといかんの?単に視点を設定するだけで?
まあこれが最近の正しい3Dプログラミングだというならそれにならおう。シェーダなんか知らね、とかいうロートルプログラマじゃだめってことですか。まあこんくらいの基礎中の基礎ならなんとかなりそう、か?
あと三角形の描画自体は、
Color c = new Color(50, 255, 50, 100); triangle[0] = new VertexPositionColor(new Vector3(1.0f, 0.0f, 0.0f), c); triangle[1] = new VertexPositionColor(new Vector3(0.0f, 1.0f, 0.0f), c); triangle[2] = new VertexPositionColor(new Vector3(-1.0f, 0.0f, 0.0f), c);
というようなVertexPositionColorの配列を用意して、
graphics.GraphicsDevice.DrawUserPrimitives<VertexPositionColor> (PrimitiveType.TriangleList, 1, triangle);
DrawUserPrimitivesを呼び出せばよいみたい。三角形にアルファをかけるには、
graphics.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha; graphics.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha; graphics.GraphicsDevice.RenderState.AlphaBlendEnable = true;
てな具合にRenderStateを設定すればOK。あとアルファ値は直接Colorで設定してもいいし、ピクセルシェーダで'OUT.color.a'みたいなパラメタを変更してもいい。これってどっちを使った方が速いんだろ。アルファが逓減するパーティクルみたいのを実現する際にピクセルシェーダをうまいこと使う方法、みたいのがあるのかな。この辺もぜんぜん分からん。
ちなみに昔の私を挫折に追いやったDirectX周りの初期化のごちゃごちゃは、XNAでは'Microsoft.Xna.Framework.Game'クラスの中にきれいに隠蔽されていて影も形もない。ゲームライフサイクル管理周りはProcessing並みに簡単になっている感じ。この辺はよくできてそうだ。
あとここまで書いてから気づいたのだが、
- XNA Game Studioメモ(http://www.saturn.dti.ne.jp/~npaka/xna/index.html)
ここにも3Dプリミティブを表示するサンプルがちゃんとあった……でも頂点シェーダは使っているなあ。やっぱり必須なのかな。