Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Ambient Light Rendering #5018

Closed
mrjustaguy opened this issue Jul 30, 2022 · 11 comments
Closed

Improve Ambient Light Rendering #5018

mrjustaguy opened this issue Jul 30, 2022 · 11 comments

Comments

@mrjustaguy
Copy link

mrjustaguy commented Jul 30, 2022

Describe the project you are working on

N/A

Describe the problem or limitation you are having in your project

Mono color (or low variance color) Ambient Lighting result in loss of Object Depth resulting in a Very flat look of Geometry.
This issue is also Present with other Ambient Lighting, (such as the Default Skies and the like) just not to the same extent, as the variance in lighting does add a little bit of the depth back
Left: Proposed
Right: Current
Irradiance

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Adding the depth to Radiance and Irradiance would resolve this issue at minimal performance impact.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Add the equivalent to these GDShader Fragment snippets To Shaders resolves this issue for both Metallic and Non-Metallic Materials when in the presence of low variance Ambient/Reflected Lighting
IRRADIANCE+=vec4(0.0,0.0,0.0,-clamp(dot(VIEW,NORMAL),0.25,1.0)*multiplier);
RADIANCE+=vec4(0.0,0.0,0.0,-clamp(dot(VIEW,NORMAL),0.25,1.0)*multiplier);
multiplier is a user controlled variable, that determines how strong the depth should be, and should be added to the Materials, a base of 0.5 should probably be default for best overall results, and value of 0 reverts to old behavior.

If this enhancement will not be used often, can it be worked around with a few lines of script?

Yes, but you have to create a shader for each material.

Is there a reason why this should be core and not an add-on in the asset library?

Drastically Improves Core Rendering.

@mrjustaguy
Copy link
Author

Here are a few Extra References:
Godot Icon Sky
image
Noise Sky Default Frequency
image
Procedural Sky
image

@Calinou
Copy link
Member

Calinou commented Jul 30, 2022

cc @clayjohn

Is this a physically accurate change? This sounds like a form of fake contrast to me 🙂
If this is not physically accurate, I suggest making this a project setting so it can be easily toggled on and off globally. That said, people have been clamoring for greater PBR accuracy, so adding settings that deviate from this may not be a good idea.

Also, the way this is done in your shader makes ambient lighting brighter than intended. You should subtract some of the lighting when this feature is set to a value greater than 0 (so the average is identical).

@mrjustaguy
Copy link
Author

mrjustaguy commented Jul 30, 2022

