# Effect shader world pos calculation!

Hi All
I am just have a mess around with an effect shader and I am just wanting to something simple and recreate the world coordinate for rendered pixels. I have ‘borrowed’ a shader found on these forums but it isn’t giving the expected results. Can anyone suggest where I might be going wrong. When I output the calculated world pos as a color I get a lot or red and as I rotate and move the camera instead of the colors staying the same shade they all change, it seems to returning positions relative to the bottom left of the screen in camera space or something.

``````Shader "ShowPos Effect Shader"
{
Properties
{
_MainTex ("Base (RGB)", 2D) = "white" {}
}

{
Pass
{
ZTest Always Cull Off ZWrite Off
Fog { Mode off }

CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
#include "UnityCG.cginc"

uniform sampler2D _MainTex;
uniform float4 _MainTex_TexelSize;

struct appdata
{
float4 vertex : POSITION;
float3 texcoord : TEXCOORD0;
};

struct v2f
{
float4 pos : SV_POSITION;
float4 uv : TEXCOORD0;
float3 ray : TEXCOORD1;
};

v2f vert (appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = ComputeScreenPos (o.pos);
o.ray = mul (UNITY_MATRIX_MV, v.vertex).xyz * float3(-1,-1,1);

// v.texcoord is equal to 0 when we are drawing 3D light shapes and
// contains a ray pointing from the camera to one of near plane's
// corners in camera space when we are drawing a full screen quad.
o.ray = lerp(o.ray, v.texcoord, v.texcoord.z != 0);

return o;
}

float4x4 _CameraToWorld;

float4 frag (v2f i) : COLOR
{
i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
float2 uv = i.uv.xy / i.uv.w;

depth = Linear01Depth(depth);
float4 vpos = float4(i.ray * depth, 1);
float3 wpos = mul(_MyCameraToWorld, vpos).xyz;

return float4(normalize(wpos), 1);
}

ENDCG
}
}

Fallback off
}
``````

Mmm I guess this shader gets the viewspace position, bit stuck on getting a world space has anyone done this before?

Lots of crazy stuff happening in that shader, bits and prices copied from Unity’s internal shadowmapping shader??? I’m not sure if the texture uv’s are actually going to be constructed in the way you want. Perhaps if you told us what you’re trying to do?

I suggest trying to simplify things and write a shader that does nothing but recolors the output based on world position reconstructed form the depth texture, kinda pointless but less variables will make it easier for people here to help and once you have that solved you can re-introduce the math for whatever effect it is you’re trying to recreate.

one way of calculating world position of a pixel in world coordinates is:
camerapos + float3(clipspacepos.xy + CameradirectionVector * depth (z))

EDIT: camera direction vector should reach to the end of far clip plane and depth should be 0-1

Keep in mind the opengl d3d differences in mind when passing your cameradirectionvector

Or,

float depth = depthsampler (Clipspace)
// H is the viewport position at this pixel in the range -1 to 1.
float4 H = float4((uvCoord.x) * 2 - 1, (uvCoord.y) * 2 - 1, depth, 1);
float4 D = mul((camera.projectionMatrix * camera.worldToCameraMatrix).inverse; (passed from your script), H);
return D/D.w;

EDIT: I am not sure about the second option, but that is what im using to generate screenspace water effect and it works on directx.

EDIT: Corrected second method

1 Like

Errr, second method i posted above was wrong(inverted), i corrected it.
If you still have trouble, use the attached image as guide. Your final image should look like it while at position 0,0,0 and looking straight forward.

I ran into an issue after getting an image similar to aubergine’s and using the second method detailed. When I move the camera around, the colors on the sphere change, indicating that these aren’t the actual world coordinates. I got a bit closer by modifying the method:

``````...
float4 D = mul((camera.projectionMatrix * camera.worldToCameraMatrix).inverse; (passed from your script), H);
D = D/D.w;
return D + float4(_WorldSpaceCameraPos, 1);
``````

With a unit sphere at the origin, it looks like the following:

This works and the colors on the sphere stay consistent as you move the camera around until you translate the camera on the Y axis, which modifies the computed world space position on the Y axis. The issue is best seen with a plane perpendicular to the Y axis at the origin. The effect seems to be too large to be a floating point error. Any ideas on what the issue could be?

Fully working solution with scene on GitHub: https://github.com/zezba9000/UnityMathReference/tree/master/Assets/Shaders/DepthBuffToWorldPos