godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91k stars 21.17k forks source link

Different depth obtained for the same shader in Godot4 vs Godot3 #56283

Closed Zylann closed 2 years ago

Zylann commented 2 years ago

Godot version

4.0 28174d531b7128f0281fc2b88da2f4962fd3513e

System information

Windows 10 64 bits GLES3 GeForce GTX 1060 6GB/PCIe/SSE2

Issue description

I have a planet atmosphere shader effect in which I can fly into (see https://github.com/Zylann/godot_atmosphere_shader). I'm porting it to Godot 4, but I quickly realized the atmosphere appears to be drawing "behind" the planet. After investigating a bit, it seems like the depth calculated by the shader is no longer the same as it was in Godot 3.

I simplified the shader and made a very simple scene in both Godot 3 and 4. and obtained different results when outputting the depth I calculated. The scene is a 1x1x1 cube contained inside a 2x2x2 cube. The larger cube has the shader on it.

Godot 3: image

Godot 4: image

I also added a camera to each project so the main scene can be run, and a similar result can be observed. Depth is still "behaving like depth", getting closer makes the inner cube show up, but it varies differently and likely causes the discrepancy in my effect.

Steps to reproduce

I used the following code to obtain depth, amongst other things. Does it need to change in Godot4?

    float nonlinear_depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;
    vec3 ndc = vec3(SCREEN_UV, nonlinear_depth) * 2.0 - 1.0;
    vec4 view_coords = INV_PROJECTION_MATRIX * vec4(ndc, 1.0);
    vec4 world_coords = CAMERA_MATRIX * view_coords;
    vec3 pos_world = world_coords.xyz / world_coords.w;
    vec3 cam_pos_world = (CAMERA_MATRIX * vec4(0.0, 0.0, 0.0, 1.0)).xyz;
    float linear_depth = distance(cam_pos_world, pos_world);

Minimal reproduction project

Godot4 project: ShaderFogEffect.zip

Godot3 project: ShaderFogEffect.zip

Play main.tscn in both versions, and observe the discrepancy. It can also be observed in editor, without launching the scene.

clayjohn commented 2 years ago

This is a known difference between Vulkan and OpenGL. It's already documented here https://docs.godotengine.org/en/latest/tutorials/shaders/advanced_postprocessing.html#depth-texture

Zylann commented 2 years ago

Will the OpenGL renderer in Godot4 have the same convention though? (If not, every shader reading depth will have to be copy/pasted, unless a constant or #ifdefs are available)

clayjohn commented 2 years ago

@Zylann we haven't written the GL3 renderer. But if it's not too detrimental to performance and readability I would like to use the Vulkan-convention.