「VCS/XnaBlock」の編集履歴(バックアップ)一覧はこちら

VCS/XnaBlock」(2012/12/04 (火) 17:18:57) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C# 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Windows Game (4.0)| |プロジェクト名|XnaBlock| Block Builder(仮) Texture4.png #ref(Texture4_2.png) Palette16.png #ref(Palette16.png) Game1.cs #highlight(c#){{ // #1 using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace XnaBlock { class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch sprite; SpriteFont font; Effect effect; Texture2D texture; // fps DateTime prevTime; int draw = 0; int fps = 0; const int gridSize = 100; const int blockMax = 20000; short blockNum = 0; short[] grid; VertexBuffer instanceBuffer; VertexBuffer geometryBuffer; IndexBuffer indexBuffer; VertexDeclaration instanceVertexDeclaration; VertexBufferBinding[] bindings; Matrix projection; // カメラ Vector3 camPos = new Vector3(50.5f, 1.5f, 50.5f); int camLat = 0; int camLong = 225; readonly int[] dirX = { 1, 1, 0, -1, -1, -1, 0, 1, 1 }; readonly int[] dirZ = { 0, 1, 1, 1, 0, -1, -1, -1, 0 }; struct InstanceInfo { public Matrix World; public Vector2 AtlasCoordinate; } struct Position { public int X; public int Y; public int Z; public Position(int x, int y, int z) { X = x; Y = y; Z = z; } } public Game1() { graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void Initialize() { sprite = new SpriteBatch(GraphicsDevice); prevTime = DateTime.Now; base.Initialize(); } protected override void LoadContent() { // ソリューション エクスプローラーの(Content)に追加しておく font = Content.Load<SpriteFont>("SpriteFont1"); // 新しい項目:Sprite Font effect = Content.Load<Effect>("HardwareInstancing"); // 新しい項目:Effect File (.fx) texture = Content.Load<Texture2D>("Palette16"); // 既存の項目:Palette16.png GenerateGeometryBuffers(0.5f); GenerateInstanceVertexDeclaration(); GenerateInstanceInformation(); bindings = new VertexBufferBinding[2]; bindings[0] = new VertexBufferBinding(geometryBuffer, 0); bindings[1] = new VertexBufferBinding(instanceBuffer, 0, 1); projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 2000); effect.CurrentTechnique = effect.Techniques["Instancing"]; effect.Parameters["cubeTexture"].SetValue(texture); base.LoadContent(); } void GenerateGeometryBuffers(float size) { VertexPositionTexture[] vertices = new VertexPositionTexture[24]; for (int n = 0; n < 4; n++) { float u = size * ((n & 1) * 2 - 1); float v = size * ((n & 2) - 1); vertices[0 + n].Position = new Vector3(u, size, v); vertices[4 + n].Position = new Vector3(u, -size, -v); vertices[8 + n].Position = new Vector3(-size, -v, u); vertices[12 + n].Position = new Vector3(u, -v, size); vertices[16 + n].Position = new Vector3(size, -v, -u); vertices[20 + n].Position = new Vector3(-u, -v, -size); } for (int n = 0; n < 24; n++) { vertices[n].TextureCoordinate = new Vector2(n & 1, (n >> 1) & 1); } geometryBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 24, BufferUsage.WriteOnly); geometryBuffer.SetData(vertices); int[] indices = new int[36]; for (int n = 0; n < 6; n++) { int n6 = n * 6; int n4 = n * 4; indices[n6 + 0] = n4 + 0; indices[n6 + 1] = n4 + 1; indices[n6 + 2] = n4 + 2; indices[n6 + 3] = n4 + 1; indices[n6 + 4] = n4 + 3; indices[n6 + 5] = n4 + 2; } indexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), 36, BufferUsage.WriteOnly); indexBuffer.SetData(indices); } void GenerateInstanceVertexDeclaration() { VertexElement[] elements = new VertexElement[5]; for (int n = 0; n < 4; n++) // Matrix = Vector4 * 4 { elements[n] = new VertexElement(sizeof(float) * 4 * n, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, n + 1); } elements[4] = new VertexElement(sizeof(float) * 16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 5); instanceVertexDeclaration = new VertexDeclaration(elements); } void GenerateInstanceInformation() { instanceBuffer = new VertexBuffer(GraphicsDevice, instanceVertexDeclaration, blockMax, BufferUsage.None); // 読み込みもする grid = new short[gridSize * gridSize * gridSize]; // 地面 for (int z = 0; z < gridSize; z++) { for (int x = 0; x < gridSize; x++) { SetNewBlock(x, 0, z, 4); } } // 正8面体 for (int y = -10; y <= 10; y++) { int x1 = 10 - Math.Abs(y); for (int x = -x1; x <= x1; x++) { int z1 = x1 - Math.Abs(x); int z2 = (z1 == 0) ? 1 : z1 * 2; for (int z = -z1; z <= z1; z += z2) { SetNewBlock(10 + x, 20 + y, 30 + z, 3); } } } // 太陽 for (int y = -10; y <= 10; y++) { for (int x = -10; x <= 10; x++) { for (int z = -10; z <= 10; z++) { int r = (x * x) + (y * y) + (z * z); if (90 < r && r < 111) // 9.5^2 < r^2 < 10.5^2 { SetNewBlock(30 + x, 20 + y, 10 + z, 2); } } } } } int GridIndex(int x, int y, int z) { return (y * gridSize + x) * gridSize + z; } void SetNewBlock(int x, int y, int z, byte color) { InstanceInfo[] ins = new InstanceInfo[1]; // stride = 4*(16+2) ins[0].World = Matrix.CreateTranslation(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f)); ins[0].AtlasCoordinate = new Vector2((color & 3) / 4.0f, (color >> 2) / 4.0f); instanceBuffer.SetData<InstanceInfo>(blockNum++ * 72, ins, 0, 1, 72); grid[GridIndex(x, y, z)] = blockNum; } short GetGrid(int x, int y, int z) { if (x < 0 || gridSize <= x || y < 0 || gridSize <= y || z < 0 || gridSize <= z) return Int16.MinValue; return grid[GridIndex(x, y, z)]; } Position GetForwardPos() { Position pos; int dir = (camLong + 22) / 45; pos.X = (int)camPos.X + dirX[dir]; pos.Y = (int)camPos.Y - 1; pos.Z = (int)camPos.Z + dirZ[dir]; return pos; } void SetGrid(Position pos, float u, float v, short insIndex, short gridIndex) { InstanceInfo[] ins = new InstanceInfo[1]; int start = (insIndex - 1) * 72; instanceBuffer.GetData<InstanceInfo>(start, ins, 0, 1, 72); ins[0].AtlasCoordinate = new Vector2(u, v); instanceBuffer.SetData<InstanceInfo>(start, ins, 0, 1, 72); grid[GridIndex(pos.X, pos.Y, pos.Z)] = gridIndex; } void SetBlock(byte color) { Position pos = GetForwardPos(); short index = GetGrid(pos.X, pos.Y, pos.Z); if (0 < index || index == Int16.MinValue) return; if (index == 0) { SetNewBlock(pos.X, pos.Y, pos.Z, color); } else { // 再利用 SetGrid(pos, (color & 3) / 4.0f, (color >> 2) / 4.0f, (short)-index, index); } } void DelBlock() { Position pos = GetForwardPos(); short index = GetGrid(pos.X, pos.Y, pos.Z); if (index <= 0) return; // 論理削除 SetGrid(pos, 2.0f, 0, index, (short)-index); } protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); if (state[Keys.Escape] == KeyState.Down) Exit(); if (state[Keys.W] == KeyState.Down) MoveXZ(0); if (state[Keys.S] == KeyState.Down) MoveXZ(180); if (state[Keys.A] == KeyState.Down) MoveXZ(-90); if (state[Keys.D] == KeyState.Down) MoveXZ(90); if (state[Keys.Up] == KeyState.Down) camLat++; if (state[Keys.Down] == KeyState.Down) camLat--; if (state[Keys.Left] == KeyState.Down) camLong = (camLong + 359) % 360; if (state[Keys.Right] == KeyState.Down) camLong = (camLong + 1) % 360; if (state[Keys.PageUp] == KeyState.Down) MoveY(0.1f); if (state[Keys.PageDown] == KeyState.Down) MoveY(-0.1f); if (state[Keys.NumPad0] == KeyState.Down) DelBlock(); if (state[Keys.NumPad1] == KeyState.Down) SetBlock(1); if (state[Keys.NumPad2] == KeyState.Down) SetBlock(2); if (state[Keys.NumPad3] == KeyState.Down) SetBlock(3); if (state[Keys.NumPad4] == KeyState.Down) SetBlock(4); if (state[Keys.NumPad5] == KeyState.Down) SetBlock(5); if (state[Keys.NumPad6] == KeyState.Down) SetBlock(6); if (state[Keys.NumPad7] == KeyState.Down) SetBlock(7); if (state[Keys.NumPad8] == KeyState.Down) SetBlock(8); base.Update(gameTime); } void MoveXZ(int degree) { float rad = MathHelper.ToRadians(camLong + degree); float x = camPos.X + (float)Math.Cos(rad) * 0.1f; float z = camPos.Z + (float)Math.Sin(rad) * 0.1f; if (GetGrid((int)x, (int)camPos.Y, (int)z) <= 0) { camPos.X = x; camPos.Z = z; } } void MoveY(float dy) { float y = camPos.Y + dy; if (GetGrid((int)camPos.X, (int)y, (int)camPos.Z) <= 0) { camPos.Y = y; } } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); GraphicsDevice.DepthStencilState = DepthStencilState.Default; float rad = MathHelper.ToRadians(camLat); float y = (float)Math.Sin(rad) + camPos.Y; float r = (float)Math.Cos(rad); rad = MathHelper.ToRadians(camLong); float x = camPos.X + (float)Math.Cos(rad) * r; float z = camPos.Z + (float)Math.Sin(rad) * r; Matrix view = Matrix.CreateLookAt(camPos, new Vector3(x, y, z), Vector3.Up); GraphicsDevice.Indices = indexBuffer; effect.Parameters["WVP"].SetValue(view * projection); effect.Parameters["totalTime"].SetValue((float)gameTime.TotalGameTime.TotalMilliseconds); effect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SetVertexBuffers(bindings); GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, 24, 0, 12, blockNum); // フレームレート draw++; DateTime now = DateTime.Now; TimeSpan t = now - prevTime; if (t.TotalMilliseconds >= 1000) { fps = draw; draw = 0; prevTime = now; } sprite.Begin(); string text = "fps=" + fps + " lat=" + camLat + " long=" + camLong + " block=" + blockNum; sprite.DrawString(font, text, new Vector2(0, 0), Color.White); text = string.Format("x={0:f1} y={1:f1} z={2:f1}", camPos.X, camPos.Y, camPos.Z); sprite.DrawString(font, text, new Vector2(0, 20), Color.White); sprite.End(); base.Draw(gameTime); } } } }} HardwareInstancing.fx #highlight{{ /* #1 Effect File プロジェクトのプロパティ [XNA Game Studio]タブ Use HiDef to access the complete API */ float4x4 WVP; texture cubeTexture; float totalTime; sampler TextureSampler = sampler_state { texture = <cubeTexture>; mipfilter = LINEAR; minfilter = LINEAR; magfilter = LINEAR; }; struct InstancingVSinput { float4 Position : POSITION0; float2 TexCoord : TEXCOORD0; }; struct InstancingVSoutput { float4 Position : POSITION0; float2 TexCoord : TEXCOORD0; }; InstancingVSoutput InstancingVS( InstancingVSinput input, float4x4 instanceTransform : TEXCOORD1, float2 atlasCoord : TEXCOORD5) { InstancingVSoutput output; float4 pos = input.Position; pos = mul(pos, transpose(instanceTransform)); // pos.y = (pos.y + 0.01f * totalTime * atlasCoord.x) % 100.0f; pos = mul(pos, WVP); output.Position = pos; output.TexCoord = float2( atlasCoord.x + (input.TexCoord.x / 4.0f), atlasCoord.y + (input.TexCoord.y / 4.0f)); return output; } float4 InstancingPS(InstancingVSoutput input) : COLOR0 { if (2.0f <= input.TexCoord.x) discard; return tex2D(TextureSampler, input.TexCoord); } technique Instancing { pass Pass0 { VertexShader = compile vs_3_0 InstancingVS(); PixelShader = compile ps_3_0 InstancingPS(); } } }}
|開発環境|Microsoft Visual C# 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Windows Game (4.0)| |プロジェクト名|XnaBlock| Block Builder(仮) Texture4.png #ref(Texture4_2.png) Palette16.png #ref(Palette16.png) Game1.cs #highlight(c#){{ // #1 using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; namespace XnaBlock { class Game1 : Game { GraphicsDeviceManager graphics; SpriteBatch sprite; SpriteFont font; Effect effect; Texture2D texture; // fps DateTime prevTime; int draw = 0; int fps = 0; const int gridSize = 100; const int blockMax = 20000; short blockNum = 0; short[] grid; VertexBuffer instanceBuffer; VertexBuffer geometryBuffer; IndexBuffer indexBuffer; VertexDeclaration instanceVertexDeclaration; VertexBufferBinding[] bindings; Matrix projection; // カメラ Vector3 camPos = new Vector3(50.5f, 1.5f, 50.5f); int camLat = 0; int camLong = 225; readonly int[] dirX = { 1, 1, 0, -1, -1, -1, 0, 1, 1 }; readonly int[] dirZ = { 0, 1, 1, 1, 0, -1, -1, -1, 0 }; struct InstanceInfo { public Matrix World; public Vector2 AtlasCoordinate; } struct Position { public int X; public int Y; public int Z; public Position(int x, int y, int z) { X = x; Y = y; Z = z; } } public Game1() { graphics = new GraphicsDeviceManager(this); graphics.PreferredBackBufferWidth = 1280; graphics.PreferredBackBufferHeight = 720; Content.RootDirectory = "Content"; IsMouseVisible = true; } protected override void Initialize() { sprite = new SpriteBatch(GraphicsDevice); prevTime = DateTime.Now; base.Initialize(); } protected override void LoadContent() { // ソリューション エクスプローラーの(Content)に追加しておく font = Content.Load<SpriteFont>("SpriteFont1"); // 新しい項目:Sprite Font effect = Content.Load<Effect>("HardwareInstancing"); // 新しい項目:Effect File (.fx) texture = Content.Load<Texture2D>("Palette16"); // 既存の項目:Palette16.png GenerateGeometryBuffers(0.5f); GenerateInstanceVertexDeclaration(); GenerateInstanceInformation(); bindings = new VertexBufferBinding[2]; bindings[0] = new VertexBufferBinding(geometryBuffer, 0); bindings[1] = new VertexBufferBinding(instanceBuffer, 0, 1); projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 2000); effect.CurrentTechnique = effect.Techniques["Instancing"]; effect.Parameters["cubeTexture"].SetValue(texture); base.LoadContent(); } void GenerateGeometryBuffers(float size) { VertexPositionTexture[] vertices = new VertexPositionTexture[24]; for (int n = 0; n < 4; n++) { float u = size * ((n & 1) * 2 - 1); float v = size * ((n & 2) - 1); vertices[0 + n].Position = new Vector3(u, size, v); vertices[4 + n].Position = new Vector3(u, -size, -v); vertices[8 + n].Position = new Vector3(-size, -v, u); vertices[12 + n].Position = new Vector3(u, -v, size); vertices[16 + n].Position = new Vector3(size, -v, -u); vertices[20 + n].Position = new Vector3(-u, -v, -size); } for (int n = 0; n < 24; n++) { vertices[n].TextureCoordinate = new Vector2(n & 1, (n >> 1) & 1); } geometryBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionTexture), 24, BufferUsage.WriteOnly); geometryBuffer.SetData(vertices); int[] indices = new int[36]; for (int n = 0; n < 6; n++) { int n6 = n * 6; int n4 = n * 4; indices[n6 + 0] = n4 + 0; indices[n6 + 1] = n4 + 1; indices[n6 + 2] = n4 + 2; indices[n6 + 3] = n4 + 1; indices[n6 + 4] = n4 + 3; indices[n6 + 5] = n4 + 2; } indexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), 36, BufferUsage.WriteOnly); indexBuffer.SetData(indices); } void GenerateInstanceVertexDeclaration() { VertexElement[] elements = new VertexElement[5]; for (int n = 0; n < 4; n++) // Matrix = Vector4 * 4 { elements[n] = new VertexElement(sizeof(float) * 4 * n, VertexElementFormat.Vector4, VertexElementUsage.TextureCoordinate, n + 1); } elements[4] = new VertexElement(sizeof(float) * 16, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 5); instanceVertexDeclaration = new VertexDeclaration(elements); } void GenerateInstanceInformation() { instanceBuffer = new VertexBuffer(GraphicsDevice, instanceVertexDeclaration, blockMax, BufferUsage.None); // 読み込みもする grid = new short[gridSize * gridSize * gridSize]; // 地面 for (int z = 0; z < gridSize; z++) { for (int x = 0; x < gridSize; x++) { SetNewBlock(x, 0, z, 4); } } // 正8面体 for (int y = -10; y <= 10; y++) { int x1 = 10 - Math.Abs(y); for (int x = -x1; x <= x1; x++) { int z1 = x1 - Math.Abs(x); int z2 = (z1 == 0) ? 1 : z1 * 2; for (int z = -z1; z <= z1; z += z2) { SetNewBlock(10 + x, 20 + y, 30 + z, 3); } } } // 太陽 for (int y = -10; y <= 10; y++) { for (int x = -10; x <= 10; x++) { for (int z = -10; z <= 10; z++) { int r = (x * x) + (y * y) + (z * z); if (90 < r && r < 111) // 9.5^2 < r^2 < 10.5^2 { SetNewBlock(30 + x, 20 + y, 10 + z, 2); } } } } } int GridIndex(int x, int y, int z) { return (y * gridSize + x) * gridSize + z; } void SetNewBlock(int x, int y, int z, byte color) { InstanceInfo[] ins = new InstanceInfo[1]; // stride = 4*(16+2) ins[0].World = Matrix.CreateTranslation(new Vector3(x + 0.5f, y + 0.5f, z + 0.5f)); ins[0].AtlasCoordinate = new Vector2((color & 3) / 4.0f, (color >> 2) / 4.0f); instanceBuffer.SetData<InstanceInfo>(blockNum++ * 72, ins, 0, 1, 72); grid[GridIndex(x, y, z)] = blockNum; } short GetGrid(int x, int y, int z) { if (x < 0 || gridSize <= x || y < 0 || gridSize <= y || z < 0 || gridSize <= z) return Int16.MinValue; return grid[GridIndex(x, y, z)]; } Position GetForwardPos() { Position pos; int dir = (camLong + 22) / 45; pos.X = (int)camPos.X + dirX[dir]; pos.Y = (int)camPos.Y - 1; pos.Z = (int)camPos.Z + dirZ[dir]; return pos; } void SetGrid(Position pos, float u, float v, short index) { InstanceInfo[] ins = new InstanceInfo[1]; int start = (Math.Abs(index) - 1) * 72; instanceBuffer.GetData<InstanceInfo>(start, ins, 0, 1, 72); ins[0].AtlasCoordinate = new Vector2(u, v); instanceBuffer.SetData<InstanceInfo>(start, ins, 0, 1, 72); grid[GridIndex(pos.X, pos.Y, pos.Z)] = index; } void SetBlock(byte color) { Position pos = GetForwardPos(); short index = GetGrid(pos.X, pos.Y, pos.Z); if (0 < index || index == Int16.MinValue) return; if (index == 0) { SetNewBlock(pos.X, pos.Y, pos.Z, color); } else { // 再利用 SetGrid(pos, (color & 3) / 4.0f, (color >> 2) / 4.0f, (short)-index); } } void DelBlock() { Position pos = GetForwardPos(); short index = GetGrid(pos.X, pos.Y, pos.Z); if (index <= 0) return; // 論理削除 SetGrid(pos, 2.0f, 0, (short)-index); } protected override void Update(GameTime gameTime) { KeyboardState state = Keyboard.GetState(); if (state[Keys.Escape] == KeyState.Down) Exit(); if (state[Keys.W] == KeyState.Down) MoveXZ(0); if (state[Keys.S] == KeyState.Down) MoveXZ(180); if (state[Keys.A] == KeyState.Down) MoveXZ(-90); if (state[Keys.D] == KeyState.Down) MoveXZ(90); if (state[Keys.Up] == KeyState.Down) camLat++; if (state[Keys.Down] == KeyState.Down) camLat--; if (state[Keys.Left] == KeyState.Down) camLong = (camLong + 359) % 360; if (state[Keys.Right] == KeyState.Down) camLong = (camLong + 1) % 360; if (state[Keys.PageUp] == KeyState.Down) MoveY(0.1f); if (state[Keys.PageDown] == KeyState.Down) MoveY(-0.1f); if (state[Keys.NumPad0] == KeyState.Down) DelBlock(); if (state[Keys.NumPad1] == KeyState.Down) SetBlock(1); if (state[Keys.NumPad2] == KeyState.Down) SetBlock(2); if (state[Keys.NumPad3] == KeyState.Down) SetBlock(3); if (state[Keys.NumPad4] == KeyState.Down) SetBlock(4); if (state[Keys.NumPad5] == KeyState.Down) SetBlock(5); if (state[Keys.NumPad6] == KeyState.Down) SetBlock(6); if (state[Keys.NumPad7] == KeyState.Down) SetBlock(7); if (state[Keys.NumPad8] == KeyState.Down) SetBlock(8); base.Update(gameTime); } void MoveXZ(int degree) { float rad = MathHelper.ToRadians(camLong + degree); float x = camPos.X + (float)Math.Cos(rad) * 0.1f; float z = camPos.Z + (float)Math.Sin(rad) * 0.1f; if (GetGrid((int)x, (int)camPos.Y, (int)z) <= 0) { camPos.X = x; camPos.Z = z; } } void MoveY(float dy) { float y = camPos.Y + dy; if (GetGrid((int)camPos.X, (int)y, (int)camPos.Z) <= 0) { camPos.Y = y; } } protected override void Draw(GameTime gameTime) { GraphicsDevice.Clear(Color.CornflowerBlue); GraphicsDevice.DepthStencilState = DepthStencilState.Default; float rad = MathHelper.ToRadians(camLat); float y = (float)Math.Sin(rad) + camPos.Y; float r = (float)Math.Cos(rad); rad = MathHelper.ToRadians(camLong); float x = camPos.X + (float)Math.Cos(rad) * r; float z = camPos.Z + (float)Math.Sin(rad) * r; Matrix view = Matrix.CreateLookAt(camPos, new Vector3(x, y, z), Vector3.Up); GraphicsDevice.Indices = indexBuffer; effect.Parameters["WVP"].SetValue(view * projection); effect.Parameters["totalTime"].SetValue( 0.01f * (float)gameTime.TotalGameTime.TotalMilliseconds); effect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SetVertexBuffers(bindings); GraphicsDevice.DrawInstancedPrimitives( PrimitiveType.TriangleList, 0, 0, 24, 0, 12, blockNum); // フレームレート draw++; DateTime now = DateTime.Now; TimeSpan t = now - prevTime; if (t.TotalMilliseconds >= 1000) { fps = draw; draw = 0; prevTime = now; } sprite.Begin(); string text = "fps=" + fps + " lat=" + camLat + " long=" + camLong + " block=" + blockNum; sprite.DrawString(font, text, new Vector2(0, 0), Color.White); text = string.Format("x={0:f1} y={1:f1} z={2:f1}", camPos.X, camPos.Y, camPos.Z); sprite.DrawString(font, text, new Vector2(0, 20), Color.White); sprite.End(); base.Draw(gameTime); } } } }} HardwareInstancing.fx #highlight{{ /* #1 Effect File プロジェクトのプロパティ [XNA Game Studio]タブ Use HiDef to access the complete API */ float4x4 WVP; texture cubeTexture; float totalTime; sampler TextureSampler = sampler_state { texture = <cubeTexture>; mipfilter = LINEAR; minfilter = LINEAR; magfilter = LINEAR; }; struct InstancingVSinput { float4 Position : POSITION0; float2 TexCoord : TEXCOORD0; }; struct InstancingVSoutput { float4 Position : POSITION0; float2 TexCoord : TEXCOORD0; }; InstancingVSoutput InstancingVS( InstancingVSinput input, float4x4 instanceTransform : TEXCOORD1, float2 atlasCoord : TEXCOORD5) { InstancingVSoutput output; float4 pos = input.Position; pos = mul(pos, transpose(instanceTransform)); // pos.y = (pos.y + totalTime * atlasCoord.x) % 100.0f; pos = mul(pos, WVP); output.Position = pos; output.TexCoord = float2( atlasCoord.x + (input.TexCoord.x / 4.0f), atlasCoord.y + (input.TexCoord.y / 4.0f)); return output; } float4 InstancingPS(InstancingVSoutput input) : COLOR0 { if (2.0f <= input.TexCoord.x) discard; return tex2D(TextureSampler, input.TexCoord); } technique Instancing { pass Pass0 { VertexShader = compile vs_3_0 InstancingVS(); PixelShader = compile ps_3_0 InstancingPS(); } } }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: