Cant get the World Pos from Depth!

Still having trouble with the whole getting world pos from depth in a shader. Ive taken the code from Lighting.cginc and put it in my shader but just cant get the right results. In the video below you will see the red area is meant to show a world position but it moves around and distorts as the camera moves, the shader is below, can any of the expert Shader authors out there give me a clue as to how I can get this working?

Edit: It says in the docs it that _CameraToWorld is a built in matrix but I need to add it to the shader code, is this wrong? Also should I be manually be setting anything such as the camera matrix, none of the unity post effects do so so I assume not.

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

    SubShader
    {
        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;
            }

            sampler2D _CameraDepthTexture;
            float4x4 _CameraToWorld;

            float4 frag (v2f i) : COLOR
            {
                i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
                float2 uv = i.uv.xy / i.uv.w;
                
                float depth = tex2D(_CameraDepthTexture, uv).r;
                depth = Linear01Depth(depth);
                float4 vpos = float4(i.ray * depth, 1);
                float3 wpos = mul(_CameraToWorld, vpos).xyz;

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

            ENDCG
        }
    }

    Fallback off
}

float3 wpos = mul(vpos, _CameraToWorld).xyz;

Thank you for the help. I have tried that before but that just seems to move the red dot to the lower left hand corner. In the shader the value _Pos is a world position I want to show as a red disc but as you can see as I move the camera around it just stays in the lower left corner, so there is something wrong with my world pos calculation in the shader but it’s the code unity uses so not sure how Ive managed to mess it up :slight_smile: Ive tried adding the camera position, subtracting it, doing it all in view space, all sorts but cant get anything to work right, I blame my cold :slight_smile:

Edit: Is it right that the xy parts of i.ray are always 0 as that is what Iam getting.

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

    float depth = tex2D(_CameraDepthTexture, uv).r;
    depth = Linear01Depth(depth);
    float4 vpos = float4(i.ray * depth, 1);

    float3 wpos = mul(vpos, _CameraToWorld).xyz;
    float3 tocentre = wpos - _Pos;

    float dist = length(tocentre);

    float4 rgb = tex2D(_MainTex, uv);

    if ( dist < _Radius )
        rgb.r += 0.5f;

    return rgb;
}

Ive been told by another user that in image effect shaders UNITY_MATRIX_MV is always identity, is this true? Also could someone shed some light on the values that are in vertex and texcoord when passed to an image shader, is vertex in world space or camera space, and some comments from unity code say texcoord is already a Ray from the camera to a corner, if so why is the ray recalculated? Also why does it get multiplied by float3(-1, -1, 1) and what is the purpose of the lerp?

Still having trouble with this, any experts out there who can shed any light on how to correctly get a world position, I am failing dismally as this ‘simple’ task :frowning:

Desperate plea can anyone provide a working example of getting recreating a world position in a post effect shader, wasted so much time trying to get this to work, just cant figure out all the input values, the docs just dont seem to give enough info. So a desperate cry for help from Aras or or a shader expert for an quick example of a working shader to reconstruct world position :slight_smile:
Going slightly mad and I have so many other things to work on :slight_smile:
Chris

I don’t completely understand what you are looking for, but this may help. I just changed the water shader to account for distance from the camera. Here’s how:

In struct v2f add:
float3 eyeDir : TEXCOORD4;

In vert shader add:
o.eyeDir = WorldSpaceViewDir(v.vertex);

In pixel shader add:
float eyeDist = dot(i.eyeDir, i.eyeDir);

I don’t have the solution, but I can tell you that I gave up trying to calculate the world pos from the provided depth map and wrote a shader that writes the worldpos to a texture, then use that as an input texture to whatever shader I need it for.
Sure, it is much more expensive, but it does the job. If you’re interested, I can see if I have the code lying around…

That is interesting, so it’s not just me that can’t figure it out, that makes me feel a little better :slight_smile: I would be interested in seeing your solution, but it is very annoying that I cant figure out a solution.
Chris