Index Buffers

There doesn't seem to be a Help item on index buffers in XNA Studio, so I followed the Draw 3D Primitives item and I managed that successfully. I also implemented the Apply an Effect item that uses a simple shader, works as well. Then I followed the chapter about index buffers form Tom Miller's book Managed Dx9 Kickstart, and most of the stuff seems to be the same, however nothing gets drawn on the screen. Here's the code related to the drawing..

//indexed cube

VertexPositionColor[] indexedCube = new VertexPositionColorMusic;

//some vectors for the vertices of the cube

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 );

VertexDeclaration decl;

//array of indices

short[] indices = {

0,1,2, // Front Face

1,3,2, // Front Face

4,5,6, // Back Face

6,5,7, // Back Face

0,5,4, // Top Face

0,2,5, // Top Face

1,6,7, // Bottom Face

1,7,3, // Bottom Face

0,6,1, // Left Face

4,6,0, // Left Face

2,3,7, // Right Face

5,2,7 // Right Face

};

//index buffer

IndexBuffer indexbuff;

//creating the cube

indexedCube[0] = new VertexPositionColor(topLeftFront, Color.Red);

indexedCube[1] = new VertexPositionColor(topRightFront, Color.Blue);

indexedCube[2] = new VertexPositionColor(topLeftBack, Color.Green);

indexedCube[3] = new VertexPositionColor(topRightBack, Color.Yellow);

indexedCube[4] = new VertexPositionColor(bottomLeftFront , Color.Red);

indexedCube[5] = new VertexPositionColor(bottomRightFront , Color.Blue);

indexedCubeDevil = new VertexPositionColor(bottomLeftBack , Color.Green);

indexedCube[7] = new VertexPositionColor(bottomRightBack , Color.Yellow);

indexbuff = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, ResourceUsage.WriteOnly, ResourcePool.Default);

indexbuff.SetData<short>(0,indices, 0, indices.Length, SetDataOptions.None);

graphics.GraphicsDevice.Indices = indexbuff;

decl = new VertexDeclaration(graphics.GraphicsDevice, VertexPositionColor.VertexElements);

//drawing

myEffect.Begin(EffectStateOptions.Default);

foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)

{

pass.Begin();

myEffect.Parameters["WorldViewProj"].SetValue(worldMatrix * viewMatrix * projMatrix);

myEffect.CommitChanges();

graphics.GraphicsDevice.VertexDeclaration = decl;

graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace;

graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 8, 0, 12);

pass.End();

}

myEffect.End();

I should mention as well, that when I ran this using older NVIDIA drivers, I was getting the blue screen of death.. I upgraded the drivers to the latest Forceware and no crashes but still nothing is drawn on the screen. Any help




Answer this question

