Add specular occlusion from ambient light

Co-authored-by: guerro323 <kaltobattle@gmail.com>
This commit is contained in:
landervr
2025-05-06 16:51:00 +02:00
parent 1a1cc0f7b0
commit 56730d0cb2
17 changed files with 72 additions and 6 deletions

View File

@@ -182,6 +182,9 @@
<member name="disable_receive_shadows" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], the object receives no shadow that would otherwise be cast onto it.
</member>
<member name="disable_specular_occlusion" type="bool" setter="set_flag" getter="get_flag" default="false">
If [code]true[/code], disables specular occlusion even if [member ProjectSettings.rendering/reflections/specular_occlusion/enabled] is [code]false[/code].
</member>
<member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance" default="10.0">
Distance at which the object appears fully opaque.
[b]Note:[/b] If [member distance_fade_max_distance] is less than [member distance_fade_min_distance], the behavior will be reversed. The object will start to fade away at [member distance_fade_max_distance] and will fully disappear once it reaches [member distance_fade_min_distance].
@@ -706,7 +709,10 @@
<constant name="FLAG_DISABLE_FOG" value="21" enum="Flags">
Disables receiving depth-based or volumetric fog.
</constant>
<constant name="FLAG_MAX" value="22" enum="Flags">
<constant name="FLAG_DISABLE_SPECULAR_OCCLUSION" value="22" enum="Flags">
Disables specular occlusion.
</constant>
<constant name="FLAG_MAX" value="23" enum="Flags">
Represents the size of the [enum Flags] enum.
</constant>
<constant name="DIFFUSE_BURLEY" value="0" enum="DiffuseMode">

View File

@@ -3095,6 +3095,9 @@
<member name="rendering/reflections/sky_reflections/texture_array_reflections.mobile" type="bool" setter="" getter="" default="false">
Lower-end override for [member rendering/reflections/sky_reflections/texture_array_reflections] on mobile devices, due to performance concerns or driver support.
</member>
<member name="rendering/reflections/specular_occlusion/enabled" type="bool" setter="" getter="" default="true">
If [code]true[/code], reduces reflections based on ambient light.
</member>
<member name="rendering/renderer/rendering_method" type="String" setter="" getter="" default="&quot;forward_plus&quot;">
Sets the renderer that will be used by the project. Options are:
[b]forward_plus[/b] (Forward+): High-end renderer designed for desktop devices. Has a higher base overhead, but scales well with complex scenes. Not suitable for older devices or mobile.

View File

@@ -4225,6 +4225,9 @@ RasterizerSceneGLES3::RasterizerSceneGLES3() {
if (config->force_vertex_shading) {
global_defines += "\n#define USE_VERTEX_LIGHTING\n";
}
if (!config->specular_occlusion) {
global_defines += "\n#define SPECULAR_OCCLUSION_DISABLED\n";
}
material_storage->shaders.scene_shader.initialize(global_defines);
scene_globals.shader_default_version = material_storage->shaders.scene_shader.version_create();
material_storage->shaders.scene_shader.version_bind_shader(scene_globals.shader_default_version, SceneShaderGLES3::MODE_COLOR);

View File

@@ -2120,8 +2120,18 @@ void main() {
#endif // USE_LIGHTMAP_CAPTURE
#endif // !DISABLE_LIGHTMAP
ambient_light *= albedo.rgb;
ambient_light *= ao;
#ifndef SPECULAR_OCCLUSION_DISABLED
float specular_occlusion = (ambient_light.r * 0.3 + ambient_light.g * 0.59 + ambient_light.b * 0.11) * 2.0; // Luminance of ambient light.
specular_occlusion = min(specular_occlusion * 4.0, 1.0); // This multiplication preserves speculars on bright areas.
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a magic number, it gives the intended effect in most scenarios.
// Low enough for occlusion, high enough for reaction to lights and shadows.
specular_occlusion = max(min(reflective_f * specular_occlusion * 10.0, 1.0), specular_occlusion);
specular_light *= specular_occlusion;
#endif // !SPECULAR_OCCLUSION_DISABLED
ambient_light *= albedo.rgb;
#endif // !AMBIENT_LIGHT_DISABLED

View File

@@ -185,6 +185,7 @@ Config::Config() {
#endif
force_vertex_shading = GLOBAL_GET("rendering/shading/overrides/force_vertex_shading");
specular_occlusion = GLOBAL_GET("rendering/reflections/specular_occlusion/enabled");
use_nearest_mip_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter");
use_depth_prepass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable"));

View File

@@ -83,6 +83,7 @@ public:
bool srgb_framebuffer_supported = false;
bool force_vertex_shading = false;
bool specular_occlusion = false;
bool support_anisotropic_filter = false;
float anisotropic_level = 0.0f;

View File

@@ -1382,6 +1382,8 @@ MaterialStorage::MaterialStorage() {
}
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.render_mode_defines["specular_occlusion_disabled"] = "#define SPECULAR_OCCLUSION_DISABLED\n";
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;

View File

@@ -873,7 +873,9 @@ void BaseMaterial3D::_update_shader() {
if (flags[FLAG_DISABLE_FOG]) {
code += ", fog_disabled";
}
if (flags[FLAG_DISABLE_SPECULAR_OCCLUSION]) {
code += ", specular_occlusion_disabled";
}
if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
code += ", depth_prepass_alpha";
}
@@ -3208,6 +3210,7 @@ void BaseMaterial3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Toon,Disabled"), "set_specular_mode", "get_specular_mode");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_ambient_light"), "set_flag", "get_flag", FLAG_DISABLE_AMBIENT_LIGHT);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_fog"), "set_flag", "get_flag", FLAG_DISABLE_FOG);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "disable_specular_occlusion"), "set_flag", "get_flag", FLAG_DISABLE_SPECULAR_OCCLUSION);
ADD_GROUP("Vertex Color", "vertex_color");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR);
@@ -3466,6 +3469,7 @@ void BaseMaterial3D::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_PARTICLE_TRAILS_MODE);
BIND_ENUM_CONSTANT(FLAG_ALBEDO_TEXTURE_MSDF);
BIND_ENUM_CONSTANT(FLAG_DISABLE_FOG);
BIND_ENUM_CONSTANT(FLAG_DISABLE_SPECULAR_OCCLUSION);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);

