# How to do perspective transformation of linear depth in vertex shader

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.

..."XXX.vert"...
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 );
}

..."XXX.frag"...
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.