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

Effect shader world pos calculation!

Discussion in 'Shaders' started by SpookyCat, Nov 26, 2010.

  1. SpookyCat

    SpookyCat

    Joined:
    Jan 25, 2010
    Posts:
    3,748
    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.
    Code (csharp):
    1. Shader "ShowPos Effect Shader"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Base (RGB)", 2D) = "white" {}
    6.     }
    7.  
    8.     SubShader
    9.     {
    10.         Pass
    11.         {
    12.             ZTest Always Cull Off ZWrite Off
    13.             Fog { Mode off }
    14.                
    15.             CGPROGRAM
    16.             #pragma vertex vert
    17.             #pragma fragment frag
    18.             #pragma fragmentoption ARB_precision_hint_fastest
    19.             #include "UnityCG.cginc"
    20.  
    21.             uniform sampler2D _MainTex;
    22.             uniform float4 _MainTex_TexelSize;
    23.  
    24.             struct appdata
    25.             {
    26.                 float4 vertex : POSITION;
    27.                 float3 texcoord : TEXCOORD0;
    28.             };
    29.  
    30.             struct v2f
    31.             {
    32.                 float4 pos : SV_POSITION;
    33.                 float4 uv : TEXCOORD0;
    34.                 float3 ray : TEXCOORD1;
    35.             };
    36.  
    37.             v2f vert (appdata v)
    38.             {
    39.                 v2f o;
    40.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    41.                 o.uv = ComputeScreenPos (o.pos);
    42.                 o.ray = mul (UNITY_MATRIX_MV, v.vertex).xyz * float3(-1,-1,1);
    43.    
    44.                 // v.texcoord is equal to 0 when we are drawing 3D light shapes and
    45.                 // contains a ray pointing from the camera to one of near plane's
    46.                 // corners in camera space when we are drawing a full screen quad.
    47.                 o.ray = lerp(o.ray, v.texcoord, v.texcoord.z != 0);
    48.    
    49.                 return o;
    50.             }
    51.  
    52.             sampler2D _CameraDepthTexture;
    53.             float4x4 _CameraToWorld;
    54.  
    55.             float4 frag (v2f i) : COLOR
    56.             {
    57.                 i.ray = i.ray * (_ProjectionParams.z / i.ray.z);
    58.                 float2 uv = i.uv.xy / i.uv.w;
    59.                
    60.                 float depth = tex2D(_CameraDepthTexture, uv).r;
    61.                 depth = Linear01Depth(depth);
    62.                 float4 vpos = float4(i.ray * depth, 1);
    63.                 float3 wpos = mul(_MyCameraToWorld, vpos).xyz;
    64.  
    65.                 return float4(normalize(wpos), 1);
    66.             }
    67.  
    68.             ENDCG
    69.         }
    70.     }
    71.  
    72.     Fallback off
    73. }
     
  2. SpookyCat

    SpookyCat

    Joined:
    Jan 25, 2010
    Posts:
    3,748
    Mmm I guess this shader gets the viewspace position, bit stuck on getting a world space has anyone done this before?
     
  3. Cameron_SM

    Cameron_SM

    Joined:
    Jun 1, 2009
    Posts:
    915
    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.
     
  4. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    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 :)
     
    Last edited: Dec 5, 2011
    mewlist likes this.
  5. aubergine

    aubergine

    Joined:
    Sep 12, 2009
    Posts:
    2,878
    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.
     

    Attached Files:

    • $1.png
      $1.png
      File size:
      15.6 KB
      Views:
      2,516
  6. etical

    etical

    Joined:
    Jul 26, 2013
    Posts:
    1
    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:

    Code (csharp):
    1.  
    2. ...
    3. float4 D = mul((camera.projectionMatrix * camera.worldToCameraMatrix).inverse; (passed from your script), H);
    4. D = D/D.w;
    5. return D + float4(_WorldSpaceCameraPos, 1);
    6.  
    With a unit sphere at the origin, it looks like the following:

    $worldSpaceImageEffect.png

    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?
     
  7. zezba9000

    zezba9000

    Joined:
    Sep 28, 2010
    Posts:
    985