Closed WrobotGames closed 11 months ago
Suppose I am getting this right. Do we need to bake the ambient light emission from the ground affected by directional light? I may be wrong here.
I guess this is more of an "enhancement" suggestion. Right now "backlight" is a setting that only applies to direct lights in Godot, it doesn't add anything to indirect lights/GI.
For direct lights we add an extra term ((1/PI) - BRDF) * backlight
. So I tried adding a comparable term to the ambient sky light
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 8a7008492e..28e989b3c2 100644
--- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -1153,6 +1153,9 @@ void fragment_shader(in SceneData scene_data) {
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
cubemap_ambient *= scene_data.IBL_exposure_normalization;
+#if defined(LIGHT_BACKLIGHT_USED)
+ cubemap_ambient += (vec3(1.0 / M_PI) - cubemap_ambient) * backlight;
+#endif
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
It certainly softens the lighting the way that backlight does, but I'm not sure if it is the correct approach. Can you test with the above patch and let me know if the result matches your expectations?
This patch seems to be a solution. It is not perfect, but it is good enough of a solution. (so yes, the results match my expectations) As can be seen from this image, the patch solves the main problem.
(Note: unreal uses a different HDRI and I don't know how to disable the specular reflection in Unity HDRP) There are still some differences between the pieces of software, but those seem to be coming from the way the mesh is lit by the HDRI, rather then how the backlight is calculated. Example: The underside of the sphere isn't black in Godot, and the sides are not that blue, this can be seen in the backlight.
The patch had really improved the look of the grass. Without patch: With patch:
Some issues I've encountered:
Thanks for checking! Your analysis shows that the lines of code I posted are definitely not correct. So more investigation will be needed to figure out what a proper backlight formula for sky lighting looks like
All the translucency in blender seems to do is to sample the diffuse from the inverted normal, multiplying that by the backlight color and then adding it to the rest of the ambient light. When only plugging in the translucency node into the output, blender will give inverted shading:
This is what that would look like in the godot shader. I've duplicated the cubemap samplers and renamed them to cubemapambient2. Yes this code is a bit messy and unoptimized. (/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forwardclustered.glsl:1149)
if (scene_data.use_ambient_light) {
ambient_light = scene_data.ambient_light_color_energy.rgb;
if (scene_data.use_ambient_cubemap) {
vec3 ambient_dir = scene_data.radiance_inverse_xform * normal;
vec3 ambient_dir2 = scene_data.radiance_inverse_xform * normal * vec3(-1.0, -1.0, -1.0);
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb;
vec3 cubemap_ambient2 = texture(samplerCubeArray(radiance_cubemap, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(ambient_dir2, MAX_ROUGHNESS_LOD)).rgb;
#else
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
vec3 cubemap_ambient2 = textureLod(samplerCube(radiance_cubemap, SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), ambient_dir2, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
cubemap_ambient *= scene_data.IBL_exposure_normalization;
cubemap_ambient2 *= scene_data.IBL_exposure_normalization;
#if defined(LIGHT_BACKLIGHT_USED)
cubemap_ambient += cubemap_ambient2 * backlight;
#endif
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
This code gives the right results in what seems to be the right way. Example: Sphere with (and without) 100% red backlight, only lit by HDRI.
The backlight effect goes away when enabling sdfgi, because it does not use this bit of code. I do not know (yet) how to make that work. For proper results the backlight should be implemented everywhere. (reflectionsprobes, voxelgi etc)
I am closing this issue, because the more I look into it, the more I realize a potential fix is a lot more complicated. I feel like this discussion should be moved to the Godot proposals repo.
For example: Bevy introduced backlighting in its 0.12 update. https://bevyengine.org/news/bevy-0-12/
Diffuse transmission is implemented via a second, reversed and displaced fully-diffuse Lambertian lobe, which is added to the existing PBR lighting calculations. This is a simple and relatively cheap approximation, but works reasonably well.
This sounds fairly simple, but when I tried the demo it seemed like there are some changes made to the lighting of the non backlit side, when changing the backlighting intensity. Some kind of correction for the added lighting. (Energy Conservation.)
Also, the backlighting currently implemented doesn't seem to handle normals correctly, with the sides of a sphere being lit even though the light is at an 90 degree angle. (This behavior does not occur in other game engines / in blender)
Godot version
v4.1.stable.official [970459615]
System information
Godot v4.1.stable - Windows 10.0.22621 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1060 6GB (NVIDIA; 31.0.15.3667) - Intel(R) Core(TM) i7-9700K CPU @ 3.60GHz (8 Threads)
Issue description
When using backlight/translucency ambient light (the background/hdri) is not used for the backlight effect. This results in, for example foliage materials looking really 'harsh' in Godot.
The ambient light is included by default in the following software: blender cycles, blender eevee, unity hdrp and unreal engine. (This has been tested) Ambient light being included is basically the expected behavior, and that's why this is an issue that this isn't there is Godot.
Example: plane against the sky, the reproduction project.
A white plane with 100% backlight against the sky. Godot 4: Blender Eevee:
Example: foliage (no download due to copyright)
In materials where the backlight is used, for example foliage, the lighting will often look too 'harsh' when the ambient light isnt used in the backlight. Godot 4 grass with 100% backlight: Blender Eevee grass with 100% backlight: The lighting in Eevee looks notably more soft, and a bit brighter. This is the expected outcome with a 100% backlight. Its not possible to get this result in Godot without writing your own light shader. (Which is really complicated and should be the case here)
Steps to reproduce
Do the same thing in other software and there will be a difference by enabling it. (Tested in: Cycles, Eevee, Unity, Unreal)
Minimal reproduction project
Backlight_Godot4.zip Backlight_Blender.zip