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

Question Problems with converting shader from godot to unity

Discussion in 'Shaders' started by CGDever, Sep 9, 2023.

  1. CGDever

    CGDever

    Joined:
    Dec 17, 2014
    Posts:
    154
    Hi guys!
    I can't make godot's shader works in unity.
    Here is a part of this shader:
    Code (CSharp):
    1. shader_type spatial;
    2.  
    3. render_mode unshaded;
    4. render_mode depth_test_disabled, cull_front;
    5.  
    6. uniform sampler2D depth_tex : hint_depth_texture;
    7.  
    8. group_uniforms Color;
    9.  
    10. uniform float col_distance_scale = 1.0;
    11. uniform vec3 col_near : source_color = vec3(1.0);
    12. uniform vec3 col_far : source_color = vec3(0.0);
    13. uniform float emission_boost = 1.0;
    14.  
    15. group_uniforms;
    16.  
    17. group_uniforms SDFNoise;
    18.  
    19. uniform float sphere_radius = 0.5;
    20.  
    21. uniform float noise_scale = 1.0;
    22. uniform int detail = 4;
    23. uniform float rough = 0.5;
    24. uniform float inflate = 0.1;
    25. uniform float smooth_fac = 0.2;
    26.  
    27. uniform float step_mult = 1.0;
    28.  
    29. group_uniforms;
    30.  
    31. mat3 y_rot(float angle) {
    32.     return mat3(
    33.         vec3(cos(angle), 0.0, -sin(angle)),
    34.         vec3(0.0, 1.0, 0.0),
    35.         vec3(sin(angle), 0.0, cos(angle))
    36.     );
    37. }
    38.  
    39. void fragment() {
    40.     float depth = textureLod(depth_tex, SCREEN_UV, 0.0).r;
    41.     vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
    42.     vec3 pixel_position = upos.xyz / upos.w;
    43.  
    44.     vec4 wpos = INV_VIEW_MATRIX * (upos / upos.w);
    45.  
    46.     vec3 obj_position = -(inverse(MODEL_MATRIX) * wpos).xyz;
    47.     vec3 obj_view_vec = inverse(mat3(MODEL_MATRIX)) * mat3(INV_VIEW_MATRIX) * VIEW;
    48.  
    49.     vec3 view_dir = normalize(obj_view_vec);
    50.  
    51.     vec3 cur_pos = obj_position;
    52.     for (int i = 0; i < 50; i++) {
    53.      
    54.         // float offset = length (cur_pos)-sphere_radius;
    55.         float offset = -sdf_map(cur_pos);
    56.      
    57.         if (offset < -0.005) {break;}
    58.      
    59.         cur_pos += view_dir * offset * step_mult;
    60.     }
    61.  
    62.     float cur_dist = 0.;
    63.  
    64.     float alpha = 1.0 - clamp(cur_dist * -100.0, 0.0, 1.0);
    65.     ALPHA = 1.0;// pow(alpha, 2.0);
    66.  
    67.     float vol_depth = distance(obj_position, cur_pos);
    68.  
    69.     float col_mix_fac = pow(1.0 - exp(-col_distance_scale * vol_depth), 2.0);
    70.  
    71.     vec3 vol_color = mix(col_near, col_far, col_mix_fac);
    72.  
    73.     ALBEDO.xyz = vol_color * emission_boost;
    74.  
    75.     // ALBEDO.xyz = cur_pos;
    76.     // depth = pow(depth,30.);
    77.     // ALBEDO.xyz = vec3(depth,depth,depth);
    78.     // ALBEDO.xyz = vec3(cur_pos.x,cur_pos.y,cur_pos.z);
    79.     ALBEDO.xyz = VIEW;
    80. }
    I have many problems, one of them is reprodiction of godot's vec3 VIEW.
    It seems I have reproduction problems of it because if I output it as a color it looks different to godot's version.
    Godot's instruction says:
    in vec3 VIEW is a normalized vector from fragment position to camera (in view space).

    Here is how I calculate it:
    Vert:
    Code (CSharp):
    1. o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
    2. float3 worldSpaceViewDir = _WorldSpaceCameraPos - o.worldPos;
    3. //Convert from world to view space
    4. o.VIEW = mul(UNITY_MATRIX_V, float4(worldSpaceViewDir, 0.));
    Frag:
    Code (CSharp):
    1. return float4( normalize(i.VIEW), 1.);

    Here is visible a visual difference between my and GODOT's views:
    gg.jpg

    Guys, could help me what am I doing wrong?
     
  2. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,394
    Do both projects use the same color space (linear or gamma)?
     
  3. CGDever

    CGDever

    Joined:
    Dec 17, 2014
    Posts:
    154
    Thank you for your help!
    I changed color space in unity to linear and it seems looks more similar to godot's:
    gg.png

    Well, yes, all things are much better! Thank YOU again!
    I was too confused about total misunderstanding the difference in outputs :/

    I still have a few questions.
    I don't understand why here is a difference between godot's depth texture output and unity's.
    Here is godot's output (not transparent cube is inside of geometry with this shader):
    gg.jpg

    The same code in Unity (I guess it is the same) renders completely black cube:
    Code (CSharp):
    1. float depth = tex2D(_CameraDepthTexture, SCREEN_UV).r;
    2. depth = pow(depth, 30.);
    3. return float4(depth, depth, depth, 1.);
    Do you have some ideas why this happens?

    Update:
    I thought Editor's camera uses _CameraDepthTexture, but scene camera at least renders some depth:
    234.png
     
    Last edited: Sep 9, 2023
  4. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,394
    I can't help much with depth. I've only worked a little with it in shader graph (here there are 3 different ways of showing the depth texture).
     
  5. CGDever

    CGDever

    Joined:
    Dec 17, 2014
    Posts:
    154
    Thank you for your help!

    I still have problem with repeating the depth in unity.
    A adjusted in Godot camera's Near and Far planes, FOV made them the same like in unity, used:
    Code (CSharp):
    1. GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;
    but still have massive difference with depth outputs:
    gg.jpg

    Does somebody see the problem? I completely don't understand why the depth looks very different.
    I have being tying to use Linear01Depth, LinearEyeDepth - no success :/
     
  6. CGDever

    CGDever

    Joined:
    Dec 17, 2014
    Posts:
    154
    Bump!
    The best result which I was able to achieve in Unity:
    Code (CSharp):
    1. float linear_depth_to_notlinear (float srcDepth) {
    2.                 // return zNear * zFar / (zFar + d * (zNear - zFar));// I found this on the internet
    3.                 // VVVV express d VVVV
    4.                 return (_ProjectionParams.y * _ProjectionParams.z / srcDepth - _ProjectionParams.z) / (_ProjectionParams.y - _ProjectionParams.z);
    5.             }
    6.  
    7.             fixed4 frag(v2f i) : SV_Target{
    8.                 float2 SCREEN_UV = i.screenPos.xy / i.screenPos.w;//+
    9.                 // 0 - close
    10.                 // 1 - far
    11.                 float depth = LinearEyeDepth( tex2D(_CameraDepthTexture, SCREEN_UV).r );
    12.                 depth = linear_depth_to_notlinear(depth);
    13.                 depth = pow(depth, 30.);
    14.                 return float4(depth, depth, depth, 1.);
    15. }
    Here is Godot's source which gives the result which i have to reproduce:
    Code (CSharp):
    1. float depth = textureLod(depth_tex, SCREEN_UV, 0.0).r;
    2. depth = pow(depth, 30.);
    3. ALBEDO.xyz = vec3(depth,depth,depth);
    gu.jpg

    The cube in Unity looks quite similar to Godot's, but there is a difference!
    I'm quite bad in shaders and don't understand why there is a difference. Does somebody see the problem?