PDA

View Full Version : back face culling



gmseed
11-22-2011, 06:38 AM
Hi

When reading about OpenGL we see that it supports face culling; eg:



@Override
public void init(GLAutoDrawable gLDrawable)
{
GL gl = gLDrawable.getGL();
//...
// enable face culling
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
gl.glFrontFace(GL.GL_CW);
}


This is easy to understand for a 2D triangle with vertices [v0,v1,v2] ordered either [v0,v1,v2] for an anticlockwise vertex ordering or ordered [v0,v2,v1] for a clockwise ordering.

However, the texts always fail to discuss in detail how to handle the 3D case. For example, how are we to handle the following list of triangle vertices if the ordering is not specified:



class CubeTriangles
{
public static int vertexCount = 12 * 3;

public static final float vertexData[] =
{
0.25f, 0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,

0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,

0.25f, 0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,

0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,

-0.25f, 0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,
//...


If the vertices are to be correctly ordered when filling a vertex buffer then how is the clockwise/anticlockwise ordering resolved? Let's say a triangle has vertices [v0,v1,v2] and the cross-product of v0v1 x v0v2 gives a normal n about which the vertices are ordered anti-clockwise. Viewed from the opposite side [-n] then the vertices are ordered clockwise. Thus, I can't see how the ordering is resolved unless a fixed reference vector is specified. This may be possible for triangles making up a sphere but what about twisted and convoluted surfaces?

If anyone knows the established and robust way of handling 3D face ordering/culling I'd appreciate hearing from you.

Thanks

Graham

Ed Daenar
11-22-2011, 07:29 AM
Backface culling is basicly resolved after projection,so it's escencialy done in 2D. In 3D, you would do it checking normals against the camera's view vector, for example in a geometry shader.

What that means is that what a back face is and what a front face is happens to be completely arbitrary, so you need a convention set by yourself to determine that. The whole "Clockwise and counter clockwise" thing only has a meaning in 2D.

An inverted complex figure makes just as much sense as one that isn't.

remdul
11-28-2011, 01:26 AM
As Ed Daenar said.


For example, how are we to handle the following list of triangle vertices if the ordering is not specified
For backface culling to work, the polygon vertex order must be known. This information is stored implicitly in your vertex array/index array.

gmseed
12-15-2011, 04:08 AM
Ed Daenar said: "In 3D, you would do it checking normals against the camera's view ".

I have a couple of questions:

1) It's common in a 3D view to use the mouse to rotate a model. Are you saying that the normals have to be recomputed each time a model is rotated? For a large model this can be expensive.

2) It's the same issue when specifying vertex normals for lighting. The OpenGL FAQs says to just compute the crossproduct - fine but which way to point? A view can have several different lights and unlike a single camera point we do not have a single reference point for resolving the correct sense of a surface vertex for lighting.

3) Some surfaces/solids it can be detrermined what is the inside and what is outside; eg a sphere. But for many surfaces the notion of in/out is meaningless.

V-man
12-15-2011, 08:57 AM
1) GL doesn't compute any normals. If you want lighting to work properly, yes you would have to compute normal vectors. You don't need to recompute normals (on CPU side) if you rotate it.

Of course, in your shader, you do have to transform the normals to eye space to compute lighting as usual.

2) It sounds like you need to do 2 sided lighting. That mean you do a dot product in your shader.
result = dot(mynormal, LightVector);

and of result is negative, you flip the normal.
mynormal = -mynormal;

and then do your lighting calculation as usual.

3) See above for 2 sided lighting.