## Depth Sorting Polygons

thaeez
Unregistered

Post: #1
I am using a lot of blended (semi-transparent) polygons and thus need to draw them from back to front for my scene to appear correct. I am having a lot of trouble getting this to work, basically my code goes like this:

glViewport(...);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
gluPerspective(...);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();

gluLookAt([CameraPosition getVectorX], [CameraPosition getVectorY], [CameraPosition getVectorZ], 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(cameraRotation, 0.0, 1.0, 0.0);

/* Draw primitives... */

/* Then, to get primitive distances: */

GLdouble m[16];
glGetDoublev(GL_MODELVIEW_MATRIX, m);

/* For each vertex in the primitive: */
matrixVertexMultiply(m, &x, &y, &z);

/* Matrix multiply code: */

- (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z
/* Multiplies hte vertex (x,y,z) by the matrix pointed to by sourceMatrix. */
{
float a11 = sourceMatrix[ 0], a12 = sourceMatrix[ 1], a13 = sourceMatrix[ 2], a14 = sourceMatrix[ 3];
float a21 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a23 = sourceMatrix[ 6], a24 = sourceMatrix[ 7];
float a31 = sourceMatrix[ 8], a32 = sourceMatrix[ 9], a33 = sourceMatrix[10], a34 = sourceMatrix[11];
float tx = *x;
float ty = *y;
float tz = *z;

*x = a11 * tx + a12 * ty + a13 * tz + a14;
*y = a21 * tx + a22 * ty + a23 * tz + a24;
*z = a31 * tx + a32 * ty + a33 * tz + a34;
} /* - (void) matrixVertexMultiply: (GLdouble *) sourceMatrix X: (float *) x Y: (float *) y Z: (float *) z */

This should give me where each transformed point is (given the current MODELVIEW matrix) - I then calculate the distance from this transformed point to my 'camera' location (using sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)) to get the distance from the 'camera' for each point. The distances of all the points in a primitive are then averaged to get an average distance to the primitive. This is the value that I am depth sorting with but I keep getting unexpected results depending on the rotations being used (sometimes it draws in the correct order and looks fine as in the case of x-axis rotations but it does not draw in the correct order for other rotations). What am I missing? Do I need to multiply the camera location by the current matrix as well? Do I need to multiply the projection matrix somewhere?

Basically, given a list of vertices in a primitive, a 'camera' location (as defined by gluLookAt), and the current transformation matrices, I need to compute the distance to the 'camera'. Any suggestions as to what I'm doing wrong or a better way of doing this would be greatly appreciated. Is there a good depth sort tutorial or some nice example code that resembles what I need out there? Thnaks in advance,

thaeez
Member
Posts: 72
Joined: 2006.10
Post: #2
It really depends on the way your scene manages polygons, but when I have a lot of blended polygons, I start by drawing all the opaque polygons, then I disable writting to the depth buffer before drawing the blended polygons. That way, depth sorting is not necessary at all.

on another note, for your problem, when you get the modelview matrix, you get a trasposed matrix. So, you should use a transposed matrix ( with GL_ARB_transpose_matrix ), or change
Code:
```float a11 = sourceMatrix[ 0], a12 = sourceMatrix[ 1], a13 = sourceMatrix[ 2], a14 = sourceMatrix[ 3]; float a21 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a23 = sourceMatrix[ 6], a24 = sourceMatrix[ 7]; float a31 = sourceMatrix[ 8], a32 = sourceMatrix[ 9], a33 = sourceMatrix[10], a34 = sourceMatrix[11];```

To:

Code:
```float a11 = sourceMatrix[ 0], a21 = sourceMatrix[ 1], a31 = sourceMatrix[ 2], a41 = sourceMatrix[ 3]; float a12 = sourceMatrix[ 4], a22 = sourceMatrix[ 5], a32 = sourceMatrix[ 6], a42 = sourceMatrix[ 7]; float a13 = sourceMatrix[ 8], a23 = sourceMatrix[ 9], a33 = sourceMatrix[10], a43 = sourceMatrix[11];```

Just my 2 cents.

- Sohta
thaeez
Unregistered

Post: #3
Thanks for the help Sohta, your suggestion fixed my problem and surely saved me many, many hours - I can now rotate on any axis and correctly determine draw order (kind of...). The problem that I am still having is when a number of primitives are lined up horizontally or vertically and the rotations are such that an entire row of primitives have the same Z value after multiplying their points through the current MODELVIEW matrix. In this situation, the top to bottom (when dealing with a vertical row) or the left to right (when dealing with a horizontal row) draw order is not always correct - they all have the same Z value and I need to draw the furthest from the camera, not simply the furthest Z distance. Anyways, to get this value, it's still not really clear to me if I need to consider:

a: MODELVIEW matrix ONLY...
b: PROJECTION & MODELVIEW matrix (multiply point through projection, then through modelview matrix)
c: MODELVIEW & PROJECTION matrix (multiply point through modelview, then through projection matrix)
or
d: none of the above: specify please _______________. =)

Again, I am using:

gluPerspective(); /* Set up a perspective 3D view */
gluLookAt(); /* Position the camera. */

When depth sorting, do you guys use averageZ, minZ, or maxZ - what are the pros and cons to using these different methods. How do I compute the distance form the transformed point to 'camera' point as specified in gluLookAt()? Thanks again for the help, and sorry for so many questions...

Oh yeah, Sohta, you were suggesting that depth sorting is not necessary if you draw opaque polys first, then blended ones with the depth buffer read only. This works most of the time, but draw order is still important when considering many semi-transparent polygons and a read-only depth buffer (red glass in front of blue glass looks different that the opposite combination). Of course, one can remedy this by using an additive blending function, but in my humble opinion, these blending functions only look realistic when used with special effects such as explosions, fire, etc. This leaves us with a lot of manual depth sorting to do (all polys that use blending...) if we want the transparent polys behind other transparent polys to be drawn correctly.

Thanks again and sorry for the long reply,

thaeez