オンラインのチュートリアルから取得した XNA のテクスチャ キューブがあります。唯一のことは、これらの立方体の多くをレンダリングするたびに遅れることです. 友人は、キューブに使用しているベクトルの数を 8 (コーナーごとに 1 つ) に減らし、インデックスを使用してキューブの三角形を作成できると教えてくれました。だから私はこれをやろうとしましたが、特にテクスチャの Vector2 を要求している場合は特に、その方法がわからないことを認めます。
グラフィックス デバイスで背面カリングを有効にしています。
Riemer のチュートリアルを確認しましたが、役に立ちません。私は視覚的な学習者であり、頂点とインデックスに関する長い記事を読むことは、説明付きの YouTube ビデオを見るほど魅力的ではありません。誰かが私に何をすべきかアドバイスしてください:
- より多くのキューブをレンダリングするときのゲームのパフォーマンスを改善します。
- 複数のテクスチャを持つ立方体をレンダリングします。
- キューブごとに描画される頂点の数を減らすために、キューブを「チャンク」に「結合」します。
私の立方体は、指定した ID に応じてテクスチャ マップからテクスチャを取得しますが、これは正常に機能します。「Windows Phone 7 の XNA で頂点を持つ立方体を構築、描画、テクスチャリングする」というタイトルのチュートリアルを使用しました。Google 検索では、キューブの作成に使用しているコードの大部分が表示されます。
私は一日の大半をぼんやりと見つめて無駄にし、コード全体を頭に入れようとして頭が痛くなりました。概念は単純ですが、実装は難しいです (少なくとも私にとっては)。
編集:ベクトルの数を 8 に減らすことに成功し、立方体を描画しました。ただし、ベクターごとにテクスチャを描画することはできません。この方法に代わる方法は、テクスチャの代わりに色を使用することですが、それはまだ私が頼りにしたいものではありません. たった 8 つのベクトルで各立方体を描画しても、同じ量の遅延が発生します... そのため、今のところ、36 個のベクトルを使用して、テクスチャをあるべき場所に保持することに戻りました。上記の3点は今後もやっていきたいと思います。
編集 2:要求に応じて、私のレンダリング コードを以下に示します。以下を使用して、コンストラクタ内の各キューブにテクスチャを渡しています。
public Block(Vector3 position, int BlockID)
{
Position = position;
Texture = Assets.GetBlockTexture(@"Textures/terrain", BlockID);
Size = new Vector3(1, 1, 1);
}
Assets.GetBlockTexture は基本的に、渡されたブロック ID に基づいて、256x256 の大きなテクスチャ マップから特定の 16x16 の「ブロック」テクスチャを返します (はい、1.4 より前の Minecraft と非常によく似ています)。
私のゲームの Draw メソッドは次のとおりです。
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
var s = new DepthStencilState {DepthBufferEnable = true};
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.PointClamp, s, RasterizerState.CullCounterClockwise);
foreach (var block in blocks) block.Draw(GraphicsDevice, camera, effect);
spriteBatch.End();
base.Draw(gameTime);
}
各ブロックの Draw メソッドを呼び出す:
public void Draw(GraphicsDevice device, Camera camera, BasicEffect effect)
{
effect = new BasicEffect(device)
{
TextureEnabled = true,
Texture = Texture,
View = camera.View,
Projection = camera.Projection,
World = Matrix.Identity
};
effect.EnableDefaultLighting();
foreach (var pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
Render(device);
}
}
次に、ブロックの Render メソッドを呼び出します。
public void Render(GraphicsDevice graphicsDevice)
{
if (!isConstructed) ConstructBlock();
using (var buffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, NUMVERTICES, BufferUsage.WriteOnly))
{
buffer.SetData(vertices);
graphicsDevice.SetVertexBuffer(buffer);
}
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, NUMTRIANGLES);
}
ConstructBlock メソッドは、正しいテクスチャ座標で 36 個の頂点を作成します。
private void ConstructBlock()
{
vertices = new VertexPositionNormalTexture[NUMVERTICES];
// Calculate the position of the vertices on the top face.
var topLeftFront = Position + new Vector3(-1.0f, 1.0f, -1.0f) * Size;
var topLeftBack = Position + new Vector3(-1.0f, 1.0f, 1.0f) * Size;
var topRightFront = Position + new Vector3(1.0f, 1.0f, -1.0f) * Size;
var topRightBack = Position + new Vector3(1.0f, 1.0f, 1.0f) * Size;
// Calculate the position of the vertices on the bottom face.
var btmLeftFront = Position + new Vector3(-1.0f, -1.0f, -1.0f) * Size;
var btmLeftBack = Position + new Vector3(-1.0f, -1.0f, 1.0f) * Size;
var btmRightFront = Position + new Vector3(1.0f, -1.0f, -1.0f) * Size;
var btmRightBack = Position + new Vector3(1.0f, -1.0f, 1.0f) * Size;
// Normal vectors for each face (needed for lighting / display)
var normalFront = new Vector3(0.0f, 0.0f, 1.0f) * Size;
var normalBack = new Vector3(0.0f, 0.0f, -1.0f) * Size;
var normalTop = new Vector3(0.0f, 1.0f, 0.0f) * Size;
var normalBottom = new Vector3(0.0f, -1.0f, 0.0f) * Size;
var normalLeft = new Vector3(-1.0f, 0.0f, 0.0f) * Size;
var normalRight = new Vector3(1.0f, 0.0f, 0.0f) * Size;
//UV texture coordinates
var textureTopLeft = new Vector2(1.0f * Size.X, 0.0f * Size.Y);
var textureTopRight = new Vector2(0.0f * Size.X, 0.0f * Size.Y);
var textureBottomLeft = new Vector2(1.0f * Size.X, 1.0f * Size.Y);
var textureBottomRight = new Vector2(0.0f * Size.X, 1.0f * Size.Y);
//FRONT face.
vertices[0] = new VertexPositionNormalTexture(topLeftFront, normalFront, textureTopLeft);
vertices[1] = new VertexPositionNormalTexture(btmLeftFront, normalFront, textureBottomLeft);
vertices[2] = new VertexPositionNormalTexture(topRightFront, normalFront, textureTopRight);
vertices[3] = new VertexPositionNormalTexture(btmLeftFront, normalFront, textureBottomLeft);
vertices[4] = new VertexPositionNormalTexture(btmRightFront, normalFront, textureBottomRight);
vertices[5] = new VertexPositionNormalTexture(topRightFront, normalFront, textureTopRight);
//BACK face.
vertices[6] = new VertexPositionNormalTexture(topLeftBack, normalBack, textureTopRight);
vertices[7] = new VertexPositionNormalTexture(topRightBack, normalBack, textureTopLeft);
vertices[8] = new VertexPositionNormalTexture(btmLeftBack, normalBack, textureBottomRight);
vertices[9] = new VertexPositionNormalTexture(btmLeftBack, normalBack, textureBottomRight);
vertices[10] = new VertexPositionNormalTexture(topRightBack, normalBack, textureTopLeft);
vertices[11] = new VertexPositionNormalTexture(btmRightBack, normalBack, textureBottomLeft);
//TOP face.
vertices[12] = new VertexPositionNormalTexture(topLeftFront, normalTop, textureBottomLeft);
vertices[13] = new VertexPositionNormalTexture(topRightBack, normalTop, textureTopRight);
vertices[14] = new VertexPositionNormalTexture(topLeftBack, normalTop, textureTopLeft);
vertices[15] = new VertexPositionNormalTexture(topLeftFront, normalTop, textureBottomLeft);
vertices[16] = new VertexPositionNormalTexture(topRightFront, normalTop, textureBottomRight);
vertices[17] = new VertexPositionNormalTexture(topRightBack, normalTop, textureTopRight);
//BOTTOM face.
vertices[18] = new VertexPositionNormalTexture(btmLeftFront, normalBottom, textureTopLeft);
vertices[19] = new VertexPositionNormalTexture(btmLeftBack, normalBottom, textureBottomLeft);
vertices[20] = new VertexPositionNormalTexture(btmRightBack, normalBottom, textureBottomRight);
vertices[21] = new VertexPositionNormalTexture(btmLeftFront, normalBottom, textureTopLeft);
vertices[22] = new VertexPositionNormalTexture(btmRightBack, normalBottom, textureBottomRight);
vertices[23] = new VertexPositionNormalTexture(btmRightFront, normalBottom, textureTopRight);
//LEFT face.
vertices[24] = new VertexPositionNormalTexture(topLeftFront, normalLeft, textureTopRight);
vertices[25] = new VertexPositionNormalTexture(btmLeftBack, normalLeft, textureBottomLeft);
vertices[26] = new VertexPositionNormalTexture(btmLeftFront, normalLeft, textureBottomRight);
vertices[27] = new VertexPositionNormalTexture(topLeftBack, normalLeft, textureTopLeft);
vertices[28] = new VertexPositionNormalTexture(btmLeftBack, normalLeft, textureBottomLeft);
vertices[29] = new VertexPositionNormalTexture(topLeftFront, normalLeft, textureTopRight);
//RIGHT face.
vertices[30] = new VertexPositionNormalTexture(topRightFront, normalRight, textureTopLeft);
vertices[31] = new VertexPositionNormalTexture(btmRightFront, normalRight, textureBottomLeft);
vertices[32] = new VertexPositionNormalTexture(btmRightBack, normalRight, textureBottomRight);
vertices[33] = new VertexPositionNormalTexture(topRightBack, normalRight, textureTopRight);
vertices[34] = new VertexPositionNormalTexture(topRightFront, normalRight, textureTopLeft);
vertices[35] = new VertexPositionNormalTexture(btmRightBack, normalRight, textureBottomRight);
isConstructed = true;
}
画面には 10 個のブロックで 288 個の三角形しかレンダリングされていませんが、なんと 1 ~ 3 FPS で描画されています。多くの 3D ゲームを問題なくプレイできることから、問題の原因が自分のグラフィック カードではないことはわかっています。
Nico のリクエストに応じてコードを更新しました。
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
var s = new DepthStencilState {DepthBufferEnable = true};
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.PointClamp, s, RasterizerState.CullCounterClockwise);
foreach (var block in blocks) block.Draw(camera, effect);
spriteBatch.DrawString(Content.Load<SpriteFont>("SpriteFont1"), "Number of triangles: " + triangles, new Vector2(10, 10), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
ブロック.cs:
private VertexPositionNormalTexture[] vertices;
private VertexBuffer buffer;
private GraphicsDevice device;
public Block(GraphicsDevice device, Vector3 position, int BlockID)
{
this.device = device;
Position = position;
Texture = Assets.GetBlockTexture(@"Textures/terrain", BlockID);
Size = new Vector3(1, 1, 1);
buffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, NUMVERTICES, BufferUsage.WriteOnly);
}
public void Render()
{
if (!isConstructed) ConstructBlock();
buffer.SetData(vertices);
device.SetVertexBuffer(buffer);
device.DrawPrimitives(PrimitiveType.TriangleList, 0, NUMTRIANGLES);
}
public void Draw(Camera camera, BasicEffect effect)
{
effect = new BasicEffect(device)
{
TextureEnabled = true,
Texture = Texture,
View = camera.View,
Projection = camera.Projection,
World = Matrix.Identity,
PreferPerPixelLighting = false
};
effect.EnableDefaultLighting();
foreach (var pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
Render();
}
}
コードの残りの部分はほとんど同じです。