I'm working on a project for school where I need to implement a fisheye shader, and I'm struggling with the process for determining the depth values of the vertices. I know that for a point in space P1 = (x, y, z, w) that P * my projection matrix should result in a new point P2 = (a, b, c, d) where for any point between the near and far clipping planes P2.c/P2.d results in a number between 0 and 1.
My hlsl vertex shader contains this code where input.Position is the raw Vertex Position
float distance3d(float4 input) // Finds 3d hypotenuse
{
return sqrt(input[0] * input[0] + input[1] * input[1] + input[3] * input[3]);
}
//Vertex Position data
float4 worldPosition = mul(input.Position, World); // object to world xform
float4 viewPosition = mul(worldPosition, View); // world to camera xform
output.Position = mul(viewPosition, Projection); // perspective xform
float z = output.Position[3];
float distance = distance3d(output.Position) * (z < 0 ? -1 : 1);
float f = Projection[2][2];
float n = Projection[3][2];
output.Position[3] = distance;
output.Position[2] = -distance * f + square * n;
And my projection matrix is generated using this code.
new Matrix( -focalLength * Math.Sin(-FOV), 0, 0, 0,
0, -focalLength * Math.Sin(-FOV), 0, 0,
0, 0, -farPlane / (farPlane - nearPlane), -1,
0, 0, -farPlane / (farPlane - nearPlane) * nearPlane, 0);
Normal Projection: https://i.sstatic.net/nmS1R.jpg
Fisheye Projection: https://i.sstatic.net/KNwaz.jpg
As you can see, distant triangles render in front of near triangles.
Thanks for the help.
I solved my issue by changing from modifying the Projected z position (output.Position[3]) to modifying the z Position relative to the camera (viewPosition[2]). I output.Position[2] needs to include the hypotenuse instead of the raw z value for the depth calculations to work correctly.
float4 worldPosition = mul(input.Position, World); // object to world xform
float4 viewPosition = mul(worldPosition, View); // world to camera xform
float z = viewPosition[2];
float square = distance3d(viewPosition) * (z < 0 ? -1 : 1);
viewPosition[2] = square;
output.Position = mul(viewPosition, Projection); // perspective xform
output.wPosition = mul(input.Position, World);