原文はこちら。この翻訳は間違いが多いかもしれないから気をつけてください。
このサンプルでは、BasicEffectクラスのインスタンスを作成して初期化する方法、BasicEffectに描画させたい頂点バッファを初期化する方法、エフェクトを適用する方法およびジオメトリ(何らかの形状)を描画する方法を説明する。
Note:
このサンプルでは、BasicEffectクラスが作成したエフェクトを適用する方法をやる。自分でエフェクトを記述したい人はEffectクラスを使ってくれ。Effectクラスに興味があるならHow to: Create and Apply Custom Effects?を読んでくれ。
BasicEffectの使い方
1. BasicEffectクラスを使うには、ワールド、ビュー、プロジェクションの三つの行列、頂点バッファ、頂点のタイプの宣言、そしてBasicEffectクラスのインスタンスが必要だ。だからこれらのオブジェクトを、ゲームのプログラムの最初のほうで宣言する。
Matrix worldMatrix; Matrix viewMatrix; Matrix projectionMatrix; VertexPositionNormalTexture[] cubeVertices; VertexDeclaration basicEffectVertexDeclaration; VertexBuffer vertexBuffer; BasicEffect basicEffect;
2. ワールド、ビュー、プロジェクションの三つの行列を初期化する。このサンプルでは、ジオメトリをx軸とy軸に沿って22.5度回転させるワールド行列作成する。ビュー行列はカメラを(0, 0, 5)の位置に置いて原点の方を見ているような"ルックアット行列(look-at matrix)"だ。プロジェクション行列は、画角45度でアスペクト比はウィンドウと同じ、前方クリップ面と後方クリップ面を設定する、そんな感じだ。
float tilt = MathHelper.ToRadians( 22.5f ); // 22.5度
//立方体をX軸とY軸を中心に回転させるワールド行列。
worldMatrix = Matrix.CreateRotationX(tilt) *
Matrix.CreateRotationY(tilt);
viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), Vector3.Zero,
Vector3.Up);
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians( 45 ), // 45 度
(float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height,
1.0f, 100.0f);
3. BasicEffectを必要に応じた値で初期化
basicEffect = new BasicEffect(graphics.GraphicsDevice, null); basicEffect.Alpha = 1.0f; basicEffect.DiffuseColor = new Vector3(1.0f, 0.0f, 1.0f); basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f); basicEffect.SpecularPower = 5.0f; basicEffect.AmbientLightColor = new Vector3(0.75f, 0.75f, 0.75f); basicEffect.DirectionalLight0.Enabled = true; basicEffect.DirectionalLight0.DiffuseColor = Vector3.One; basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)); basicEffect.DirectionalLight0.SpecularColor = Vector3.One; basicEffect.DirectionalLight1.Enabled = true; basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0.5f, 0.5f, 0.5f); basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)); basicEffect.DirectionalLight1.SpecularColor = new Vector3(0.5f, 0.5f, 0.5f); basicEffect.LightingEnabled = true; basicEffect.World = worldMatrix; basicEffect.View = viewMatrix; basicEffect.Projection = projectionMatrix;
4. BasicEffectでは、有効になってるエフェクトに応じた適切な頂点の型を使う必要がある。
- ライトが有効になってるなら、頂点は法線ベクトルを持たなくてはいけない
- 頂点カラーが有効になってるなら、頂点には色がついてなくてはいけない
- テクスチャが有効なら、頂点にはテクスチャ座標が設定されていなくてはいけない
VertexPositionNormalTexture型の頂点で作られた立方体のコードを下に示そう。
cubeVertices = new VertexPositionNormalTexture[36];
Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);
Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);
Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f);
Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f);
Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f);
Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f);
Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f);
Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f);
Vector2 textureTopLeft = new Vector2(0.0f, 0.0f);
Vector2 textureTopRight = new Vector2(1.0f, 0.0f);
Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f);
Vector2 textureBottomRight = new Vector2(1.0f, 1.0f);
Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f);
Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f);
Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f);
Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f);
Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f);
Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f);
// 前面
cubeVertices[0] =
new VertexPositionNormalTexture(
topLeftFront, frontNormal, textureTopLeft);
cubeVertices[1] =
new VertexPositionNormalTexture(
bottomLeftFront, frontNormal, textureBottomLeft);
cubeVertices[2] =
new VertexPositionNormalTexture(
topRightFront, frontNormal, textureTopRight);
cubeVertices[3] =
new VertexPositionNormalTexture(
bottomLeftFront, frontNormal, textureBottomLeft);
cubeVertices[4] =
new VertexPositionNormalTexture(
bottomRightFront, frontNormal, textureBottomRight);
cubeVertices[5] =
new VertexPositionNormalTexture(
topRightFront, frontNormal, textureTopRight);
// 後面
cubeVertices[6] =
new VertexPositionNormalTexture(
topLeftBack, backNormal, textureTopRight);
cubeVertices[7] =
new VertexPositionNormalTexture(
topRightBack, backNormal, textureTopLeft);
cubeVertices[8] =
new VertexPositionNormalTexture(
bottomLeftBack, backNormal, textureBottomRight);
cubeVertices[9] =
new VertexPositionNormalTexture(
bottomLeftBack, backNormal, textureBottomRight);
cubeVertices[10] =
new VertexPositionNormalTexture(
topRightBack, backNormal, textureTopLeft);
cubeVertices[11] =
new VertexPositionNormalTexture(
bottomRightBack, backNormal, textureBottomLeft);
// 上面
cubeVertices[12] =
new VertexPositionNormalTexture(
topLeftFront, topNormal, textureBottomLeft);
cubeVertices[13] =
new VertexPositionNormalTexture(
topRightBack, topNormal, textureTopRight);
cubeVertices[14] =
new VertexPositionNormalTexture(
topLeftBack, topNormal, textureTopLeft);
cubeVertices[15] =
new VertexPositionNormalTexture(
topLeftFront, topNormal, textureBottomLeft);
cubeVertices[16] =
new VertexPositionNormalTexture(
topRightFront, topNormal, textureBottomRight);
cubeVertices[17] =
new VertexPositionNormalTexture(
topRightBack, topNormal, textureTopRight);
//下面
cubeVertices[18] =
new VertexPositionNormalTexture(
bottomLeftFront, bottomNormal, textureTopLeft);
cubeVertices[19] =
new VertexPositionNormalTexture(
bottomLeftBack, bottomNormal, textureBottomLeft);
cubeVertices[20] =
new VertexPositionNormalTexture(
bottomRightBack, bottomNormal, textureBottomRight);
cubeVertices[21] =
new VertexPositionNormalTexture(
bottomLeftFront, bottomNormal, textureTopLeft);
cubeVertices[22] =
new VertexPositionNormalTexture(
bottomRightBack, bottomNormal, textureBottomRight);
cubeVertices[23] =
new VertexPositionNormalTexture(
bottomRightFront, bottomNormal, textureTopRight);
//左面
cubeVertices[24] =
new VertexPositionNormalTexture(
topLeftFront, leftNormal, textureTopRight);
cubeVertices[25] =
new VertexPositionNormalTexture(
bottomLeftBack, leftNormal, textureBottomLeft);
cubeVertices[26] =
new VertexPositionNormalTexture(
bottomLeftFront, leftNormal, textureBottomRight);
cubeVertices[27] =
new VertexPositionNormalTexture(
topLeftBack, leftNormal, textureTopLeft);
cubeVertices[28] =
new VertexPositionNormalTexture(
bottomLeftBack, leftNormal, textureBottomLeft);
cubeVertices[29] =
new VertexPositionNormalTexture(
topLeftFront, leftNormal, textureTopRight);
// 右面
cubeVertices[30] =
new VertexPositionNormalTexture(
topRightFront, rightNormal, textureTopLeft);
cubeVertices[31] =
new VertexPositionNormalTexture(
bottomRightFront, rightNormal, textureBottomLeft);
cubeVertices[32] =
new VertexPositionNormalTexture(
bottomRightBack, rightNormal, textureBottomRight);
cubeVertices[33] =
new VertexPositionNormalTexture(
topRightBack, rightNormal, textureTopRight);
cubeVertices[34] =
new VertexPositionNormalTexture(
topRightFront, rightNormal, textureTopLeft);
cubeVertices[35] =
new VertexPositionNormalTexture(
bottomRightBack, rightNormal, textureBottomRight);
vertexBuffer = new VertexBuffer(
graphics.GraphicsDevice,
VertexPositionNormalTexture.SizeInBytes * cubeVertices.Length,
ResourceUsage.None,
ResourceManagementMode.Automatic
);
vertexBuffer.SetData<VertexPositionNormalTexture>(cubeVertices);
5. VertexPositionNormalTextureタイプのVertexDeclartionクラスを作成する。このVertexDeclartionは次のステップでやる描画のループでつかう。
basicEffectVertexDeclaration = new VertexDeclaration(
graphics.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
6. Effect.Begin関数を実行し、BasicEffectを適用する。EffectPass.BeginとEffectPass.Endの間にジオメトリを描画する。Effect.Endを呼ぶとテクニックが終わる。
graphics.GraphicsDevice.VertexDeclaration =
basicEffectVertexDeclaration;
graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
//このコードはdeviceのBeginSceneとEndSceneの間にないとだめ
basicEffect.Begin();
foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes)
{
pass.Begin();
graphics.GraphicsDevice.DrawPrimitives(
PrimitiveType.TriangleList,
0,
12
);
pass.End();
}
basicEffect.End();
完全なコード
using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using Microsoft.Xna.Framework.Content; public class Game1 : Microsoft.Xna.Framework.Game { GraphicsDeviceManager graphics; ContentManager content; Matrix worldMatrix; Matrix viewMatrix; Matrix projectionMatrix; VertexPositionNormalTexture[] cubeVertices; VertexDeclaration basicEffectVertexDeclaration; VertexBuffer vertexBuffer; BasicEffect basicEffect; public Game1() { graphics = new GraphicsDeviceManager(this); content = new ContentManager(Services); } protected override void Initialize() { base.Initialize(); } protected override void LoadGraphicsContent(bool loadAllContent) { InitializeTransform(); if (loadAllContent) { InitializeEffect(); InitializeCube(); } } private void InitializeTransform() { float tilt = MathHelper.ToRadians( 22.5f ); //22.5度 //立方体をX軸とY軸を中心に回転させるワールド行列。 worldMatrix = Matrix.CreateRotationX(tilt) * Matrix.CreateRotationY(tilt); viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 5), Vector3.Zero, Vector3.Up); projectionMatrix = Matrix.CreatePerspectiveFieldOfView( MathHelper.ToRadians( 45 ), // 45 度 (float)graphics.GraphicsDevice.Viewport.Width / (float)graphics.GraphicsDevice.Viewport.Height, 1.0f, 100.0f); } private void InitializeEffect() { basicEffectVertexDeclaration = new VertexDeclaration( graphics.GraphicsDevice, VertexPositionNormalTexture.VertexElements); basicEffect = new BasicEffect(graphics.GraphicsDevice, null); basicEffect.Alpha = 1.0f; basicEffect.DiffuseColor = new Vector3(1.0f, 0.0f, 1.0f); basicEffect.SpecularColor = new Vector3(0.25f, 0.25f, 0.25f); basicEffect.SpecularPower = 5.0f; basicEffect.AmbientLightColor = new Vector3(0.75f, 0.75f, 0.75f); basicEffect.DirectionalLight0.Enabled = true; basicEffect.DirectionalLight0.DiffuseColor = Vector3.One; basicEffect.DirectionalLight0.Direction = Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)); basicEffect.DirectionalLight0.SpecularColor = Vector3.One; basicEffect.DirectionalLight1.Enabled = true; basicEffect.DirectionalLight1.DiffuseColor = new Vector3(0.5f, 0.5f, 0.5f); basicEffect.DirectionalLight1.Direction = Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)); basicEffect.DirectionalLight1.SpecularColor = new Vector3(0.5f, 0.5f, 0.5f); basicEffect.LightingEnabled = true; basicEffect.World = worldMatrix; basicEffect.View = viewMatrix; basicEffect.Projection = projectionMatrix; } private void InitializeCube() { cubeVertices = new VertexPositionNormalTexture[36]; Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f); Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f); Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f); Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f); Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f); Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f); Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f); Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f); Vector2 textureTopLeft = new Vector2(0.0f, 0.0f); Vector2 textureTopRight = new Vector2(1.0f, 0.0f); Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f); Vector2 textureBottomRight = new Vector2(1.0f, 1.0f); Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f); Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f); Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f); Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f); Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f); Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f); // 前面 cubeVertices[0] = new VertexPositionNormalTexture( topLeftFront, frontNormal, textureTopLeft); cubeVertices[1] = new VertexPositionNormalTexture( bottomLeftFront, frontNormal, textureBottomLeft); cubeVertices[2] = new VertexPositionNormalTexture( topRightFront, frontNormal, textureTopRight); cubeVertices[3] = new VertexPositionNormalTexture( bottomLeftFront, frontNormal, textureBottomLeft); cubeVertices[4] = new VertexPositionNormalTexture( bottomRightFront, frontNormal, textureBottomRight); cubeVertices[5] = new VertexPositionNormalTexture( topRightFront, frontNormal, textureTopRight); // 後面 cubeVertices[6] = new VertexPositionNormalTexture( topLeftBack, backNormal, textureTopRight); cubeVertices[7] = new VertexPositionNormalTexture( topRightBack, backNormal, textureTopLeft); cubeVertices[8] = new VertexPositionNormalTexture( bottomLeftBack, backNormal, textureBottomRight); cubeVertices[9] = new VertexPositionNormalTexture( bottomLeftBack, backNormal, textureBottomRight); cubeVertices[10] = new VertexPositionNormalTexture( topRightBack, backNormal, textureTopLeft); cubeVertices[11] = new VertexPositionNormalTexture( bottomRightBack, backNormal, textureBottomLeft); // 上面 cubeVertices[12] = new VertexPositionNormalTexture( topLeftFront, topNormal, textureBottomLeft); cubeVertices[13] = new VertexPositionNormalTexture( topRightBack, topNormal, textureTopRight); cubeVertices[14] = new VertexPositionNormalTexture( topLeftBack, topNormal, textureTopLeft); cubeVertices[15] = new VertexPositionNormalTexture( topLeftFront, topNormal, textureBottomLeft); cubeVertices[16] = new VertexPositionNormalTexture( topRightFront, topNormal, textureBottomRight); cubeVertices[17] = new VertexPositionNormalTexture( topRightBack, topNormal, textureTopRight); // 下面 cubeVertices[18] = new VertexPositionNormalTexture( bottomLeftFront, bottomNormal, textureTopLeft); cubeVertices[19] = new VertexPositionNormalTexture( bottomLeftBack, bottomNormal, textureBottomLeft); cubeVertices[20] = new VertexPositionNormalTexture( bottomRightBack, bottomNormal, textureBottomRight); cubeVertices[21] = new VertexPositionNormalTexture( bottomLeftFront, bottomNormal, textureTopLeft); cubeVertices[22] = new VertexPositionNormalTexture( bottomRightBack, bottomNormal, textureBottomRight); cubeVertices[23] = new VertexPositionNormalTexture( bottomRightFront, bottomNormal, textureTopRight); // 左面 cubeVertices[24] = new VertexPositionNormalTexture( topLeftFront, leftNormal, textureTopRight); cubeVertices[25] = new VertexPositionNormalTexture( bottomLeftBack, leftNormal, textureBottomLeft); cubeVertices[26] = new VertexPositionNormalTexture( bottomLeftFront, leftNormal, textureBottomRight); cubeVertices[27] = new VertexPositionNormalTexture( topLeftBack, leftNormal, textureTopLeft); cubeVertices[28] = new VertexPositionNormalTexture( bottomLeftBack, leftNormal, textureBottomLeft); cubeVertices[29] = new VertexPositionNormalTexture( topLeftFront, leftNormal, textureTopRight); //右面 cubeVertices[30] = new VertexPositionNormalTexture( topRightFront, rightNormal, textureTopLeft); cubeVertices[31] = new VertexPositionNormalTexture( bottomRightFront, rightNormal, textureBottomLeft); cubeVertices[32] = new VertexPositionNormalTexture( bottomRightBack, rightNormal, textureBottomRight); cubeVertices[33] = new VertexPositionNormalTexture( topRightBack, rightNormal, textureTopRight); cubeVertices[34] = new VertexPositionNormalTexture( topRightFront, rightNormal, textureTopLeft); cubeVertices[35] = new VertexPositionNormalTexture( bottomRightBack, rightNormal, textureBottomRight); vertexBuffer = new VertexBuffer( graphics.GraphicsDevice, VertexPositionNormalTexture.SizeInBytes * cubeVertices.Length, ResourceUsage.None, ResourceManagementMode.Automatic ); vertexBuffer.SetData<VertexPositionNormalTexture>(cubeVertices); } protected override void UnloadGraphicsContent(bool unloadAllContent) { if (unloadAllContent == true) { content.Unload(); } } protected override void Update(GameTime gameTime) { // Allows the default game to exit on Xbox 360 and Windows if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed) this.Exit(); base.Update(gameTime); } protected override void Draw(GameTime gameTime) { graphics.GraphicsDevice.Clear(Color.CornflowerBlue); graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace; graphics.GraphicsDevice.VertexDeclaration = basicEffectVertexDeclaration; graphics.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes); //このコードはdeviceのBeginSceneとEndSceneの間にないとだめ basicEffect.Begin(); foreach (EffectPass pass in basicEffect.CurrentTechnique.Passes) { pass.Begin(); graphics.GraphicsDevice.DrawPrimitives( PrimitiveType.TriangleList, 0, 12 ); pass.End(); } basicEffect.End(); base.Draw(gameTime); } }
affillogo.gif