• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
Pasihukka

Directx9: Problem using index buffer to draw simple triangles

8 posts in this topic

Hello,

 

I am new to directx and trying to study it's concepts from a scratch. So far I have managed to render geometries using vertex buffers. This has worked fine from the beginning. However, now I am trying to convert my application to use index buffers together with vertex buffers. But now I am facing a strange problem with index buffers. I just can't figure out what is wrong

 

The problem is that the DrawIndexedPrimitive method seems to behave oddly, especially the PrimitiveCount parameter.

 

Here is the problem:

 

I am trying to render one triangle with vertices:

0, 0, 0,

100, 0, 0,

0, 100, 0

 

Indices being 0,1,2 this is how I try to render my triangle:

 

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 1);

 

But strangely, nothing is rendered! However, when I change my primitive count to 2:

 

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 2);

 

my triangle is rendered.

 

Puzzled about this I decided to try how it works with two triangles:

0, 0, 0,

100, 0, 0,

0, 100, 0,

100, 0 ,0,

100, 100, 0,

0, 100, 0,

 

Now, indices being 0,1,2,3,4,5. The result is:

 

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 6, 0, 1); -> Nothing is rendered

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 6, 0, 2); -> Nothing is rendered

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 6, 0, 3); ->  The first triangle is rendered

DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 6, 0, 4); -> Now both triangles are rendered

 

When I switch DrawIndexedPrimitive to DrawPrimitive it works as expected. I have absolutely no clue what is happening. Do you have any ideas? I know it may be hard without seeing the actual code, but you also may know right a way what's the problem.

 

Thanks!

 

0

Share this post


Link to post
Share on other sites

I don't use DirectX 9, but if you're seeing the triangles sometimes it probably has something to do with back face culling.

 

By default, a lot of renderers require you to specify triangle vertices in a particular order. Draw the vertices Clockwise and they'll show up. Draw them counter-clockwise and the render skips it. The reason for this is that the renderer only draws one side of the triangle to save work.

 

Consider a tetrahedron (a 4-sided die). When you draw it a certain way, you can guarantee that the sides that would be normally visible to the camera are drawn clockwise while the ones hidden from the user are drawn counter clockwise. As the model rotates, the ones that wind up being hidden by the front faces of the tetrahedron wind up being hit in a counter-clockwise order. For an easier to visualize example, you can draw a triangle on a piece of paper, number the vertices clockwise 1, 2, 3. Now flip the paper over. If you hit 1, 2, 3 from this side you'll see it's counter-clockwise

 

You've probably seen the results of this in video games. When there's a bug that allows the camera to poke through a wall, you'll see through the "backs" of other walls but can see the floor/walls on the opposite side.

 

- Eck

0

Share this post


Link to post
Share on other sites


I don't use DirectX 9, but if you're seeing the triangles sometimes it probably has something to do with back face culling.

 

Thanks for your response. I am familiar with back face culling and winding order of triangles. In this case, this is most certainly not the problem. I have tested with both culling on and off and the result is the same. The problem is that primitivecount parameter in DrawIndexedPrimitive call seems to make absolutely no sense at all. When I pass the same vertex information to DrawPrimitive it works ok. None of the calls I make return any error code but it just won't work.

0

Share this post


Link to post
Share on other sites

I am new to directx and trying to study it's concepts from a scratch.


DirectX 9 is 12 years old. If you're trying to understand graphics and DirectX concepts, you should _really_ start with D3D 11. The concepts it'll teach you are much more relevant to modern hardware and the design is much closer to how all graphics APIs are built now.

D3D9 was built for the long-gone transitional era from fixed-function to programmable pipelines. Modern hardware often can't even run D3D9 natively anymore (because things like the fixed-function pipeline is gone) and support for D3D9 on said hardware requires a lot of emulation in the driver to make it work (which means you might learn some concept that looks like it's fine but ends up being a performance or architectural problem when you try to apply it to modern graphics code). There's also a lot of things missing in D3D9 that are essential to really understanding modern graphics architecture. Plus there's obnoxious things in D3D9 like how gets into the LOST_DEVICE state every time you sneeze.

If your hardware is old, just remember that Direct3D 11 has a mechanism called "feature levels" that lets you use the new API with older, less-capable hardware; it lets you use the newer base API but disables some of the newer stuff that requires more recent hardware. If your OS is old, upgrade. If for some reason you want to support XP, consider using GL instead; it gives you access to newer hardware features and lets you port more easily to OSX/Linux/iOS/Android (the proprietary console APIs are more similar to D3D11). There's no good reason that I can think of for anyone to ever write new Direct3D 9 code today.
0

Share this post


Link to post
Share on other sites


DirectX 9 is 12 years old. If you're trying to understand graphics and DirectX concepts, you should _really_ start with D3D 11.

 

Hi. Thank you for your thoughts. I agree with you. I probably should have chosen D3D 11. The reason I chose 9 is that WPF D3DImage works only with D3D9. I am not trying,to build a game so I need a rich set of UI controls. I'll probably need to take another look if I can make WPF work with 11.

 

 

 

