0
\$\begingroup\$

EDIT NOTE:

I was trying to impliment indexing to my code instead of instancing. I left the indexing method because in my case, I don't need to use it.

Preview

Untill now I have drawed my cube with 36 vertices (2 triangles for each face - in total 12 triangles), but my game performance is bad.

I decided to improve the performance by using the index draw method.

This method would let me use only 8 vertices per cube but each draw I'll need to define the drawing order of these vertices (so I'll still draw 12 triangles but by only 8 vertices).

The Problems

  1. I don't draw the vertices in the right order so it makes the cube a mess (and I don't know currect order that it should be).

  2. I want to use a diffrent texture for each side of the cube, but with this method I need to draw the vertices all at once. That means I can't devide the cube into faces and use a diffrent texture for each face. Can I use 1 texture for the cube that will make it look like a diffrent texture for each face?

  3. I am using VertexPositionNormalTexture and I want to use lighting in my game. Which means I have to give each vertex a normal. But with only 8 vertices I can't define the normals of the cube because each one of them is used by 3 diffrent faces.

  4. The texture of the block is also drawen from the inside, While I want to render the cube only from the outside.

My Code

Global - Setup The Indices and Index Buffer:

    public static void SetupIndices()
    {
        // Define the indices:
        indices = new short[36];

        // TOP
        indices[0] = 4; indices[1] = 2; indices[2] = 0;
        indices[3] = 4; indices[4] = 5; indices[5] = 2;

        // BOTTOM
        indices[6] = 6; indices[7] = 1; indices[8] = 3;
        indices[9] = 6; indices[10] = 3; indices[11] = 7;

        // LEFT
        indices[12] = 5; indices[13] = 7; indices[14] = 3;
        indices[15] = 2; indices[16] = 5; indices[17] = 3;

        // RIGHT
        indices[18] = 4; indices[19] = 1; indices[20] = 6;
        indices[21] = 0; indices[22] = 1; indices[23] = 4;

        // BACK
        indices[24] = 0; indices[25] = 2; indices[26] = 1;
        indices[27] = 1; indices[28] = 2; indices[29] = 3;

        // FRONT
        indices[30] = 4; indices[31] = 6; indices[32] = 5;
        indices[33] = 6; indices[34] = 7; indices[35] = 5;

        blocksIndexBuffer = new IndexBuffer(graphicsDevice, typeof(short), indices.Length, BufferUsage.WriteOnly);
        blocksIndexBuffer.SetData(indices);
    }

Block Class - Build Block (Vertices Area):

            // Calculate the position of the vertices.
            Vector3 topLeftFront = origin + new Vector3(-1.0f, 1.0f, -1.0f) * this.blockSize;
            Vector3 topLeftBack = origin + new Vector3(-1.0f, 1.0f, 1.0f) * this.blockSize;
            Vector3 topRightFront = origin + new Vector3(1.0f, 1.0f, -1.0f) * this.blockSize;
            Vector3 topRightBack = origin + new Vector3(1.0f, 1.0f, 1.0f) * this.blockSize;
            Vector3 bottomLeftFront = origin + new Vector3(-1.0f, -1.0f, -1.0f) * this.blockSize;
            Vector3 bottomLeftBack = origin + new Vector3(-1.0f, -1.0f, 1.0f) * this.blockSize;
            Vector3 bottomRightFront = origin + new Vector3(1.0f, -1.0f, -1.0f) * this.blockSize;
            Vector3 bottomRightBack = origin + new Vector3(1.0f, -1.0f, 1.0f) * this.blockSize;

            // Normal vectors for each face (needed for lighting/display)
            Vector3 normalTop = origin + new Vector3(0.0f, 1.0f, 0.0f);
            Vector3 normalBottom = origin + new Vector3(0.0f, -1.0f, 0.0f);
            Vector3 normalLeft = origin + new Vector3(-1.0f, 0.0f, 0.0f);
            Vector3 normalRight = origin + new Vector3(1.0f, 0.0f, 0.0f);
            Vector3 normalFront = origin + new Vector3(0.0f, 0.0f, 1.0f);
            Vector3 normalBack = origin + new Vector3(0.0f, 0.0f, -1.0f);

            // UV texture coordinates
            Vector2 textureTopLeft = new Vector2(0f, 0.0f);
            Vector2 textureTopRight = new Vector2(1f, 0.0f);
            Vector2 textureBottomLeft = new Vector2(0f, 1.0f);
            Vector2 textureBottomRight = new Vector2(1f, 1.0f);

            // Define the vertices of the cube.
            vertices[0] = new VertexPositionNormalTexture(topLeftBack, normalTop, textureBottomLeft);
            vertices[1] = new VertexPositionNormalTexture(bottomLeftBack, normalBottom, textureBottomLeft);
            vertices[2] = new VertexPositionNormalTexture(topRightBack, normalTop, textureBottomLeft);
            vertices[3] = new VertexPositionNormalTexture(bottomRightBack, normalBottom, textureTopLeft);
            vertices[4] = new VertexPositionNormalTexture(topLeftFront, normalTop, textureTopLeft);
            vertices[5] = new VertexPositionNormalTexture(topRightFront, normalBottom, textureTopRight);
            vertices[6] = new VertexPositionNormalTexture(bottomLeftFront, normalTop, textureBottomLeft);
            vertices[7] = new VertexPositionNormalTexture(bottomRightFront, normalBottom, textureBottomRight);

Block Class - Render Block Method:

                graphicsDevice.SetVertexBuffer(blocksVerticesBuffer);
                blocksVerticesBuffer.SetData(this.vertices);
                blocksBasicEffect.Texture = topBlockTexture;
                blocksIndexBuffer.SetData(indices);
                graphicsDevice.Indices = blocksIndexBuffer;
                blocksBasicEffect.CurrentTechnique.Passes[0].Apply();
                graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip, 0, 0, 12);

Running Result:

The Result That I Get By The Indices Draw Method

\$\endgroup\$
  • 1
    \$\begingroup\$ I recommend breaking this down into multiple questions that can each be answered directly. \$\endgroup\$ – Almo Jan 22 at 15:40
  • \$\begingroup\$ You might find searching for existing information about cube vertex formatting helps you answer some of your areas of certainty, and you can focus your question on one remaining question. \$\endgroup\$ – DMGregory Jan 22 at 17:16
  • \$\begingroup\$ Also, you write performance as the main reason to go down this route- However, indexing will not inprove all that much with the requirements in your list. What made you decide to move to indexing (instead of instancing)? \$\endgroup\$ – Felsir Jan 22 at 19:26
  • \$\begingroup\$ @Felsir I'm new to XNA and also to 3D Rendering techniques, I didn't know that there is such a technique called instancing. Instancing soundes much better then indexing so I'm gonna try impliment Instancing to my previous code (before I tried doing indexing). Thank you for your helpful comment, and if you know another techniqe that I can impliment in my code to make it render faster it will be great :D \$\endgroup\$ – Omer Eli Jan 22 at 21:15
  • \$\begingroup\$ As an aside, if you're trying to make a Minecraft-style voxel world, neither sharing vertices nor instancing will be enough on their own to get good performance. What matters more is hidden surface removal — you'll want to stop rendering cubes, and start rendering chunk meshes consisting of only the visible faces at the surface of the voxel structure, without all the hidden interior faces. \$\endgroup\$ – DMGregory Jan 23 at 13:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.