Sorry to necro this post but here in the future I am trying to port Ben’s code to Shadergraph. I have written a port of his code for a Custom Function node, but the behaviour is not the same. I’ve poured over it repeatedly and cannot find a single mistake or error, yet the behaviour is not correct.
Do you see any mistakes?
Pictured: Left: my code, Right: Ben’s code.

inline float rayPlaneIntersection(float3 rayDir, float3 rayPos, float3 planeNormal, float3 planePos)
{
float denom = dot(planeNormal, rayDir);
denom = max(denom, 0.000001); // avoid divide by zero
float3 diff = planePos - rayPos;
return dot(diff, planeNormal) / denom;
}
void VerticalZDepth_float(
float3 vertexPos, // object-space vertex position
float4x4 ObjectToWorld, // Object-to-World matrix
float4x4 Matrix_V, // View matrix
float4x4 Matrix_P, // Projection matrix
float4x4 Matrix_I_V, // Inverse View matrix
float4x4 Matrix_VP, // ViewProjection matrix
float3 WorldSpaceCameraPos, // World-space camera position
out float4 position // modified clip-space position (xyzw)
)
{
// billboard mesh towards camera
float3 vpos = mul((float3x3) ObjectToWorld, vertexPos);
float4 worldCoord = float4(ObjectToWorld[0][3], ObjectToWorld[1][3], ObjectToWorld[2][3], 1.0);
float4 viewPos = mul(Matrix_V, worldCoord) + float4(vpos, 0.0);
float4 clipPos = mul(Matrix_P, viewPos);
// calculate distance to vertical billboard plane seen at this vertex's screen position
float3 planeNormal = normalize(float3(Matrix_V[2][0], 0.0, Matrix_V[2][2]));
float3 planePoint = float3(ObjectToWorld[0][3], ObjectToWorld[1][3], ObjectToWorld[2][3]);
float3 rayStart = WorldSpaceCameraPos;
float3 invViewPos = mul(Matrix_I_V, float4(viewPos.xyz, 1.0)).xyz;
float3 rayDir = -normalize(invViewPos - rayStart);
float dist = rayPlaneIntersection(rayDir, rayStart, planeNormal, planePoint);
// calculate the clip space z for vertical plane
float4 planeOutPos = mul(Matrix_VP, float4(rayStart + rayDir * dist, 1.0));
float newPosZ = (planeOutPos.z / planeOutPos.w) * clipPos.w;
// use the closest clip space z
#if defined(UNITY_REVERSED_Z)
clipPos.z = max(clipPos.z, newPosZ);
#else
clipPos.z = min(clipPos.z, newPosZ);
#endif
position = clipPos;
}
My only lead is my suspicion that the tables are built differently, and that index positions as well as rows and columns do not directly equate the way I have written here:
float3 planePoint = unity_ObjectToWorld._m03_m13_m23;
float3 planePoint = float3(ObjectToWorld[0][3], ObjectToWorld[1][3], ObjectToWorld[2][3]);
Are these not equivalent? How would I determine if they are or are not equivalent? How do I make them equivalent?
