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