TOP

ABOUT

PROGRAM

DIALY







バンプマッピング

 1.はじめに
 XNAのほうでバンプマッピングのプログラムを組んでみました。




 2.やり方
 基本的にはOpenGLのコードの使いまわしで,ほぼ同じです。
OpenGLの方では接ベクトルをパラメータを送る関数を使ってシェーダ側に渡していたのですが,
HLSLではセマンティックスでTANGENTが使えるので頂点宣言を使って頂点データを作成することにします。
まず,最初に頂点宣言用に構造体を定義します。
00019:          struct VertexPositionNormalTextureTangent
00020:          {
00021:              public Vector3 Position;
00022:              public Vector3 Normal;
00023:              public Vector2 TextureCoordinate;
00024:              public Vector3 Tangent;
00025:  
00026:              /// <summary>
00027:              /// Name : VertexPositionNormalTextureTangent()
00028:              /// Desc : コンストラクタ
00029:              /// </summary>
00030:              /// <param name="positon">位置座標</param>
00031:              /// <param name="normal">法線ベクトル</param>
00032:              /// <param name="texcoord">テクスチャ座標</param>
00033:              /// <param name="tangent">接ベクトル</param>
00034:              public VertexPositionNormalTextureTangent(Vector3 positon, Vector3 normal, Vector2 texcoord, Vector3 tangent)
00035:              {
00036:                  Position = positon;
00037:                  Normal = normal;
00038:                  TextureCoordinate = texcoord;
00039:                  Tangent = tangent;
00040:              }
00041:  
00042:              /// <summary>
00043:              /// 頂点要素
00044:              /// </summary>
00045:              public static readonly VertexElement[] vertexElements = {
00046:                  new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
00047:                  new VertexElement(0, sizeof(float)*3, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0),
00048:                  new VertexElement(0, sizeof(float)*(3+3), VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
00049:                  new VertexElement(0, sizeof(float)*(3+3+2), VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Tangent, 0)
00050:              };
00051:  
00052:              /// <summary>
00053:              /// サイズを返す
00054:              /// </summary>
00055:              public static int SizeInBytes
00056:              {
00057:                  get { return System.Runtime.InteropServices.Marshal.SizeOf(typeof(VertexPositionNormalTextureTangent)); }
00058:              }
00059:              
00060:          }

あとは,カメラの設定を行ない,頂点の設定を行なっていきます。
頂点の設定は上のように自分で用意した,VertexPositionNormalTextureTangent構造体を使って次のようにしました。
00123:          /// <summary>
00124:          /// Name : InitializeVertex()
00125:          /// Desc : 頂点の初期化
00126:          /// </summary>
00127:          public void InitializeVertex()
00128:          {
00129:              int numVertex = 6;
00130:  
00131:              // 頂点バッファを作成
00132:              vertexBuffer = new VertexBuffer(graphics.GraphicsDevice, VertexPositionNormalTextureTangent.SizeInBytes * numVertex, BufferUsage.None);
00133:  
00134:              // 頂点データを作成
00135:              VertexPositionNormalTextureTangent[] vertex = new VertexPositionNormalTextureTangent[numVertex];
00136:              
00137:              // 頂点データを設定
00138:              vertex[0] = new VertexPositionNormalTextureTangent(new Vector3(-1.0f, 1.0f, 0.0f), Vector3.UnitZ, new Vector2(0.0f, 0.0f), Vector3.UnitX);
00139:              vertex[1] = new VertexPositionNormalTextureTangent(new Vector3(1.0f, 1.0f, 0.0f), Vector3.UnitZ, new Vector2(1.0f, 0.0f), Vector3.UnitX);
00140:              vertex[2] = new VertexPositionNormalTextureTangent(new Vector3(-1.0f, -1.0f, 0.0f), Vector3.UnitZ, new Vector2(0.0f, 1.0f), Vector3.UnitX);
00141:              vertex[3] = new VertexPositionNormalTextureTangent(new Vector3(1.0f, 1.0f, 0.0f), Vector3.UnitZ, new Vector2(1.0f, 0.0f), Vector3.UnitX);
00142:              vertex[4] = new VertexPositionNormalTextureTangent(new Vector3(1.0f, -1.0f, 0.0f), Vector3.UnitZ, new Vector2(1.0f, 1.0f), Vector3.UnitX);
00143:              vertex[5] = new VertexPositionNormalTextureTangent(new Vector3(-1.0f, -1.0f, 0.0f), Vector3.UnitZ, new Vector2(0.0f, 1.0f), Vector3.UnitX);
00144:  
00145:              // 頂点バッファにデータをセット
00146:              vertexBuffer.SetData<VertexPositionNormalTextureTangent>(vertex);
00147:          }

頂点データの設定が終われば,あとはシェーダ側にパラメータを送って描画するだけです。
00228:          protected override void Draw(GameTime gameTime)
00229:          {
00230:              graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
00231:  
00232:              // TODO: Add your drawing code here
00233:  
00234:              // 頂点の設定とか
00235:              graphics.GraphicsDevice.VertexDeclaration = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionNormalTextureTangent.vertexElements);
00236:              graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTextureTangent.SizeInBytes);
00237:              
00238:              // カリングを無効化
00239:              graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;
00240:  
00241:              // パラメータをセット
00242:              effect.Parameters["Projection"].SetValue(projection);
00243:              effect.Parameters["View"].SetValue(view);
00244:              effect.Parameters["World"].SetValue(world);
00245:              effect.Parameters["bumpTexture"].SetValue(bumpMap);
00246:              effect.Parameters["color"].SetValue(texColor);
00247:              effect.Parameters["lightDir"].SetValue(lightDirection);
00248:  
00249:              // 描画処理
00250:              effect.Begin();
00251:              foreach(EffectPass pass in effect.CurrentTechnique.Passes)
00252:              {
00253:                  pass.Begin();
00254:                  graphics.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);
00255:                  pass.End();
00256:              }
00257:              effect.End();
00258:              
00259:              base.Draw(gameTime);
00260:          }
00261:      }
00262:  }

デフォルトだと背面カリングが有効になっており,テクスチャを回転させたときに見えなくなってしまうので239行目でカリングを使わないように設定しました。
シェーダの方はほとんどOpenGLと変わらないので,シェーダ側の処理についてはOpenGLのページのほうを参考にしてください。


 Download
本ソースコードおよびプログラムを使用したことによる如何なる損害も製作者は責任を負いません。
本ソースコードおよびプログラムは自己責任でご使用ください。
プログラムの作成にはMicrosoft Visual Studio 2005 SP1 Professional, XNA Game Studio 2.0を用いています。