godotengine / godot

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

Vulkan: Screen Space Reflections don't appear on non-metallic materials #61930

Closed BraqueDown closed 2 years ago

BraqueDown commented 2 years ago

Godot version

v4.0.alpha.custom_build [e297ddf65]

System information

Windows 10, Vulkan Clustered, RTX 3070 (512.15)

Issue description

The opacity/strength of Screen Space Reflections is tied to the Metallic property of the material receiving them. The effect gets stronger the more metallic the surface is, and dissapears completely at 0.0.

This means that SSR is totally non-functional on dielectric materials.

image

image

Video version:

https://user-images.githubusercontent.com/43602802/173183899-3cd00bab-2111-4b20-a6f6-fd2c86b0329e.mp4

Same scene in Blender with Eevee SSR for comparison:

https://user-images.githubusercontent.com/43602802/173183975-df64cc2a-4681-489b-9c1f-0a7520e08e77.mp4

Steps to reproduce

  1. Create a mesh, add a material, then create additional meshes to be reflected.
  2. Add a WorldEnvironment node, and enable SSR.
  3. Adjust the metallic property on the initial mesh's material, and notice the reflections fading in and out.

Minimal reproduction project

SSR Metal Bug.zip

Calinou commented 2 years ago

I can confirm this on 4.0.alpha 126e4d0a5 (Linux, NVIDIA 510.68.02). This issue does not occur with SDFGI – its reflection remains visible on non-metallic materials.

I remember being able to see SSR on non-metallic materials a few months ago, but I may be wrong.

An equalized crop of the image at metallic = 0.0 reveals that there is indeed no visible screen-space reflection at all:

image

The SSR metallic blend is done here: https://github.com/godotengine/godot/blob/1847094271bda14c947bf46cbc52a4ca1603fb69/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl#L232-L234

Commenting out both lines fixes the issue. It causes a diagonal streak to appear through the sky, but I assume this is an underlying SSR issue that would otherwise occur (but is invisible as the sky is never metallic):

image

Also, commenting out both lines makes reflections on rough non-metallic materials too visible:

image

SSR opacity should probably be modulated by roughness instead of metallic. This change would fit well with https://github.com/godotengine/godot/pull/56804.

Diff to modulate SSR by roughness instead of metallic ```diff diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl index a416891ff2..57a0ef3fa3 100644 --- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl @@ -197,11 +197,12 @@ void main() { vec4 final_color; + float roughness = normal_roughness.w; + #ifdef MODE_ROUGH // if roughness is enabled, do screen space cone tracing float blur_radius = 0.0; - float roughness = normal_roughness.w; if (roughness > 0.001) { float cone_angle = min(roughness, 0.999) * M_PI * 0.5; @@ -229,9 +230,8 @@ void main() { #endif final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend); - //change blend by metallic - vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask); - final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0)); + // Change blend by roughness. + final_color.a *= 1.0 - roughness; imageStore(ssr_image, ssC, final_color); ```