Face normals for culling

Started by
4 comments, last by skytiger 16 years ago
This is kind of "back to basics" When deciding which faces to cull (based on winding order) does DX calculate the face normal for each face? If so that sounds expensive especially for a static geometry where they are the same every time Would it not make sense to pass DX an array of face normals: - vertices[vi] = vertex - indices[ii] = vi - normals[ii / 3] = face normal or does DX use a more efficient method of deciding between front and back facing faces than I know of - face direction = cross(v2 - v1, v3 - 1) - direction to face in viewspace = v1 - then dot product maybe DX can cache face normals internally? I know the theory of culling but can not find specifics as to how it is implemented in DX / drivers I am doing shadow volumes and need to calculate face normals for all of my occluders so I can create the near and far caps For occluders with static geometry these face normals will be cached and reused It seems a shame that DX will have to recalculate them again (and again) Or am I missing something? Maybe it is cheaper to calculate face normal from vertices in view space than transform a face normal from model space to view space?
Advertisement
Normals would be a quite expensive way of computing the winding order of a polygon. A faster approach, which I suspect is used by most drivers is to project the triangle on the screen, select the topmost vertex (something which is automatically computed when rasterizing), and see if the two others are in the correct left-to-right order or not.

Besides, it's not like there is a single 'view direction' vector to begin with: in your typical projection matrix, every pixel has its own view direction.
i've had the same queries myself. coming from the point of view of someone who has written what i consider a basic software renderer i think it comes down to things like this...

1. precalc'd normals then need to me passed to the renderer which adds to the data being moved around when it may end-up being for a face that's culled before anything is done with it anyway (e.g. behind the camera)

2. any face that doesnt stay absolutely in the one spot will require it's normal manipulated beforehand anyway if you are to then pass it to the renderer, so why not just let the renderer calc it when it decides it needs to instead of giving yourself more work beforehand. e.g. a spinning cube would require it's normals to be 'spun' as well to keep them matching the face and actually, well, being 'normals' and this just adds to potentially unnecessary computations before the renderer has taken charge of things.

3. i wonder if dx doesnt use some real cheap and easy quick-culs to knock-out some data on the cheap e.g. if pointA is left of pointB and PointC, and PointB is above or equal to pointA and pointB, then this faces normal is backface... or something like that. (basically if a face has points that are the epitome of obviously being front/back-face then cull or dont cull etc).

4. i'm probably full of crap

[edit] oh snap, toorhvyk you are like everywhere man!
DX only has to deal with backface culling when it's running in software emulation mode, i.e. Reference Device. In hardware accelerated mode the graphics card performs all backface culling, DX just has to switch a bit to turn on backface culling, that's it. There is no performance penalty for doing backface culling, it's essentially "free".
deathkrushPS3/Xbox360 Graphics Programmer, Mass Media.Completed Projects: Stuntman Ignition (PS3), Saints Row 2 (PS3), Darksiders(PS3, 360)
There is a formula (I can't think of it at the top of my head) that takes in 3 vertices of a triangle and tells you if its vertices are defined in clockwise or counter-clockwise order. DirectX (or the hardware) projects the vertices onto the screen and uses that formula. The programmer tells DirectX which winding order they would like culled and those triangles are not rendered. From what I see it has nothing to do with normals.
Hope that helps,
zach297




the formula that i know

is to take the three vertices in projection or screen space (v1, v2, v3)
(in original order)

calculate the cross product: Cross(v2 - v1, v3 - v1)

and check polarity of z

the clockwise thing works because:

Cross(v2 - v1, v3 - v1)

returns a normal in the opposite direction from:

Cross(v3 - v1, v2 - v1)

i guess because the hardware only needs to check Z

it doesn't have to do a full cross product - just enough to calculate polarity of Z

vector cross product = (ax, ay, az) X (bx, by, bz)

z = ax * by - ay * bx

presumably testing for polarity on a float is as easy as for a signed binary number

so that reduces to:

z = sign(ax) * sign(by) - sign(ay) * sign(bx)

which is very cheap

This topic is closed to new replies.

Advertisement