I do not know if it is the most Physically accurate change, as in I'm unsure if there is a better more accurate way of getting the Ambient Light/Reflected Light to not result in totally flat looking geometry with the problematic lighting conditions, But I do know that even if it's a Hack, it's significantly more accurate to the current behavior.. Just turning on SDFGI in such scenarios gives the current Ambient Lighting a similar look, but is Significantly more expensive
SDFGI ON
image
SDFGI OFF (P.S. There is a Human to the Right, it's just effectively rendered invisible due to the issue this Proposal is trying to solve)
image

As for the Brightness issue, that can probably be fixed, although I'm not exactly sure how (Not that great with Shaders tbh)... Possibly Normalizing the Radiance and Irradiance would help?

@mrjustaguy
Copy link
Author

mrjustaguy commented Jul 31, 2022

Ok, well I've found one unexpected side effect.. in a cube, when rotating the camera, the faces change their light intensity...
The solution to that was to replace Normal.z with dot(VIEW,NORMAL)

I still haven't found a way to negate the added lighting.

Closest I've gotten to similar light levels as OG is with the following
IRRADIANCE+=fract(vec4(0.0,0.0,0.0,-clamp(dot(VIEW,NORMAL),0.25,1.0)))*Multiplier;
RADIANCE+=fract(vec4(0.0,0.0,0.0,-clamp(dot(VIEW,NORMAL),0.25,1.0)))*Multiplier;
resulting in slight darkening over reference (0.5 Multiplier) which is possibly ok?
image

The dot product is clamped above 0.25 because below those values the edges of the meshes get artifacts (a single Pixel Bright Edge or the likes) as demonstrated in this example
Clamp 0.0 to 1.0
image
Clamp 0.25 to 1.0
image

@WrobotGames
Copy link

WrobotGames commented Jul 31, 2022

cc @clayjohn
Is this a physically accurate change? This sounds like a form of fake contrast to me 🙂

This doesnt seem physically accurate to me after checking how its done in unreal and blender. (And a bit of light theory) Basically every single material should get brighter the smaller the angle gets. (the Fresnel effect). (And this kinda is the opposite of what happens in the above images.

Here is a sphere mesh in Godot, Unreal, and cycles. (Albedo = white, Metallic = 0, Specular = default (0.5), roughness = 0)
image

I think that the material on the images that mrjustaguy had a roughness of 1 (Godots default). This effect ins't there in any of the real-time renderers that I tested.
Here is the same image but with a roughness of 1, (Blender eevee instead of cycles in this image)
image
yes it looks flat, but this is to be expected. the fresnel is there is blender cycles (not in the image) but this a completely different technique of rendering.

If this 'fake shading' were to be added to godot, it should be an option in the project settings, and should definitely NOT be the default. I hope this makes stuff clear :)

@mrjustaguy
Copy link
Author

mrjustaguy commented Jul 31, 2022

My current Implementation seems to be getting fairly close to what Blender Cycles is Getting so I'm not getting what you're talking about exactly...

Godot My Proposal:
image
Blender Cycles:
image
Godot Current (Fully Flat, unable to see geometry):
image

NOTE: There is likely still a bit of tinkering with values that could be done to get closer to the Cycles which is used as the Ground Truth Reference, Also, This effect Can be disabled to get Current behavior by setting the Multiplier to 0, as the Multiplier Determines how strong the effect is.

@Calinou
Copy link
Member

Calinou commented Jul 31, 2022

If this 'fake shading' were to be added to godot, it should be an option in the project settings, and should definitely NOT be the default. I hope this makes stuff clear :)

At this point, I'd prefer to have a way to override BaseMaterial3D in a project so you can add your own customizations without having to use a ShaderMaterial everywhere. Project settings that are disabled by default will barely ever be used, so I'd prefer not to bloat the engine with optional tweaks like these.

@Zireael07
Copy link

I'd prefer to have a way to override BaseMaterial3D in a project so you can add your own customizations without having to use a ShaderMaterial everywhere.

Please please, this would be so useful for many things.

@WrobotGames
Copy link

WrobotGames commented Jul 31, 2022

At this point, I'd prefer to have a way to override BaseMaterial3D in a project so you can add your own customizations without having to use a ShaderMaterial everywhere.

A slot somewhere in the project settings where you could use your own shader as defaultshader would indeed be really handy for projects with a more stylized art direction.
Tweaks like the one mentioned in this issue could probably be done in de light shader.

@clayjohn
Copy link
Member

clayjohn commented Aug 1, 2022

This is a very cheap and very fake way to approximate ambient occlusion. Comparing the blender cycles render to the proposed implementation makes that very clear. This adds occlusion to every tangential surface in motion you will see the occlusion swimming across the surface of objects. It essentially is faking a large light source between the camera and object.

In the cycles render you can see occlusion is only present in occluded areas (between the model's legs for example).

In Godot you can achieve this looks by either specifying ambient occlusion maps in the baseMaterial (most accurate) or by turning on SSAO (easier but less accurate).

I do not think we should add such a specific hack to the engine.

@mrjustaguy
Copy link
Author

Closing as a suitable workaround for the issue was found (Calculating irradiance with a Gradient 2d texture with the top being Bright and bottom being Dark, providing Neutral Lighting that also makes depth visible, while also being done in a single shader (sky shader) and easy to control)

@Calinou Calinou closed this as not planned Won't fix, can't repro, duplicate, stale Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants