I am trying to find the point along the x axis where a plane with normal pointing along the x axis would flip to back facing after perspective projection. Essentially the red line in this image.

My first attempt to find it I just sampled along the x axis checking if a triangle there was back facing after projection. This only gave me an approximation but I could make the approximation as accurate as I wanted by just sampling more planes so I used this as a baseline to verify other solutions.

I then tried the following:

vec4 center = projection.inverse()*vec4(0,0,0,1);
center /= center.w;
float d = dot(center.xyz, vec3(1,0,0));
vec3 point = vec3(1,0,0)*d;

But this did not work, it was close but not right. See this image, the red line is the sampled point and the blue is the one calculated from that.

I then tried changing the calculation for center to projection.inverse()*vec4(0,0,-1,1) to see what that would look like. With the the sampled point in red, the blue line being the previous version and the green the new version. I got the following image which as you can see is still not correct.

But I noticed that the green was always directly between the blue and the red so I tried the following.

vec4 c1 = projection.inverse()*vec4(0,0,0,1);
c1 /= c1.w;
float d1 = dot(c1.xyz, vec3(1,0,0));
vec4 c2 = projection.inverse()*vec4(0,0,-1,1);
c2 /= c2.w;
float d2 = dot(c2.xyz, vec3(1,0,0));
float d = (d2-d1)*2 + d1;
vec3 point = vec3(1,0,0)*d;

Which seems to be correct but I have no idea why that works. It is always extremely close to the sampled point so I assume it is correct.

My question is why does this work?

  • \$\begingroup\$ Wouldn't it be just the x coordinate of the camera? \$\endgroup\$
    – lisyarus
    Jan 7 at 15:47

Essentially you have to project worldspace camera position on line. The position of projection would be the point where normals flip.

enter image description here

Having arbitrary point on line, normalized line direction and camera pos you can do following:

float d = dot(CamPos.xyz - LinePos.xyz, NrmLineDir.xyz);
vec3 point = LinePos.xyz + NrmLineDir.xyz * d;

I think what you did was overcomplicated solution of what I wrote here, so removing some of the code would result in same solution.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.