Direct3D Z order question
Aric Cyr
Aric.Cyr at gmail.com
Mon Feb 13 04:17:27 CST 2006
Stefan Dösinger <stefandoesinger <at> gmx.at> writes:
> I don't know much about GL drawing, but I noticed that GL clips primitive
> parts that are outside the Z range. So if vertices that were processed into a
> [0,5.3333] Z range are drawn into a [0,1.0] viewport leads to missing
> vertices. I guess I have to attend a few more courses at univertiy to really
> understand what exactly is going on.
There are two components to Z buffering, the first is the Z range and the second
is the near and far planes. These work together to determine whether a vertex
is clipped (based on the near/far planes) and to what Z value it will obtain.
In OpenGL, first the vertices are clipped against the near/far planes (as
specified by glFrustum), then modified for perspective. The near plane is
mapped to z=-1 and far plane is z=1. All non-clipped vertices are now in [-1,1]
(called normalized depth coordinates). Now window (i.e. viewport) depths are
calculated based on the Z depth range as specified by glDepthRange(r_near,
r_far). Window depth coords range [0,1] though, so a linear transform is
applied to get from [-1,1] => [r_near,r_far].
> The relevant code is at dlls/wined3d/drawprim.c, line 186, vtx_transformed is
> true, useVS and vtx_lit are false.
Seems to me that the call to glOrtho should be replaced by a call to
glViewport(x,y,width,height) and glDepthRange(near,far). Since your vertices
are already in viewport coordinates, according to the comment in the code, how
does something like the following work for you:
{
.....
/* reset projection matrix before modelview since
the glTranslate below should really be applied to
the modelview matrix */
glMatrixMode(GL_PROJECTION);
checkGLcall("glMatrixMode(GL_PROJECTION)");
glLoadIdentity();
checkGLcall("glLoadIdentity");
glMatrixMode(GL_MODELVIEW);
checkGLcall("glMatrixMode(GL_MODELVIEW)");
glLoadIdentity();
checkGLcall("glLoadIdentity");
/* Set up the viewport to be full viewport */
X = This->stateBlock->viewport.X;
Y = This->stateBlock->viewport.Y;
height = This->stateBlock->viewport.Height;
width = This->stateBlock->viewport.Width;
minZ = This->stateBlock->viewport.MinZ;
maxZ = This->stateBlock->viewport.MaxZ;
glViewport(X, Y, width, height);
checkGLcall("glViewport");
/* depth ranges will be clamped to [0, 1] */
glDepthRange(minZ, maxZ);
checkGLcall("glDepthRange");
/* Window Coord 0 is the middle of the first pixel,
so translate by half a pixel (See comment above glTranslate
below)
*/
glTranslatef(0.5, 0.5, 0);
checkGLcall("glTranslatef(0.5, 0.5, 0)");
if (This->renderUpsideDown) {
glMultMatrixf(invymat);
checkGLcall("glMultMatrixf(invymat)");
}
.....
}
Regards,
Aric
More information about the wine-devel
mailing list