Index Buffers

  • Werner Clausen

    Ah thank you. I figured it was something simple I was overlooking.

    There is probably something similar as to why the vertex color isn't being read My triangles are all grey, regardless of the color given to them.

  • Franco Finstad

    The snippet in the Xna docs for drawing 3D primitives uses GraphicsDevice.DrawUserPrimitives(), the DrawUser* methods allow you to submit the vertex data with the draw call rather than creating and setting a vertex buffer. Your code is using DrawIndexedPrimitives() which expects a vertex buffer to have been set. You should change it to use DrawUserIndexedPrimitives() or better, since the DrawUser* methods are slow, create a vertex buffer and use that with DrawIndexedPrimitives().

    Cheers,
    Leaf.


  • anshuman_atri

    The most common reasons for such a problem are a wrong vertex declaration or an error in the shader code.



  • search and deploy

    Maybe it’s only missing in your snipped but I could not spot the code that create and set your vertex buffer.



  • r3n

    I actually have the same problem. Although I create the vertex buffer, it seems odd that there is no way to set it to the device. Granted the device is passed in as a parameter to the constructor of the vertex buffer but if multiple vertex buffers were created, how does the call to DrawIndexedPrimitives() know which to use Or is there only one



  • SgtMauler

    This how I assign the buffers

    Create()

    //Vertexbuffer data

    vb = new VertexBuffer(Game.graphics.GraphicsDevice, typeof(VertexPositionColor), vpc.Length, ResourceUsage.WriteOnly

    | ResourceUsage.WriteOnly, ResourcePool.Managed);

    vb.SetData<VertexPositionColor>(vpc, 0, vpc.Length, SetDataOptions.None);

    //Indexbuffer data

    indexbuff = new IndexBuffer(Game.graphics.GraphicsDevice, typeof(short),

    myIndices.Length * VertexPositionColor.SizeInBytes, ResourceUsage.WriteOnly, ResourcePool.Managed);

    indexbuff.SetData<short>(myIndices, 0, myIndices.Length, SetDataOptions.None);

    Render()

    myEffect.Begin(EffectStateOptions.Default);

    foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)

    {

    pass.Begin();

    //Set input data to stream

    Game.graphics.GraphicsDevice.Indices = indexbuff;

    Game.graphics.GraphicsDevice.Vertices[0].SetSource(vb, 0, VertexPositionColor.SizeInBytes);

    //declare vertex information

    VertexDeclaration decl = new VertexDeclaration(Game.graphics.GraphicsDevice,VertexPositionColor.VertexElements );

    Game.graphics.GraphicsDevice.VertexDeclaration = decl;

    Game.graphics.GraphicsDevice.RenderState.CullMode = CullMode.CullClockwiseFace;

    Game.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,

    0, 0, myNumVerticesY * myNumVerticesX, 0, numTriangles);

    myEffect.CommitChanges();

    pass.End();

    }

    myEffect.End();


  • Jco316

    Turned out to be the shader for the color. I was using the BasicEffect which seems to have a few issues. I was using it for the View and Projection matrices. A simple routine to move the camera forward/back and rotate it about the Y was resulting in some odd translation of the objects in the world.

    Stealing the shader from the provided SpaceWar game fixes both the color and translation issues.

  • clint 2

     

     

    hi you could try this

    there is a model object in xna which is fantastic: it lets you build bone herichys a well, I used the ModelMesh object as there is also a model object, but that reads specefic data I have not yet figures out, I think its for reading FXB files... when the content manage ment is released, but for not use the MODELMESH object e.t.c.....

    '//Create Model mesh

    Dim TempModel As ModelMesh

    Dim TempPart As New List(Of ModelMeshPart)

    TempPart.Insert(0, New ModelMeshPart(0, 0, NumberofPoints, 0, NumberofFaces, Me.VertexDeclaration, VertexPositionNormalTexture.SizeInBytes, Nothing))

    TempModel = New ModelMesh("Test object", Nothing, New BoundingSphere(New Vector3(0, 0, 0), 30), Me.VertexBuffer, Me.IndexBuffer, TempPart, Nothing)

     

    and render like this , I cracked this yesterday and it makes drawing ever so easy, Just have a look at the class implementation and it renders with no problems!!!

    Public Sub Draw()

    ' Dim pass1 As EffectPass

    Dim EffectApply As BasicEffect

     

    '*************************************************************************************

    '*Start State block ..... Tridex ... Code chnage / update .....

    '*************************************************************************************

    Dim Tempstate As New StateBlock(mUseDevice, StateBlockType.All)

    Tempstate.Capture()

    '*************************************************************************************

    '*Start The effect pass.....

    '*************************************************************************************

    mUseDevice.RenderState.CullMode = CullMode.None

    Dim i As Long

    For i = 0 To materials.Count - 1

     

    ' For Each pass1 In Me.effect.CurrentTechnique.Passes

    ' pass1.Begin()

    If Not IsNothing(materials.Item(i).texture) Then

    EffectApply = EffectsAndSshaderEngine.CreateMaterial(mUseDevice, True, materials.Item(i).vDiffuse, materials.Item(i).vAmbient, New Vector3(0.1, 0.1, 0.1), materials.Item(i).vSpecular, materials.Item(i).nShininess, materials.Item(i).fAlpha, New Vector3(0.1, 0.1, 0.1))

    EffectApply.View = Me.ViewMatrix.GetXNAMatrix

    EffectApply.World = Me.WorldMatrix.GetXNAMatrix

    EffectApply.Projection = Me.ProjectionMatrix.GetXNAMatrix

    EffectApply.Texture = materials.Item(i).texture

    Else

    EffectApply = EffectsAndSshaderEngine.CreateMaterial(mUseDevice, True, materials.Item(i).vDiffuse, materials.Item(i).vAmbient, New Vector3(0.1, 0.1, 0.1), materials.Item(i).vSpecular, materials.Item(i).nShininess, materials.Item(i).fAlpha, New Vector3(0.1, 0.1, 0.1))

    EffectApply.View = Me.ViewMatrix.GetXNAMatrix

    EffectApply.World = Me.WorldMatrix.GetXNAMatrix

    EffectApply.Projection = Me.ProjectionMatrix.GetXNAMatrix

    End If

    EffectApply.Begin(EffectStateOptions.Default)

    EffectApply.Techniques.Item(0).Passes.Item(0).Begin()

    EffectApply.CommitChanges()

    TempModel.BeginDraw()

    Dim Part As TridexConsultants.Engine.ModelMeshPart

    For Each Part In TempModel.MeshParts

    Part.Draw()

    Next

    TempModel.EndDraw()

    '*************************************************************************************

    '*End Do your normal redering here

    '*************************************************************************************

    EffectApply.Techniques.Item(0).Passes.Item(0).End()

    EffectApply.End()

    Next


  • Captain Baz

    I am not sure what’s going wrong but at first you should create your buffers in the managed and not the default buffer. Additional your vertex buffer should not be dynamic. This is only for vertices that you are change all the time.

    Locking at your index and vertex values I have the feeling that they don’t match. You should try to render it with cull mode none to get sure you haven’t defined them in the wrong order.

    Additional I would try to render the first triangle from your vertex buffer only to make sure that everything else is fine.



  • nicelily

    Yes, I did not declare a VertexBuffer.. but neither does the code in the XNA Help that creates a non-indexed cube.. I guess this is different from MDX1 Or I'm missing the idea all the way here hehe

  • Ben Weber

    Leaf. wrote:
    The snippet in the Xna docs for drawing 3D primitives uses GraphicsDevice.DrawUserPrimitives(), the DrawUser* methods allow you to submit the vertex data with the draw call rather than creating and setting a vertex buffer. Your code is using DrawIndexedPrimitives() which expects a vertex buffer to have been set. You should change it to use DrawUserIndexedPrimitives() or better, since the DrawUser* methods are slow, create a vertex buffer and use that with DrawIndexedPrimitives().

    Cheers,
    Leaf.

    Ah ic, well I'm doing this:

    indexedCube[0] = new VertexPositionColor(topLeftFront, Color.Red);

    indexedCube[1] = new VertexPositionColor(topRightFront, Color.Blue);

    indexedCube[2] = new VertexPositionColor(topLeftBack, Color.Green);

    indexedCube[3] = new VertexPositionColor(topRightBack, Color.Yellow);

    indexedCube[4] = new VertexPositionColor(bottomLeftFront , Color.Red);

    indexedCube[5] = new VertexPositionColor(bottomRightFront , Color.Blue);

    indexedCubeDevil = new VertexPositionColor(bottomLeftBack , Color.Green);

    indexedCube[7] = new VertexPositionColor(bottomRightBack , Color.Yellow);

    //set vertex band index buffers

    vb = new VertexBuffer(graphics.GraphicsDevice, typeof(VertexPositionColor), 8, ResourceUsage.Dynamic | ResourceUsage.WriteOnly, ResourcePool.Default);

    vb.SetData<VertexPositionColor>(indexedCube, 0, indexedCube.Length, SetDataOptions.None);

    indexbuff = new IndexBuffer(graphics.GraphicsDevice, typeof(short), indices.Length, ResourceUsage.WriteOnly, ResourcePool.Default);

    indexbuff.SetData<short>(indices, 0, indices.Length, SetDataOptions.None);

    So I'm setting both VertexBuffer and an IndexBuffer.. then I draw with:

    graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, 8, 0, 12);

    I still don't get the cube, what am I missing



  • mAh3u

    You need to assign the buffer to the device:

    device.Vertices[0].SetSource(buffer, 0, bufferstride);



  • Index Buffers