In What Order Should I Send My Vertices To OpenGL for Culling

24,174

Solution 1

By default? In counter-clockwise order.

Consider a triangle facing the camera:

A
|\
| \
|  \
B---C

A->B->C would be front facing (counter-clockwise order), A->C->B would be rear-facing (clockwise order).

You can change which way OpenGL considers "front facing" via glFrontFace():

The projection of a polygon to window coordinates is said to have clockwise winding if an imaginary object following the path from its first vertex, its second vertex, and so on, to its last vertex, and finally back to its first vertex, moves in a clockwise direction about the interior of the polygon. The polygon's winding is said to be counterclockwise if the imaginary object following the same path moves in a counterclockwise direction about the interior of the polygon. glFrontFace specifies whether polygons with clockwise winding in window coordinates, or counterclockwise winding in window coordinates, are taken to be front-facing. Passing GL_CCW to mode selects counterclockwise polygons as front-facing; GL_CW selects clockwise polygons as front-facing.

By default, counterclockwise polygons are taken to be front-facing.

For ordering your vertices, consider an ideal cube:

  6---7
 /|  /|
2---3 |
| 4-|-5
|/  |/ 
0---1

For each face mentally rotate it to face the camera (your mind's eye):

Sides:
2---3  3---7  7---6  6---2
|   |  |   |  |   |  |   |
|   |  |   |  |   |  |   |
0---1  1---5  5---4  4---0

Bottom/Top
0---1  6---7
|   |  |   |
|   |  |   |
4---5  2---3

Then you can just visually read off the quads or triangle pairs in the right counter-clockwise order:

2---3                3         2---3 
|   |  becomes      /|   and   |  / 
|   |             /  |         |/ 
0---1            0---1         0 

Triangles 0-1-3 and 0-3-2
Quad 0-1-3-2

It doesn't matter which vertex you start the triangle/quad with, for example with the first triangle 0-1-3, 1-3-0, and 3-0-1 are all equally valid, front-facing triangles.

Solution 2

I learned another rule of thumb (literally) for determining the vertex order known as the "right hand rule".
Imagine your open hand (right) inside the cube with your thumb pointing towards the center of the cube. If you then curl your hand into a fist, your fingers will pass the vertices in the correct order. Since you are using your right hand for this it is called the "right hand rule".

Conversely, if you start with your left hand and point your thumb away from the center of the cube, your fingers will again sweep the vertices in the correct order. This is known as the "left hand rule" (surprise).

Both methods work to give you counter-clockwise ordering. For clockwise ordering, just use the opposite hand.

Share:
24,174
ultifinitus
Author by

ultifinitus

Currently a c++/Obj-c/Java/C# developer, focused on c++ and java at the moment. Blog: http://ultifinitus.blogspot.com [email protected]

Updated on January 30, 2020

Comments

  • ultifinitus
    ultifinitus over 4 years

    I'm learning a spot of 3d opengl, and it's going rather well, I've got a nice camera moving about and some simple cube objects, at the moment. Currently using vertex arrays, but I'm swapping to VBOs pretty quick here. I'm just trying to enable culling, however I'm not sure what order in which I ought to specify my vertices, right now this is what I'm doing:

    void cube::update_verts(){
    GLushort cur=0;
    
    ///back face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    
    ///right face
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    
    ///top face
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    
    ///front face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    
    ///bottom face
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    
    ///left face
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    
    
    }
    
    ///Drawing Code:
    
    glVertexPointer(3,GL_FLOAT,0,object.verts);
    glColorPointer(3,GL_UNSIGNED_BYTE,0,object.colors);
    glDrawArrays(GL_QUADS,0,6*4);
    

    However it's definitely quite wrong, because when I glEnable(GL_CULL_FACE); my cubes don't show the correct faces (as seen below).

    Normal Regular View From Top

    Problem Child View From Side

    With both of these images culling is enabled.

    In what order should I specify the vertices?


    (EDIT) Updated Working Function:

    void cube::update_verts(){
    GLushort cur=0;
    
    ///top face
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    
    
    ///bottom face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    
    ///left face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    
    ///right face
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    
    ///front face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z+sz;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z+sz;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z+sz;
    
    
    ///back face
    verts[cur++]=x; verts[cur++]=y; verts[cur++]=z;
    verts[cur++]=x; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y+sy; verts[cur++]=z;
    verts[cur++]=x+sx; verts[cur++]=y; verts[cur++]=z;
    
    }
    
  • ultifinitus
    ultifinitus over 12 years
    Does it have to start with a particular vertex?
  • sigpwned
    sigpwned almost 11 years
    While you're right that counterclockwise is the default winding order (as it's called) for OpenGL, it might be useful to mention that the winding order is actually configurable using glFrontFace.
  • bcrist
    bcrist over 10 years
    This is an old answer, but calling this the right hand rule is likely to cause a great deal of confusion. When dealing with 3D euclidean geometry, the right hand rule almost always refers to the use of your right thumb, index, and middle finger to remember the configuration of the axes in a RH coordinate system, such as is typical in mathematics and OpenGL.
  • genpfault
    genpfault over 4 years
    @Nikos: Nope, doesn't matter which vertex you start with.
  • KeyC0de
    KeyC0de over 4 years
    @genpfault So as long as I'm sending vertices of triangles in counter-clockwise order (or in clockwise order in DirectX), one triangle at a time, it doesn't matter which vertex I start with. This triangle will be a front facing one and as such it will be rendered in the specific frame. Got it. Thank you. By the way, this is a great answer.
  • KeyC0de
    KeyC0de over 4 years
    @genpfault I forgot to emphasize something else, something that some people may miss at first read. Not only which vertex you start with doesn't matter, but also which triangle you start with doesn't matter either! (I'm referring to the index buffer vertex indices.) No problem and thanks again!