Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Resolved _WorldSpaceCameraPos does not work correctly for VR stereo camera in single pass renderying

Discussion in 'Universal Render Pipeline' started by wsxmax, Feb 28, 2024.

  1. wsxmax

    wsxmax

    Joined:
    Sep 8, 2021
    Posts:
    4
    Hello,
    I was running into this problem trying to write a volumatic shader for meta quest 3
    since, normally, a ray marching shader would need to calculate the ray direction from vertex and camera position, I used _WorldSpaceCameraPos to get the camera position in my urp shader.

    and it seems, it returns always the left eye camera's position. so when looking into left eye only, everything seems fine. but the stereo works incorrectly, since the camera position didn't change with eyes, the ray stays with the vertex, ande everything got a little transformed exactly along the geometrie itself. and the result in stereo was, it looks like the volum was a flat texture on the surface of the geometrie.

    here's what it looks
    20240228-235946.jpg 20240228-235952.jpg

    and in case I got any low level mistakes in my code, here is the shader:

    Code (CSharp):
    1. Shader "Custome/volumn_cloud_simple_2"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex("Main Texture", 2D) = "white" {}
    6.         _Main_Texture_Scale("Main Texture Scale", Float) = 1
    7.         _HeightTex("Height Texture", 2D) = "white" {}
    8.         _Height_Texture_Scale("Height Texture Scale", Float) = 1
    9.         _TorrentTex("Torrent Texture", 2D) = "Black" {}
    10.         _Torrent_Texture_Scale("Torrent Texture Scale", Float) = 1
    11.         _TextTex_Transform("Text Texture Transform", Vector) = (1,1,0,0)
    12.         _Color("Main Color", Color) = (1,1,1,1)
    13.         _Alpha("Main Alpha",  Range(0,1)) = 1
    14.         _Density("Density", Float) = 1
    15.         _Ray_Step("Ray Steps" , Int) = 10
    16.         _Trace_Back_Threashold("Trace Back Threashold", Range(0,1)) = 0.5
    17.         _Stride_Length("Stride Length", Float) = 1
    18.         _Light_Fac("Light Factor", Float) = 1
    19.         _Absorbtion_Rate("Absorbtion Rate", Float) = 1
    20.         _Height("Height", Float) = 0
    21.         _Bottom("Bottom", Float) = 0
    22.         _Velocity("Velocity", Float) = 1
    23.         _Bottom_Light_Color("Bottom Light Color", Color) = (0,0,0,1)
    24.         _Bottom_Light_Strength("Bottom Light Strength", Float) = 1
    25.         _Fade_Color("Fade Color",Color) = (1,1,1,1)
    26.         _Test_Value("Test Value", Float)= 1
    27.  
    28.  
    29.         [Space]
    30.         _ZWrite("Depth Write", Float) = 0.0
    31.         _ZTestMode("Z Test Mode", Float) = 4
    32.     }
    33.     SubShader
    34.     {
    35.         Tags { "Queue" = "Transparent"  "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "RenderPipeline" = "UniversalPipeline" }
    36.         Blend One OneMinusSrcAlpha
    37.         Cull Back
    38.         ZWrite On
    39.         ZTest Less
    40.  
    41.         Pass
    42.         {
    43.             HLSLPROGRAM
    44. // Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members vertex_World)
    45.             #pragma vertex vert
    46.             #pragma fragment frag
    47.             #pragma multi_compile SHAKE_UV_OFF SHAKE_UV_ON
    48.             #pragma multi_compile JELLY_UV_OFF JELLY_UV_ON
    49.  
    50.             //#include "UnityCG.cginc"
    51.             #define UNIVERSAL_FORWARD_LIT_PASS_INCLUDED
    52.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    53.             #if defined(LOD_FADE_CROSSFADE)
    54.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LODCrossFade.hlsl"
    55.             #endif
    56.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
    57.  
    58.             struct appdata
    59.             {
    60.                 float4 vertex : POSITION;
    61.                 float2 uv : TEXCOORD0;
    62.                 float3 normal: NORMAL;
    63.                 float4 tangent  : TANGENT;
    64.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    65.             };
    66.  
    67.             struct v2f
    68.             {
    69.                 float2 uv : TEXCOORD0;
    70.                 //UNITY_FOG_COORDS(1)
    71.                 float4 vertex : SV_POSITION;
    72.                 float4 vertex_world: TEXCOORD1;
    73.                 UNITY_VERTEX_OUTPUT_STEREO
    74.             };
    75.  
    76.             struct FragmentOutput
    77.             {
    78.                 float4 color : SV_Target;
    79.                 float depth : SV_Depth;
    80.             };
    81.  
    82.             sampler2D _MainTex;
    83.             sampler2D _HeightTex;
    84.             sampler2D _TorrentTex;
    85.             sampler2D _TextTex;
    86.             float _Main_Texture_Scale;
    87.             float _Height_Texture_Scale;
    88.             float _Torrent_Texture_Scale;
    89.             float4 _TextTex_Transform;
    90.             float4 _MainTex_ST, _MainTex_TexelSize, _Color;
    91.             float _Alpha, _RandomSeed;
    92.             float _Light_Fac;
    93.             float _Density;
    94.             int _Ray_Step;
    95.             float _Trace_Back_Threashold;
    96.             float _Stride_Length;
    97.             float _Absorbtion_Rate;
    98.             float _Height;
    99.             float _Bottom;
    100.             float _Velocity;
    101.             float4 _Bottom_Light_Color;
    102.             float _Bottom_Light_Strength;
    103.             float _Text_Strength;
    104.             float4 _Fade_Color;
    105.             float _Test_Value;
    106.  
    107.             float4 _HitEffectColor;
    108.             float _Thickness;
    109.             float _HitEffectGlow, _HitEffectBlend;
    110.  
    111.             float _ShakeUvSpeed, _ShakeUvX, _ShakeUvY;
    112.  
    113.             float _JellyUvSpeed, _JellyUvXStrength, _JellyUvYStrength, _JellyUvX, _JellyUvY;
    114.  
    115.             int _Steps;
    116.  
    117.             v2f vert (appdata v)
    118.             {
    119.                 v2f o;
    120.                 UNITY_SETUP_INSTANCE_ID(v);
    121.                 //UNITY_INITIALIZE_OUTPUT(v2f, o);
    122.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    123.                 o.vertex_world = mul(unity_ObjectToWorld, v.vertex);
    124.                 o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    125.                 return o;
    126.             }
    127.  
    128.             float form_texture(sampler2D tex, float2 uv){
    129.                 return tex2D(tex,uv).r;
    130.             }
    131.  
    132.  
    133.             float3 density_top_bottom(float3 pos, float3 true_pos){
    134.                 float3 object_pos = mul(unity_WorldToObject,float4(pos,1)).xyz;
    135.                 float3 true_boject_pos = mul(unity_WorldToObject,float4(true_pos,1)).xyz;
    136.                 float2 flowing_torrent_uv = true_boject_pos.xz*_Torrent_Texture_Scale;
    137.                 float texture_height = min(0.5,(form_texture(_HeightTex,object_pos.xz*_Height_Texture_Scale))+ _Height);
    138.                 float height = texture_height;
    139.                 float top = height - object_pos.y;
    140.                 float bottom = object_pos.y - _Bottom;
    141.                 float density =  max(0,min(1,min(top,bottom)*25));
    142.                 bottom = length(mul((float3x3)unity_ObjectToWorld,float3(0,bottom,0)));
    143.                 top = length(mul((float3x3)unity_ObjectToWorld,float3(0,top,0)));
    144.                 return float3(density,top,bottom);
    145.             }
    146.  
    147.             float3 flow_pos(float3 pos){
    148.                 float2 flowing_torrent_uv = mul(unity_WorldToObject,float4(pos,1)).xz;
    149.                 flowing_torrent_uv.x += 0.5;
    150.                 flowing_torrent_uv.y += _Time.x*_Velocity/2500000;
    151.                 flowing_torrent_uv *= _Torrent_Texture_Scale;
    152.                 float3 flowing_pos = pos;
    153.                 flowing_pos.z += _Time.x*_Velocity;
    154.                 flowing_pos.z += tex2D(_TorrentTex,flowing_torrent_uv).r*7000;
    155.                 return flowing_pos;
    156.             }
    157.  
    158.             float3 flowing_density_top_bottom(float3 pos){
    159.                 float3 _flowing_density = 0.5*density_top_bottom(flow_pos(pos),pos);
    160.                 return _flowing_density;
    161.             }
    162.  
    163.             float4 density_integra_in_direction(float3 origin, float3 direction, int ray_step, float stride_length, float phase){
    164.                 float result = 0;
    165.                 float3 stride = normalize(direction)*stride_length;
    166.                 for(int i=0;i<ray_step;i++){
    167.                     result += stride_length*flowing_density_top_bottom(origin + stride * i)[0];
    168.                 }
    169.                 return result;
    170.             }
    171.  
    172.             float4 density_integra_to_target(float3 origin, float3 target, int ray_step, float stride_length, float phase){
    173.                 return density_integra_in_direction(origin, target - origin, ray_step, stride_length, phase);
    174.             }
    175.  
    176.  
    177.  
    178.             float3 calculate_light(float3 light_color, float density_integra){
    179.                 float3 color = light_color*exp(-density_integra*_Absorbtion_Rate*0.00001*pow(_Density,0.5));
    180.                 return color;
    181.             }
    182.  
    183.  
    184.             float3 get_light_add(Light light,float3 current_pos, float current_pos_density,int ray_step, float stride_length, float phase, float density_integra){
    185.                 float3 light_color = light.color.rgb*_Light_Fac*0.001;
    186.                 float3 light_direction = light.direction;
    187.                 return calculate_light(calculate_light(light_color,density_integra_in_direction(current_pos,light_direction,ray_step,stride_length,1)),density_integra)*current_pos_density/100;
    188.             }
    189.  
    190.             float3 get_light_add_verticle(Light top_light, Light bottom_light, float top, float bottom, float current_pos_density, float density_integra){
    191.                 return calculate_light(calculate_light(bottom_light.color.xyz*_Light_Fac*0.001,bottom)+calculate_light(top_light.color.xyz*_Light_Fac*0.001,top),density_integra)*current_pos_density/100;
    192.             }
    193.  
    194.             bool need_traceBack(float previous, float current, float threashold){
    195.                 if(abs(previous-current)>threashold){
    196.                     return true;
    197.                 }else{
    198.                     return false;
    199.                 }
    200.             }
    201.  
    202.  
    203.             FragmentOutput color_of_ray(float3 origin, float3 direction, int ray_step, float relative_stride_length, float background_depth, int trace_back, int trace_count){
    204.                 float stride_length = length(direction)*relative_stride_length/abs(direction.y);
    205.                 float3 light_accumulation = float3(0,0,0);
    206.                 float density_integra = 0;
    207.                 float3 stride = normalize(direction)*stride_length;
    208.                 float surfaceDepth = 0;
    209.                 float current_step = 0;
    210.                 float3 current_pos = origin;
    211.                 int trace_count_left = trace_count;
    212.                 bool traced = false;
    213.                 float3 current_pos_density;
    214.                 float3 previous_pos_density = flowing_density_top_bottom(origin);
    215.                 float3 previous_light_add = float3(0,0,0);
    216.                 for(int i=0;i<ray_step;i++){ //begin marching of a ray of light
    217.                     float stride_fac = 0;
    218.                     current_pos_density = flowing_density_top_bottom(current_pos);
    219.                     if (need_traceBack(current_pos_density[0],previous_pos_density[0],_Trace_Back_Threashold) && trace_count_left>0){
    220.                         float3 first_stride = stride;
    221.                         //go back for trace_back
    222.                         float density_distance = current_pos_density[0]-previous_pos_density[0];
    223.                         float3 trace_pos = current_pos;
    224.                         float3 trace_pos_density = current_pos_density;
    225.                         float3 trace_stride = -stride*0.5;
    226.                         bool Previous_inCloud = true;
    227.                         bool Current_inCloud = false;
    228.                         for (int j=0;j<trace_back;j++){
    229.                             trace_pos += trace_stride;
    230.                             first_stride += trace_stride;
    231.                             trace_pos_density = flowing_density_top_bottom(trace_pos);
    232.                             if((trace_pos_density[0]-previous_pos_density[0])/density_distance>0.5){
    233.                                 Current_inCloud = true;
    234.                             }else{
    235.                                 Current_inCloud = false;
    236.                             }
    237.                             if(Previous_inCloud == Current_inCloud){
    238.                                 trace_stride = trace_stride*0.5;
    239.                             }else{
    240.                                 trace_stride = -trace_stride*0.5;
    241.                             }
    242.                             Previous_inCloud = Current_inCloud;
    243.                         }
    244.                         trace_count_left -= 1;
    245.                         stride_fac = length(first_stride)/stride_length;
    246.                     }
    247.                     float current_depth = length(current_pos-_WorldSpaceCameraPos);
    248.                     float depth_Fac;
    249.                     if(current_depth-background_depth<0){
    250.                         depth_Fac = 1;
    251.                     }else{
    252.                         depth_Fac = 0;
    253.                     }
    254.  
    255.                     density_integra += stride_length*(stride_fac*previous_pos_density[0]+(1-stride_fac)*current_pos_density[0])*depth_Fac;
    256.                     Light light = GetMainLight();
    257.                     //float light_stride_length = length(light.direction)*relative_stride_length/abs(light.direction.y);
    258.                     //light_stride_length = stride_length;
    259.                     //light_accumulation += get_light_add(light,current_pos,current_pos_density[0],ray_step,light_stride_length,1,density_integra);
    260.                     Light bottom_light = GetMainLight();
    261.                     bottom_light.color = tex2D(_MainTex,mul(unity_WorldToObject,-float4(current_pos,1)).xz*_Main_Texture_Scale+float2(0.5,0.5)).rgb*_Bottom_Light_Strength;
    262.                     bottom_light.color += _Bottom_Light_Color;
    263.                     //bottom_light.color += tex2D(_TextTex,mul(unity_WorldToObject,float4(current_pos,1)).xz*_TextTex_Transform.xy+_TextTex_Transform.zw).r*_Color*70;
    264.                     Light top_light = GetMainLight();
    265.                     float3 light_add = get_light_add_verticle(top_light, bottom_light, current_pos_density[1],current_pos_density[2],current_pos_density[0],density_integra)*stride_length;
    266.                     //light_accumulation += get_light_add(light,current_pos,current_pos_density[0],ray_step,light_stride_length,1,density_integra)*stride_length;
    267.                     light_accumulation += (stride_fac*previous_light_add+(1-stride_fac)*light_add)*depth_Fac;
    268.                     //light.direction = float3(0,-1,0);
    269.                     //light_stride_length = length(light.direction)*relative_stride_length/abs(light.direction.y)*2;
    270.                     //light_stride_length = stride_length;
    271.                     //light_accumulation += get_light_add(light,current_pos,ray_step,light_stride_length,1,density_integra);
    272.                     /*for (int lightIndex = 0; lightIndex < 1; ++lightIndex){
    273.                         light = GetAdditionalLight(lightIndex,current_pos);
    274.                         light_stride_length = length(light.direction)*relative_stride_length/abs(light.direction.y);
    275.                         //light_stride_length = stride_length;
    276.                         light_accumulation += get_light_add(light,current_pos,ray_step,light_stride_length,1,density_integra);
    277.                     }*/
    278.                     current_pos += stride;
    279.                     previous_pos_density = current_pos_density;
    280.                     previous_light_add = light_add;
    281.                 }
    282.                 float alpha = density_integra*_Density/100000;
    283.                 //light_accumulation = float4(0,0,0,density_integra);
    284.                 //light_accumulation *= alpha;
    285.                 float fade_fac = pow(length(origin.xz)/length(origin.xyz),200);
    286.                 FragmentOutput output = (FragmentOutput)0;
    287.                 output.color = (1-fade_fac)*float4(light_accumulation,alpha)+fade_fac*_Fade_Color;
    288.                 output.depth = surfaceDepth;
    289.                 return output;
    290.             }
    291.             FragmentOutput frag (v2f i) : SV_Target
    292.             {
    293.  
    294.                 float2 UV = i.vertex.xy / _ScaledScreenParams.xy;
    295.                 #if UNITY_REVERSED_Z
    296.                     real depth = SampleSceneDepth(UV);
    297.                 #else
    298.                     real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(UV));
    299.                 #endif
    300.                 float3 worldPos = ComputeWorldSpacePosition(UV, depth, UNITY_MATRIX_I_VP);
    301.  
    302.  
    303.                 float3 ray_direction = i.vertex_world.xyz - _WorldSpaceCameraPos.xyz;
    304.                 float background_depth = length(worldPos-_WorldSpaceCameraPos.xyz);
    305.                 FragmentOutput output = color_of_ray(i.vertex_world,ray_direction,_Ray_Step,_Stride_Length/_Ray_Step,background_depth,4,2);
    306.                 return output;
    307.             }
    308.             ENDHLSL
    309.         }
    310.     }
    311. }
    312.  
    did I miss anything? or did I misundertand any part of the rendering process?
    if _WorldSpaceCameraPos was supposed to return the exact camera position in world space, (which should be consistent with the matrices, then it seem to be a bug that they won't agree with each other?)

    (so Actually I'm also trying some work around like recalculating the camera position from the given matrix, since the geometrie was correct. )

    Thank you!
     
  2. wsxmax

    wsxmax

    Joined:
    Sep 8, 2021
    Posts:
    4
    the editor version was 2022.3.17f1c1
     
  3. ThomasZeng

    ThomasZeng

    Unity Technologies

    Joined:
    Jun 24, 2019
    Posts:
    90
  4. wsxmax

    wsxmax

    Joined:
    Sep 8, 2021
    Posts:
    4
    Thanks for reply!
    exactly as you said:
    I replaced _WorldSpaceCameraPos with unity_StereoWorldSpaceCameraPos[unity_StereoEyeIndex] and it works now perfectly.

    though, it still remains strange that, for the right eye view, all matrices work fine while _WorldSpaceCameraPos, which, should already take part in the calculation of former ones, does not. I also tried UNITY_MATRIX_I_V._m03_m13_m23 as mentioned in the article: https://tips.hecomi.com/entry/2020/08/31/235742 , which, seems mentioning the same problem. but the solution didn't work for me, still both view returns left eye positon.

    after all there was actually a perfect way there, my bad to call this a bug...sorry for that...orz
    and again, thank you for your help!
     
    ThomasZeng likes this.
  5. ThomasZeng

    ThomasZeng

    Unity Technologies

    Joined:
    Jun 24, 2019
    Posts:
    90
    Thank you for diving in URP XR code and provide feedback! Appreciate it
    Glad it solves your problem :)