EDIT While I believe that the principles mentioned herein are correct, there are some mistakes made by me, namely some sign errors. In a post furthur below I correct this. /EDIT
I don't know the solution directly, but I know that OpenGL actually does handle linear perspective projection differently. The following is what I think gives the solution, but please check it double. I'm also not sure about any side effects. If you try it out please let me know what happens ...
If using glFrustum, then the last 2 rows of the projection matrix are
[ 0 0 (f+n)/(n-f) 2fn/(n-f) ][ 0 0 -1 0 ]
When multiplying this with an arbitray vertex position [ x y z 1 ]T and normalizing the result, then
z' := (f+n)/(f-n) - 2fn/(f-n)/z
is the transformed z. So, the limits are
z'(z=n) = -1
z'(z=f) = +1
In D3D the equivalent stuff is (see matrix in the cited article)
z' := f/(f-n) - fn/(f-n)/z
and hence the limits are
z'(z=n) = 0
z'(z=f) = +1
as is affirmed by the article. The trick was to alter the z' formula by dividing by f and multiplying by z, so that
z" := z'*z/f = z/(f-n) - n/(f-n)
and the limits are still
z"(z=n) = 0
z"(z=f) = +1
Now you're doing the same in OpenGL, yielding in
z" := z*(f+n)/(f-n)/f - 2n/(f-n)
with the limits
z"(z=n) = -n/f > -1
z"(z=f) = +1
Since z clipping is done on [-1,+1] but z''(z=n) is approx. 0, you'll have geometry located before the near "clipping" plane visible.
What you want instead is a linear function
z"(z) := a*z + b
that fulfills OpenGL's limits. That leads to 2 functions
z"(z=n) = a*n + b == -1
z"(z=f) = a*f + b == +1
what can be solved to
a = 2/(f-n)
b = -(n+f)/(f-n)
so that
z" = 2z/(f-n) - (n+f)/(f-n)
Dividing by w=-z and comparing the co-efficients with OpenGL's matrix values shows that
proj.m33 = -a
proj.m43 = -b
would produce the correct matrix.
Oh well, I hope that I made no mistake :)
[Edited by - haegarr on May 27, 2008 3:44:27 AM]