0

オンラインのチュートリアルから取得した 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();
    }
}

コードの残りの部分はほとんど同じです。

4

1 に答える 1