Nevertheless, I am not able to sleep my nights before I figure out what's the deal with the original problem. Any suggestions?

0

Share this post


Link to post
Share on other sites

To find out what the problem may be:

 

1. Is your vertex buffer setup as you list it? That is: (0, 0, 0); (100, 0, 0); (0, 100, 0);

2. How is the index buffer set up? As you have it: { 0,1,2,} ?

3. How do you have the view setup? Where is the eyepoint and what is the lookat point?

4. What cullmode do you have set? If none, then CCW (clockwise) culling is the default.

 

IF you have the vertices and indices as indicated, the triangles have a CCW winding order and would be culled.

 

For fun, try setting the indices for those vertices to { 1, 0, 2 } and see if that solves the problem.

 

Or, change the vertices to be in CW order ( 100, 0, 0 ); (0, 0, 0); (0, 100, 0) and leave the indices as 0, 1, 2.

 

[EDIT] Do you set the vertex declaration or FVF when you set the stream source and the indices?

 

[EDIT] By the way, the purpose of using index buffers is to reduce the number of vertices. Note that you've specified (100, 0, 0) and ( 0, 100, 0) twice.

Edited by Buckeye
0

Share this post


Link to post
Share on other sites

Thanks for your help!

 


1. Is your vertex buffer setup as you list it? That is: (0, 0, 0); (100, 0, 0); (0, 100, 0);

 

Yes, it is.

 


2. How is the index buffer set up? As you have it: { 0,1,2,} ?

 

Index buffer is set {0,1,2}

 


3. How do you have the view setup? Where is the eyepoint and what is the lookat point?

 

I have implemented camera mouse navigation. No matter what view I have, the triangle is not there.

 


4. What cullmode do you have set? If none, then CCW (clockwise) culling is the default.

 

Tried with both D3DCULL_CCW and D3DCULL_NONE

 


For fun, try setting the indices for those vertices to { 1, 0, 2 } and see if that solves the problem.

 

Tried, it no difference.

 


[EDIT] Do you set the vertex declaration or FVF when you set the stream source and the indices?

 

Yes.


[EDIT] By the way, the purpose of using index buffers is to reduce the number of vertices. Note that you've specified (100, 0, 0) and ( 0, 100, 0) twice.

 

True! I was just trying to make the simplest possible case work :)

 

Maybe you can see from here what's the problem. This is the code I use to render my triangle:

 

    int vertexBufferSize = 3 * 6 * sizeof(float);
    int triangleBufferSize = 1 * 3 * sizeof(int);
    int streamNumber = 0;
    int offsetInBytes = 0;

    HRESULT hr = 0;
    
    // Positions and their normals
    float vertices[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                        100.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
                        0.0f, 100.0f, 0.0f, 0.0f, 0.0f, 1.0f};

    int indices[] = {0,1,2};

    hr = m_pd3dDevice->CreateVertexBuffer(vertexBufferSize,
                                          D3DUSAGE_WRITEONLY,
                                          D3DFVF_CUSTOMVERTEX,
                                          D3DPOOL_DEFAULT,
                                          &m_pd3dVB,
                                          NULL);

    hr = m_pd3dDevice->CreateIndexBuffer(triangleBufferSize,
                                        D3DUSAGE_WRITEONLY,
                                        D3DFMT_INDEX32,
                                        D3DPOOL_DEFAULT,
                                        &m_pd3dIB,
                                        NULL);

    void* pVertices = nullptr;
    hr = m_pd3dVB->Lock(vertexBufferSize, 0, &pVertices, 0);
    memcpy(pVertices, vertices, vertexBufferSize);
    m_pd3dVB->Unlock();

    void* pIndices = nullptr;
    hr =  m_pd3dIB->Lock(triangleBufferSize, 0, &pIndices, 0);
    memcpy(pIndices, indices, triangleBufferSize);
    m_pd3dIB->Unlock();   

    hr = m_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX); 
    hr = m_pd3dDevice->SetStreamSource(streamNumber, m_pd3dVB, offsetInBytes, sizeof(CUSTOMVERTEX));  
    hr = m_pd3dDevice->SetIndices(m_pd3dIB);
    
    // This works
    //hr = m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1);   
    // This does not work!
    hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 1);
    // Strange enough, this works!
    //hr = m_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 3, 0, 2);

0

Share this post


Link to post
Share on other sites

Found it!

 

It turned out my lock calls were wrong.

 

hr = m_pd3dVB->Lock(vertexBufferSize, 0, &pVertices, 0);

hr =  m_pd3dIB->Lock(triangleBufferSize, 0, &pIndices, 0);

 

should be

 

hr = m_pd3dVB->Lock(0, vertexBufferSize, &pVertices, 0);

hr =  m_pd3dIB->Lock(0, triangleBufferSize, &pIndices, 0);

 

Damn, it took long to figure out this simple thing!

0

Share this post


Link to post
Share on other sites


By default, a lot of renderers require you to specify triangle vertices in a particular order
As a side note: HW by itself does not require this. It is a feature built in graphics API pretty much since day zero. The HW has little preference for one setting over another and you can even change the visible winding if you want with no performance penalty at all.
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0