Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

World Space Position in frag shader, but

Discussion in 'Shaders' started by N3V-Developer, Sep 26, 2014.

  1. N3V-Developer

    N3V-Developer

    Joined:
    Jun 7, 2014
    Posts:
    20
    Hi,

    I have searched a read though the answers serveal hours, but there was no real working solution to it.
    I want to get the global world position of a texel inside the frag shader.
    This example fades the color to red in order to the depth distance of the cam.
    Can some one help with some lines of code plz?

    thanks and regards,

    Code (CSharp):
    1.            
    2.            CGPROGRAM
    3.  
    4.             #pragma target 3.0
    5.             #pragma vertex vert_img
    6.             #pragma fragment frag
    7.             #pragma fragmentoption ARB_precision_hint_fastest
    8.             #include "UnityCG.cginc"
    9.  
    10.             uniform sampler2D _MainTex; //the depth texture
    11.             sampler2D _CameraDepthTexture;
    12.            
    13.             struct v2f
    14.             {
    15.                 float4 pos : SV_POSITION;
    16.                 float4 projPos : TEXCOORD1; //Screen position of pos
    17.             };
    18.             v2f vert(appdata_base v)
    19.             {
    20.                 v2f o;
    21.                 return o;
    22.             }
    23.          
    24.             fixed4 frag (v2f_img i) : SV_TARGET
    25.             {  
    26.              
    27.              // Get the depth of texel
    28.               float depth = UNITY_SAMPLE_DEPTH( tex2D(_CameraDepthTexture, i.uv.xy) );
    29.               depth = Linear01Depth(depth);
    30.  
    31.              // ?? How do i get the world space coordinate for the current texel??  
    32.              
    33.              // Get the texel color
    34.               fixed4 original = tex2D(_MainTex, i.uv);
    35.               fixed4 finalColor = lerp(original, fixed4(1, 0, 0, 0), depth);
    36.               return finalColor;
    37.             }
    38.             ENDCG
     
  2. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    In the image effect assets there is one called global fog post effect or something like that. That effect contains code that converts the depth to a world position. Or you can have a look at this project which also converts the depth to world pos in a shader.

    The general idea is that you provide the shader with the frustum corner directions and then project the depth from the fragments interpolated corner direction.
     
  3. N3V-Developer

    N3V-Developer

    Joined:
    Jun 7, 2014
    Posts:
    20
    Thanks

    But from what I see its the wrong way to get the WS coordinates because that based on forward lightning only.
    Deferrt use more texture ram and in this case the ws position is already textured.
    Hmm.. so that way of receiving the WS seems to currently very old stuff?
     
  4. spraycanmansam

    spraycanmansam

    Joined:
    Nov 22, 2012
    Posts:
    254
    The only difference between forward and deferred in this context is that the depth texture is a byproduct of the deferred path. You can still force Unity to create a depth texture in forward rendering at a slight performance cost. So the render path is irrelevant in this case.
    The method mentioned above is far from old - IIRC it's actually based off a Crytek implementation and is faster than the alternatives.
     
  5. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    Do you have any link or real example how to? Can't
     
    Last edited: Oct 13, 2014
  6. CHPedersen

    CHPedersen

    Joined:
    Mar 2, 2011
    Posts:
    63
    You don't have to query the depth texture if you just want the world space position of a fragment. You can get the rasterizer to interpolate it for you if you add the world space position of the vertices to your vertex output, and then readback the interpolated value in the pixel shader. It would look like this (working with lowlevel vert/frag shaders):

    Code (HLSL):
    1.             struct vertOut
    2.             {
    3.                 float4 position : SV_POSITION;
    4.                 float4 worldSpacePosition : TEXCOORD0;
    5.             };
    6.  
    7.             vertOut vert(appdata_full vertIn)
    8.             {
    9.                 vertOut o;
    10.                 o.position = mul(UNITY_MATRIX_MVP, vertIn.vertex);
    11.                 o.worldSpacePosition = mul(_Object2World, vertIn.vertex);
    12.                 return o;
    13.             }
    14.  
    15.             float4 frag(vertOut fragIn) : COLOR
    16.             {        
    17.                 float4 c_out = float4(0,0,0,0); // Whatever
    18.                 // The interpolator calculated world space pixel coordinates for you here
    19.                 float4 pixelWorldSpacePosition = fragIn.worldSpacePosition;
    20.                 return c_out;
    21.             }
     
    Xir likes this.
  7. Quatum1000

    Quatum1000

    Joined:
    Oct 5, 2014
    Posts:
    888
    Thanks.. that helped!
     
    Last edited: Nov 9, 2014
  8. spraycanmansam

    spraycanmansam

    Joined:
    Nov 22, 2012
    Posts:
    254
    Sorry yes I should have clarified that my reply was in the context of getting the world position in a post effect. No need for using depth textures in a regular shader, just store it in an interpolator like CHPedersen showed :)
     
  9. scrawk

    scrawk

    Joined:
    Nov 22, 2012
    Posts:
    804
    Yer, that's what I thought as well. :)