I’m trying to get the world position from the depth buffer for an image effect. I have actually got it working for standalone builds using the following code snippet:
// for fast world space reconstruction
uniform float4x4 _FrustumCornersWS;
uniform float3 _CameraWS; // camera's world space position (ie camera's Transform.position)
uniform float4 _CameraDir; // xyz = camera forward direction, w = near plane distance
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float2 uv_depth : TEXCOORD1;
float4 interpolatedRay : TEXCOORD2;
};
v2f vert (appdata_img v)
{
v2f o;
half index = v.vertex.z;
v.vertex.z = 0.1;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord.xy;
o.uv_depth = v.texcoord.xy;
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
o.uv.y = 1-o.uv.y;
#endif
o.interpolatedRay = _FrustumCornersWS[(int)index];
o.interpolatedRay.w = index;
return o;
}
half4 frag (v2f i) : SV_Target
{
// Reconstruct world space position and direction
float rawdpth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, -i.uv_depth);
#ifdef CAMERA_ORTHOGRAPHIC
float3 nearPlaneDist = _CameraDir.w; // from camera
float3 camDir = _CameraDir.xyz;
float3 nearPlaneOffset = camDir * nearPlaneDist; // relative to camera pos
float3 camPos = _CameraWS + nearPlaneOffset; // pretend the camera pos is at the near plane
float3 rayFar = i.interpolatedRay - nearPlaneOffset; // relative to camera near plane
float3 rayVec = camDir * dot(rayFar, camDir); // relative to rayOrigin
float3 rayOrigin = rayFar - rayVec; // relative to camera
// apparently unity inverted the Z buffer when not using Linear01Depth: https://docs.unity3d.com/Manual/UpgradeGuide55.html
#if UNITY_VERSION >= 550
rawdpth = 1 - rawdpth;
#endif
float3 rayCast = (rayFar - rayOrigin) * rawdpth; // just use the raw depth texture for ortho
float3 wsPos = camPos + rayOrigin + rayCast;
#else
float3 wsDir = i.interpolatedRay * Linear01Depth(rawdpth); // for PERSPECTIVE
float3 wsPos = _CameraWS + wsDir;
#endif
// other stuff is here...
}
So this appears to work fine for windows, but doesn’t work for android. On android, the positions are all skewed. I don’t know if my solution is best (it seems quite convoluted for orthographic).
I have looked at the source for Unity’s global fog, and it appears that it doesn’t support orthographic cameras. I’m not sure where to look next.
Has anyone got experience with reconstructing positions in image effects?
Cheers.