チュートリアル 4: マテリアルとライトの使い方
チュートリアル 4: マテリアルとライトの使い方
Lights チュートリアル プロジェクトでは、ライトとマテリアルを追加して、よりリアルな Microsoft® Direct3D® オブジェクトを作成する。シーン内の各オブジェクトは、使うライトの位置およびタイプに基づいてライトが当てられる。マテリアルは、ポリゴンがアンビエント ライトとディフューズ ライトを反射する方法、ポリゴンのスペキュラ ハイライトの表現方法、ポリゴンが光を放射するかどうかを表す。
パス
ソースの場所 : (SDK ルート)\Samples\C#\Direct3D\Tutorials\Tutorial4
手順
注 Direct3D の初期化、Microsoft Windows® メッセージの処理、レンダリング、またはシャットダウンについては、「チュートリアル 1: デバイスの作成」を参照すること。
「チュートリアル 3: 行列の使い方」では、オブジェクトの頂点を 3D でトランスフォームした。このチュートリアルでは、マテリアルとライトの作成をチュートリアル 3 のコードに追加する。
深度ステンシルの初期化
このプロジェクトでは、次のコードで示すように、z バッファ (深度バッファ) と深度ステンシルを使えるようにする初期化手順も、チュートリアル 3 の初期化処理に追加する。深度ステンシルを使うと、レンダリングしたイメージの一部分をマスクで覆って表示されないようにすることができる。ここでは、最初に深度ステンシルを有効にした後、フォーマットを 16 ビット z バッファ深度に設定する。
public bool InitializeGraphics()
{
.
.
.
// Turn on a depth stencil
presentParams.EnableAutoDepthStencil = true;
// Set the stencil format
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
.
.
.
}
頂点バッファとレンダリング ステートの初期化
ライトを使うための条件の 1 つは、各サーフェイスが法線ベクトルを持っていることである。このプロジェクトでは、これまでのチュートリアルとは異なるカスタム頂点タイプである PositionNormal 構造体を使う。Direct3D は、この構造体に含まれる 3D 位置とサーフェイス法線を使って、内部的なライティング計算を行う。
public void OnCreateDevice(object sender, EventArgs e)
{
Device dev = (Device)sender;
// Now create the vertex buffer
vertexBuffer = new VertexBuffer(typeof(CustomVertex.PositionNormal),
100,
dev,
Usage.WriteOnly,
CustomVertex.PositionNormal.Format,
Pool.Default);
vertexBuffer.Created +=
new System.EventHandler(this.OnCreateVertexBuffer);
this.OnCreateVertexBuffer(vertexBuffer, null);
}
次に示すように、このサンプル コードでは、RenderStates プロパティを使って、シーン ジオメトリを効率よく格納できるように z バッファ (深度バッファ) の使用を有効にし、Direct3D ライティングも有効にしている。
public void OnResetDevice(object sender, EventArgs e)
{
Device dev = (Device)sender;
// Turn off culling, so the user sees the front and back of the triangle
device.RenderState.CullMode = Cull.None;
// Turn on the z-buffer
device.RenderState.ZBufferEnable = true;
device.RenderState.Lighting = true; // Make sure lighting is enabled
}
円柱オブジェクトの作成
デバイスの初期化 (上で示した OnCreateDevice) では、アプリケーションで定義した OnCreateVertexBuffer メソッドを呼び出して、円柱オブジェクトを作成している。次のサンプル コードで示すように、頂点バッファを初期化して円柱のポイントを格納した後、円柱上の各ポイントの位置と法線を頂点バッファにロードしている。
public void OnCreateVertexBuffer(object sender, EventArgs e)
{
VertexBuffer vb = (VertexBuffer)sender;
// Create and lock a vertex buffer (which will return the structures)
CustomVertex.PositionNormal[] verts =
(CustomVertex.PositionNormal[])vb.Lock(0,0);
for (int i = 0; i < 50; i++)
{
// Fill up the structs
float theta = (float)(2 * Math.PI * i) / 49;
verts[2 * i].SetPosition(new Vector3(
(float)Math.Sin(theta), -1, (float)Math.Cos(theta)));
verts[2 * i].SetNormal(new Vector3(
(float)Math.Sin(theta), 0, (float)Math.Cos(theta)));
verts[2 * i + 1].SetPosition(new Vector3(
(float)Math.Sin(theta), 1, (float)Math.Cos(theta)));
verts[2 * i + 1].SetNormal(new Vector3(
(float)Math.Sin(theta), 0, (float)Math.Cos(theta)));
}
// Unlock (and copy) the data
vb.Unlock();
}
チュートリアル 3 で示したように、SetupMatrices プライベート メソッドのワールド トランスフォーム行列を使って、円柱を回転させる。
マテリアルの作成
マテリアルは、ジオメトリ オブジェクトにライトが当たったときに、ジオメトリ オブジェクトのサーフェイスから反射される色を定義する。次のサンプル コードでは、Material 構造体を使って、白色のマテリアルを作成している。このマテリアルのディフューズ色プロパティとアンビエント色プロパティは、白色に設定される。この呼び出しを行った後、色プロパティに別の値を設定するまでは、このマテリアルを使って各プリミティブがレンダリングされる。
private void SetupLights()
{
System.Drawing.Color col = System.Drawing.Color.White;
// Set up a material. The material here just has the diffuse and ambient
// colors set to white. Note that only one material can be used at a time.
Direct3D.Material mtrl = new Direct3D.Material();
device.Material = mtrl;
.
.
.
}
ライトの作成
Direct3D で利用できるライトには、ポイント ライト、ディレクショナル ライト、スポットライトの 3 種類がある。このチュートリアル プロジェクトでは、光が 1 方向を照らすディレクショナル ライトを作成し、ライトの方向を周期的に変化させる。次のサンプル コードでは、Light オブジェクトを使って、暗い青緑色のディレクショナル ライトを作成している。シーン内のすべてのオブジェクトは、低レベルのモノクロ (グレー) のアンビエント ライトによっても照らされる。
private void SetupLights()
{
.
.
.
// Set up a colored directional light, with an oscillating direction.
// Note that many lights may be active at a time (but each one slows down
// the rendering of the scene). However, here just one is used.
device.Lights[0].Type = LightType.Directional;
device.Lights[0].Diffuse = System.Drawing.Color.DarkTurquoise;
device.Lights[0].Direction = new Vector3(
(float)Math.Cos(Environment.TickCount / 250.0f),
1.0f,
(float)Math.Sin(Environment.TickCount / 250.0f));
device.Lights[0].Commit(); // Let Direct3D know about the light
device.Lights[0].Enabled = true; // Turn it on
// Finally, turn on some ambient light.
// Ambient light is light that scatters and lights all objects evenly.
device.RenderState.Ambient = System.Drawing.Color.FromArgb(0x202020);
© 2002 Microsoft Corporation. All rights reserved. Terms of use.