Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Render Texture Distance to World Pos

Discussion in 'Shaders' started by Lycake, Feb 1, 2020.

  1. Lycake

    Lycake

    Joined:
    Jun 8, 2013
    Posts:
    7
    Hello,

    I am using a shader on a render texture. I only want that effect, if the vertex is in range of a specific point in the scene. For that to work, I need to know the original world position of that vertex/pixel.

    As far as I can tell, I need to calculate from the screenspace back to worldspace. For that I guess I need something like a Camera2World and projection matrix that I give via scipt to the shader, aswell as the depth to that pixel from the camera and then... do some calculations. However, I am at a loss at what matrix I need to give to the shader exactly, how to get the depth to a pixel and how to calculate it properly.

    I tried to use camera.cameraToWorldMatrix together with something like LinearEyeDepth of the _CameraDepthTexture, but I can't seem to get it to work. I find it really difficult to debug shaders :/

    Any help would be much appreciated.
    Thank you!
     
  2. Namey5

    Namey5

    Joined:
    Jul 5, 2013
    Posts:
    188
    To find the world space position of a pixel in a post-processing shader (which is how I read this scenario), you can find the view-space positions of the 4 far-plane frustum corners in the vertex shader (so that they will be blended per-fragment, thus giving us per-pixel view directions). Multiplying this by [0,1] linear depth gives you the view-space position of the pixel, which can then be transformed to world space, i.e;

    Code (CG):
    1. ...
    2.  
    3. float4x4 _InvProjectionMatrix;    //Pass this in via 'camera.projectionMatrix.inverse'
    4. float4x4 _ViewToWorld;    //Pass this in via 'camera.cameraToWorldMatrix'
    5.  
    6. struct v2f
    7. {
    8.     float4 pos : SV_POSITION;
    9.     float2 uv : TEXCOORD0;
    10.     float4 viewDir : TEXCOORD1;
    11. };
    12.  
    13. v2f vert (appdata v)
    14. {
    15.     v2f o;
    16.     o.pos = UnityObjectToClipPos (v.vertex);
    17.     o.uv = v.uv;
    18.     o.viewDir = mul (_InvProjectionMatrix, float4 (o.uv * 2.0 - 1.0, 1.0, 1.0));
    19.     return o;
    20. }
    21.  
    22. half4 frag (v2f i) : SV_Target
    23. {
    24.     float depth = Linear01Depth (tex2D (_CameraDepthTexture, i.uv).r);
    25.  
    26.     //Perspective divide and scale by depth to get view-space position
    27.     float3 viewPos = (i.viewDir.xyz / i.viewDir.w) * depth;
    28.     //Transform to world space
    29.     float3 worldPos = mul (_ViewToWorld, float4 (viewPos, 1));
    30.  
    31.     //Fill a sphere around the origin
    32.     return 1.0 - saturate (distance (0, worldPos));
    33. }
    34.  
    35. ...
     
  3. Lycake

    Lycake

    Joined:
    Jun 8, 2013
    Posts:
    7
    Thank you so very much! You not only understood my question, but also provided a perfect answer.

    This line was the deal breaker in my previous attempts:
    Code (CSharp):
    1. o.viewDir = mul (_InvProjectionMatrix, float4 (o.uv * 2.0 - 1.0, 1.0, 1.0));
    I couldn't get it to work the way it should. My math was wrong somehow.

    Thanks again!