# Reconstruct world pos from planar reflection depth texture

I’m working on a water shader post effect (using the post processing stack) with planar reflections. Everything works great except I’m unable to get the right shading for underwater internal reflections. That is, where the light penetrates the water, bounces off an object, reflects back off the water surface and reaches the camera. In order to do this calculation I render a planar reflection into a colour texture and depth texture. I need to reconstruct the world position of the reflected fragment from the depth value so that I can calculate the distance light must travel to reach it through the water volume (exact same calculation I use for non-reflected fragments).

Sounds good? Well, unfortunately my knowledge of projection matrices is not great so I don’t actually know how to transform the planar reflection depth value into a world space position; I was hoping someone here could nudge me in the right direction.

Here’s what I do to reconstruct the world position of a non-reflected fragment (adapted from here ):

``````// in script
var p = GL.GetGPUProjectionMatrix(camera.projectionMatrix, false);
p[2, 3] = p[3, 2] = 0.0f;
p[3, 3] = 1.0f;
var clipToWorld = Matrix4x4.Inverse(p * camera.worldToCameraMatrix) * Matrix4x4.TRS(new Vector3(0, 0, -p[2, 2]), Quaternion.identity, Vector3.one);
material.SetMatrix("_ClipToWorld", clipToWorld);

struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 texcoordStereo : TEXCOORD1;
float3 worldDirection : TEXCOORD2;
};

Varyings Vert(AttributesDefault v)
{
VaryingsGreyscale o;
o.vertex = float4(v.vertex.xy, 0.0, 1.0);
o.texcoord = TransformTriangleVertexToUV(v.vertex.xy);

#if UNITY_UV_STARTS_AT_TOP
o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0);
#endif

o.texcoordStereo = TransformStereoScreenSpaceTex(o.texcoord, 1.0);

float4 clip = float4(o.vertex.xy, 0.0, 1.0);
o.worldDirection = mul(_ClipToWorld, clip).xyz - _WorldSpaceCameraPos.xyz;

return o;
}

// frag
sceneDepth = LinearEyeDepth(sceneDepth); // in world units

// scene pos
float3 worldSpaceScenePos = i.worldDirection * sceneDepth + _WorldSpaceCameraPos;
``````

I’ve tried the same method for the planar reflection texture (but using the reflection camera’s position and matrices) but this doesn’t seem to work.

Here are a few WIP screenshots:

Might be just translation error on my part, are you talking about the underwater water surface reflection?

Yes that is correct. It is a planar reflection of what is under the water surface and the context is when the camera is below the water level as opposed to above it (where the reflections would be of things above the water surface). The first screenshot I posted exhibits the effect. The colour of the reflection is slightly off due to the fact that I don’t know how to calculate its world position (you’ll notice it is a bit darker).

Since I created this thread I realised I could render the planar reflection with a custom shader which would calculate those colours without needing to transform to the scene camera space. Because this is integrated into the Post processing stack pipeline, applying the effect for other arbitrary cameras is probably a bit tricky, haven’t looked into it yet.