Direct3D Z order question

Aric Cyr Aric.Cyr at
Mon Feb 13 04:17:27 CST 2006

Stefan Dösinger <stefandoesinger <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 */


            /* 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);

            /* depth ranges will be clamped to [0, 1] */
            glDepthRange(minZ, maxZ);

            /* Window Coord 0 is the middle of the first pixel, 
               so translate by half a pixel (See comment above glTranslate
            glTranslatef(0.5, 0.5, 0);
            checkGLcall("glTranslatef(0.5, 0.5, 0)");
            if (This->renderUpsideDown) {


More information about the wine-devel mailing list