Skip to content

Commit

Permalink
(rebased) first version of specular occlusion
Browse files Browse the repository at this point in the history
  • Loading branch information
Geometror committed Jan 6, 2025
1 parent 02e4605 commit 1d03d11
Show file tree
Hide file tree
Showing 12 changed files with 195 additions and 35 deletions.
8 changes: 7 additions & 1 deletion doc/classes/BaseMaterial3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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 of objects under the influence of a [LightmapGI] node regardless of [member ProjectSettings.rendering/lightmapping/specular_occlusion/mode].
</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].
Expand Down Expand Up @@ -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 produced by non-directional [LightmapGI] nodes.
</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">
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/ProjectSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2782,6 +2782,13 @@
<member name="rendering/lightmapping/probe_capture/update_speed" type="float" setter="" getter="" default="15">
The framerate-independent update speed when representing dynamic object lighting from [LightmapProbe]s. Higher values make dynamic object lighting update faster. Higher values can prevent fast-moving objects from having "outdated" indirect lighting displayed on them, at the cost of possible flickering when an object moves from a bright area to a shaded area.
</member>
<member name="rendering/lightmapping/specular_occlusion/mode" type="int" setter="" getter="" default="2">
The specular occlusion method for object lighting from [LightmapGI]s.
- Disabled: No specular occlusion is used
- Reduce: Reduce the energy by the current [LightmapGI] pixel brightness
- Conservative: Conserve most of the energy by mixing metallic and roughness values, resulting in more realistic surface
[b]Note:[/b] When [member LightmapGI.directional] is set to [code]true[/code], this feature is disabled.
</member>
<member name="rendering/lights_and_shadows/directional_shadow/16_bits" type="bool" setter="" getter="" default="true">
Use 16 bits for the directional shadow depth map. Enabling this results in shadows having less precision and may result in shadow acne, but can lead to performance improvements on some devices.
</member>
Expand Down
52 changes: 42 additions & 10 deletions drivers/gles3/shaders/scene.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -2058,17 +2058,32 @@ void main() {
const float c3 = 0.743125;
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures[0].rgb -
c5 * lightmap_captures[6].rgb +
2.0 * c1 * lightmap_captures[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures[2].rgb * wnormal.z) *
vec3 c = (c1 * lightmap_captures[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures[0].rgb -
c5 * lightmap_captures[6].rgb +
2.0 * c1 * lightmap_captures[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures[2].rgb * wnormal.z) *
scene_data.emissive_exposure_normalization;

#if defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float specular_occlusion = (c.r * 0.3 + c.g * 0.59 + c.b * 0.11) * 2.0; // brightness from lightmap color
specular_occlusion = min(1.0, specular_occlusion * scene_data.emissive_exposure_normalization);

#if defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a number picked by hand, 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);
#endif // defined(SPECULAR_OCCLUSION_CONSERVATIVE)

specular_light *= specular_occlusion;
#endif // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
ambient_light += c;
}
#else
#ifdef USE_LIGHTMAP
Expand Down Expand Up @@ -2102,7 +2117,24 @@ void main() {
#ifdef LIGHTMAP_BICUBIC_FILTER
ambient_light += textureArray_bicubic(lightmap_textures, uvw, lightmap_texture_size).rgb * lightmap_exposure_normalization;
#else
#if defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
vec3 c = textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;

float specular_occlusion = (c.r * 0.3 + c.g * 0.59 + c.b * 0.11) * 2.0; // brightness from lightmap color
specular_occlusion = min(1.0, specular_occlusion * lightmap_exposure_normalization);

#if defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a number picked by hand, 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);
#endif // defined(SPECULAR_OCCLUSION_CONSERVATIVE)

specular_light *= specular_occlusion;
ambient_light += c;
#else // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
ambient_light += textureLod(lightmap_textures, uvw, 0.0).rgb * lightmap_exposure_normalization;
#endif // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
#endif
#endif
}
Expand Down
13 changes: 13 additions & 0 deletions drivers/gles3/storage/material_storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1375,6 +1375,19 @@ MaterialStorage::MaterialStorage() {
}
actions.render_mode_defines["fog_disabled"] = "#define FOG_DISABLED\n";

int specular_occlusion_mode = GLOBAL_GET("rendering/lightmapping/specular_occlusion/mode");

switch (specular_occlusion_mode) {
case 0:
break; // disabled, skip
case 1:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION\n";
break;
case 2:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION_CONSERVATIVE\n";
break;
}

actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;

Expand Down
6 changes: 6 additions & 0 deletions scene/resources/material.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,7 @@ void BaseMaterial3D::_update_shader() {
case SPECULAR_MAX:
break; // Internal value, skip.
}

if (features[FEATURE_SUBSURFACE_SCATTERING] && flags[FLAG_SUBSURFACE_MODE_SKIN]) {
code += ", sss_mode_skin";
}
Expand Down Expand Up @@ -864,6 +865,9 @@ void BaseMaterial3D::_update_shader() {
if (flags[FLAG_DISABLE_FOG]) {
code += ", fog_disabled";
}
if (!flags[FLAG_DISABLE_SPECULAR_OCCLUSION]) {
code += ",specular_occlusion";
}

if (transparency == TRANSPARENCY_ALPHA_DEPTH_PRE_PASS) {
code += ", depth_prepass_alpha";
Expand Down Expand Up @@ -3175,6 +3179,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);
Expand Down Expand Up @@ -3429,6 +3434,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);
Expand Down
1 change: 1 addition & 0 deletions scene/resources/material.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ class BaseMaterial3D : public Material {
FLAG_PARTICLE_TRAILS_MODE,
FLAG_ALBEDO_TEXTURE_MSDF,
FLAG_DISABLE_FOG,
FLAG_DISABLE_SPECULAR_OCCLUSION,
FLAG_MAX
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,19 @@ 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";

int specular_occlusion_mode = GLOBAL_GET("rendering/lightmapping/specular_occlusion/mode");

switch (specular_occlusion_mode) {
case 0:
break; // disabled, skip
case 1:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION\n";
break;
case 2:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION_CONSERVATIVE\n";
break;
}

actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardClustered::MATERIAL_UNIFORM_SET;
actions.base_uniform_string = "material.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,19 @@ 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";

int specular_occlusion_mode = GLOBAL_GET("rendering/lightmapping/specular_occlusion/mode");

switch (specular_occlusion_mode) {
case 0:
break; // disabled, skip
case 1:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION\n";
break;
case 2:
actions.render_mode_defines["specular_occlusion"] = "#define SPECULAR_OCCLUSION_CONSERVATIVE\n";
break;
}

actions.base_texture_binding_index = 1;
actions.texture_layout_set = RenderForwardMobile::MATERIAL_UNIFORM_SET;
actions.base_uniform_string = "material.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1654,18 +1654,34 @@ void fragment_shader(in SceneData scene_data) {
const float c3 = 0.743125;
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures.data[index].sh[0].rgb -
c5 * lightmap_captures.data[index].sh[6].rgb +
2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *

vec3 c = (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
c4 * lightmap_captures.data[index].sh[0].rgb -
c5 * lightmap_captures.data[index].sh[6].rgb +
2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
scene_data.emissive_exposure_normalization;

#if defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float specular_occlusion = (c.r * 0.3 + c.g * 0.59 + c.b * 0.11) * 2.0; // brightness from lightmap color
specular_occlusion = min(1.0, specular_occlusion * scene_data.emissive_exposure_normalization);

#if defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a number picked by hand, 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);
#endif // defined(SPECULAR_OCCLUSION_CONSERVATIVE)

specular_light *= specular_occlusion;
#endif // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
ambient_light += c;

} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
uint ofs = instances.data[instance_index].gi_offset & 0xFFFF;
Expand Down Expand Up @@ -1702,11 +1718,30 @@ void fragment_shader(in SceneData scene_data) {
ambient_light += lm_light_l1p1 * n.x * (lm_light_l0 * en * 4.0);

} else {
vec3 c;
if (sc_use_lightmap_bicubic_filter()) {
ambient_light += textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization;
c = textureArray_bicubic(lightmap_textures[ofs], uvw, lightmaps.data[ofs].light_texture_size).rgb * lightmaps.data[ofs].exposure_normalization;
} else {
ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
c = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;
}
#if defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
// vec3 c = textureLod(sampler2DArray(lightmap_textures[ofs], SAMPLER_LINEAR_CLAMP), uvw, 0.0).rgb * lightmaps.data[ofs].exposure_normalization;

float specular_occlusion = (c.r * 0.3 + c.g * 0.59 + c.b * 0.11) * 2.0; // brightness from lightmap color
specular_occlusion = min(1.0, specular_occlusion * lightmaps.data[ofs].exposure_normalization);

#if defined(SPECULAR_OCCLUSION_CONSERVATIVE)
float reflective_f = (1.0 - roughness) * metallic;
// 10.0 is a number picked by hand, 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);
#endif // defined(SPECULAR_OCCLUSION_CONSERVATIVE)

specular_light *= specular_occlusion;
ambient_light += c;
#else // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
ambient_light += c;
#endif // defined(SPECULAR_OCCLUSION) || defined(SPECULAR_OCCLUSION_CONSERVATIVE)
}
}
#else
Expand Down
Loading

0 comments on commit 1d03d11

Please sign in to comment.