View File

@@ -267,6 +267,7 @@ public:
FLAG_PARTICLE_TRAILS_MODE,
FLAG_ALBEDO_TEXTURE_MSDF,
FLAG_DISABLE_FOG,
FLAG_DISABLE_SPECULAR_OCCLUSION,
FLAG_MAX
};

View File

@@ -4872,6 +4872,11 @@ RenderForwardClustered::RenderForwardClustered() {
defines += "\n#define USE_VERTEX_LIGHTING\n";
}
bool specular_occlusion = GLOBAL_GET("rendering/reflections/specular_occlusion/enabled");
if (!specular_occlusion) {
defines += "\n#define SPECULAR_OCCLUSION_DISABLED\n";
}
{
//lightmaps
scene_state.max_lightmaps = MAX_LIGHTMAPS;

View File

@@ -766,6 +766,8 @@ void SceneShaderForwardClustered::init(const String p_defines) {
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.render_mode_defines["specular_occlusion_disabled"] = "#define SPECULAR_OCCLUSION_DISABLED\n";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
actions.base_uniform_string = "material.";

View File

@@ -3221,6 +3221,11 @@ RenderForwardMobile::RenderForwardMobile() {
defines += "\n#define USE_VERTEX_LIGHTING\n";
}
bool specular_occlusion = GLOBAL_GET("rendering/reflections/specular_occlusion/enabled");
if (!specular_occlusion) {
defines += "\n#define SPECULAR_OCCLUSION_DISABLED\n";
}
{
//lightmaps
scene_state.max_lightmaps = 2;

View File

@@ -698,6 +698,8 @@ void SceneShaderForwardMobile::init(const String p_defines) {
actions.render_mode_defines["debug_shadow_splits"] = "#define DEBUG_DRAW_PSSM_SPLITS\n";
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";
actions.render_mode_defines["specular_occlusion_disabled"] = "#define SPECULAR_OCCLUSION_DISABLED\n";
actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
actions.base_uniform_string = "material.";

View File

@@ -1969,8 +1969,18 @@ void fragment_shader(in SceneData scene_data) {
//finalize ambient light here
{
ambient_light *= albedo.rgb;
ambient_light *= ao;
#ifndef SPECULAR_OCCLUSION_DISABLED
float specular_occlusion = (ambient_light.r * 0.3 + ambient_light.g * 0.59 + ambient_light.b * 0.11) * 2.0; // Luminance of ambient light.
specular_occlusion = min(specular_occlusion * 4.0, 1.0); // This multiplication preserves speculars on bright areas.
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a magic number, it gives the intended effect in most scenarios.
// Low enough for occlusion, high enough for reaction to lights and shadows.
specular_occlusion = max(min(reflective_f * specular_occlusion * 10.0, 1.0), specular_occlusion);
specular_light *= specular_occlusion;
#endif // SPECULAR_OCCLUSION_DISABLED
ambient_light *= albedo.rgb;
if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) {
#ifdef USE_MULTIVIEW

View File

@@ -1437,9 +1437,18 @@ void main() {
} //Reflection probes
// finalize ambient light here
ambient_light *= albedo.rgb;
ambient_light *= ao;
#ifndef SPECULAR_OCCLUSION_DISABLED
float specular_occlusion = (ambient_light.r * 0.3 + ambient_light.g * 0.59 + ambient_light.b * 0.11) * 2.0; // Luminance of ambient light.
specular_occlusion = min(specular_occlusion * 4.0, 1.0); // This multiplication preserves speculars on bright areas.
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a magic number, it gives the intended effect in most scenarios.
// Low enough for occlusion, high enough for reaction to lights and shadows.
specular_occlusion = max(min(reflective_f * specular_occlusion * 10.0, 1.0), specular_occlusion);
specular_light *= specular_occlusion;
#endif // USE_SPECULAR_OCCLUSION
ambient_light *= albedo.rgb;
#endif // !AMBIENT_LIGHT_DISABLED

View File

@@ -242,6 +242,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("alpha_to_coverage_and_one") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("debug_shadow_splits") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("fog_disabled") });
shader_modes[RS::SHADER_SPATIAL].modes.push_back({ PNAME("specular_occlusion_disabled") });
}
/************ CANVAS ITEM **************************/

View File

@@ -3632,6 +3632,7 @@ void RenderingServer::init() {
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_size", PROPERTY_HINT_RANGE, "0,4096,1"), 256);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_size.mobile", PROPERTY_HINT_RANGE, "0,2048,1"), 128);
GLOBAL_DEF(PropertyInfo(Variant::INT, "rendering/reflections/reflection_atlas/reflection_count", PROPERTY_HINT_RANGE, "0,256,1"), 64);
GLOBAL_DEF_RST("rendering/reflections/specular_occlusion/enabled", true);
GLOBAL_DEF("rendering/global_illumination/gi/use_half_resolution", false);