I know mathematics of perspective transformation.

layout(binding = 0, std140) uniform global_buffer {
  layout(offset = 0) vec3 proj_S;
  layout(offset = 16) vec3 proj_C;
  layout(offset = 32) vec3 proj_c1;
  layout(offset = 48) vec3 proj_r1;
vec3 proj_transform(vec3 p) {//[nc-nr*{1,1,0},nc+nr] to [c1-r1,c1+r1], c1 = {0,0,0}, r1 = {1,1,1}
  //p1 = (p*{s,s,1} - (nc - nr*{1,1,0}))/nr*r1*{1,1,2} + (c1 - r1), s = nc[2]/p[2].
  //   = ... 
  return p/vec3(p[2],p[2],1)*proj_S + proj_C;
void main() {
  gl_Position = vec4(proj_transform( POSITION_VIEW ),1.0);

But the unexpected error seems to be the clipping, many out of range triangles have not been clip. Then

I tried some methods, multiplying the vector p1 by p.z (same as last component of nolinear perspective transformation result), that the correct clipping was obtained:

vec4 clipproj_transform(vec3 p) {
  vec3 p1 = p/vec3(p[2],p[2],1)*proj_S + proj_C;
  return vec4(p1, 1.0) * p.z;
void main() {
  gl_Position = clipproj_transform( POSITION_VIEW );
  // gl_Position = vec4(proj_transform( POSITION_VIEW ), POSITION_VIEW.z);

The performance is still normal here, but the depth test have some error. Final, but

Although the gl_FragDepth can be used to fix this error, it is very expensive (at most twice as slow as the original), and there is a hidden danger that perspective interpolation is correct.

vec4 clipproj_transform(vec3 p, out float depth) {
  vec3 p1 = p/vec3(p[2],p[2],1)*proj_S + proj_C;
  depth = p1.z;
  return vec4(p1, 1.0) * p.z;

out float fragin_depth;
void main() {
  gl_Position = clipproj_transform( POSITION_VIEW, fragin_depth );

in float fragin_depth;
void main() {
  gl_FragDepth = fragin_depth;

The goal is,

  1. In order to get more accurate depth, and the transformation of inverse of affine projection matrix will produce large errors.
  2. I can't easily use affine depth.
  • So I want to make a really correct perspective, but
    because I don't fully understand clipping, although accidentally skip clipping. However, there are still errors in the depth test.
    Finally, I fixed use the method that costs more than twice as much.

Hope the answer. in the any shaderlang, any graphics interface.

  • 1
    \$\begingroup\$ The terse variable names make it somewhat difficult to follow this code. Can you walk us through the algorithm you're using in a more descriptive fashion? I do notice you're forcing the w component to 1, similar to this other recent Q&A. In that case, this was defeating the normal perspective correction applied in later stages of the graphics pipeline, so a similar problem may be affecting your code too. \$\endgroup\$
    – DMGregory
    Sep 28 at 14:45
  • \$\begingroup\$ @DMGregory Thanks your comment. I realized that my question was not accurate enough (updated). Besides, this question should be different from that one, I may want details about clipping. \$\endgroup\$ Sep 30 at 3:08


You must log in to answer this question.

Browse other questions tagged .