Skip to content

Commit 8318a82

Browse files
committed
add microshadows
1 parent eb3d6d8 commit 8318a82

File tree

11 files changed

+86
-10
lines changed

11 files changed

+86
-10
lines changed

drivers/gles3/shaders/scene.glsl

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,6 +1493,13 @@ float SchlickFresnel(float u) {
14931493
return m2 * m2 * m; // pow(m,5)
14941494
}
14951495

1496+
// Brinck and Maximov 2016, "The Technical Art of Uncharted 4"
1497+
float compute_micro_shadowing(float NoL, float ao, float opacity) {
1498+
float aperture = 2.0 * ao * ao;
1499+
float microshadow = clamp(NoL + aperture - 1.0, 0.0, 1.0);
1500+
return mix(1.0, microshadow, opacity);
1501+
}
1502+
14961503
void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, bool is_directional, float attenuation, vec3 f0, float roughness, float metallic, float specular_amount, vec3 albedo, inout float alpha, vec2 screen_uv,
14971504
#ifdef LIGHT_BACKLIGHT_USED
14981505
vec3 backlight,
@@ -2013,7 +2020,9 @@ void main() {
20132020
#endif
20142021

20152022
float ao = 1.0;
2023+
float direct_ao = 0.0;
20162024
float ao_light_affect = 0.0;
2025+
float micro_shadows = 0.0;
20172026

20182027
float alpha = 1.0;
20192028

@@ -2349,7 +2358,7 @@ void main() {
23492358
#endif // !AMBIENT_LIGHT_DISABLED
23502359

23512360
// convert ao to direct light ao
2352-
ao = mix(1.0, ao, ao_light_affect);
2361+
direct_ao = mix(1.0, ao, ao_light_affect);
23532362
#ifndef AMBIENT_LIGHT_DISABLED
23542363
{
23552364
#if defined(DIFFUSE_TOON)
@@ -2503,7 +2512,7 @@ void main() {
25032512
normal_output_buffer.rgb = normal * 0.5 + 0.5;
25042513
normal_output_buffer.a = 0.0;
25052514

2506-
orm_output_buffer.r = ao;
2515+
orm_output_buffer.r = direct_ao;
25072516
orm_output_buffer.g = roughness;
25082517
orm_output_buffer.b = metallic;
25092518
orm_output_buffer.a = 1.0;
@@ -2701,6 +2710,12 @@ void main() {
27012710
float directional_shadow = 1.0f;
27022711
#endif // SHADOWS_DISABLED
27032712

2713+
#ifdef MICRO_SHADOWS_USED
2714+
float NdotL = dot(normal, directional_lights[directional_shadow_index].direction);
2715+
// Disable microshadowing when facing away from light.
2716+
directional_shadow *= NdotL >= 0.0 ? compute_micro_shadowing(NdotL, ao, micro_shadows) : 1.0;
2717+
#endif
2718+
27042719
#ifndef USE_VERTEX_LIGHTING
27052720
if (bool(directional_lights[directional_shadow_index].mask & layer_mask)) {
27062721
light_compute(normal, normalize(directional_lights[directional_shadow_index].direction), normalize(view), directional_lights[directional_shadow_index].size, directional_lights[directional_shadow_index].color * directional_lights[directional_shadow_index].energy, true, directional_shadow, f0, roughness, metallic, directional_lights[directional_shadow_index].specular, albedo, alpha, screen_uv,

drivers/gles3/storage/material_storage.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,7 @@ MaterialStorage::MaterialStorage() {
13061306
actions.renames["BACKLIGHT"] = "backlight";
13071307
actions.renames["AO"] = "ao";
13081308
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
1309+
actions.renames["MICRO_SHADOWS"] = "micro_shadows";
13091310
actions.renames["EMISSION"] = "emission";
13101311
actions.renames["POINT_COORD"] = "gl_PointCoord";
13111312
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
@@ -1354,6 +1355,7 @@ MaterialStorage::MaterialStorage() {
13541355
actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
13551356
actions.usage_defines["AO"] = "#define AO_USED\n";
13561357
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
1358+
actions.usage_defines["MICRO_SHADOWS"] = "#define MICRO_SHADOWS_USED\n";
13571359
actions.usage_defines["UV"] = "#define UV_USED\n";
13581360
actions.usage_defines["UV2"] = "#define UV2_USED\n";
13591361
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";

scene/resources/material.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ void BaseMaterial3D::init_shaders() {
623623
shader_names->grow = "grow";
624624

625625
shader_names->ao_light_affect = "ao_light_affect";
626+
shader_names->micro_shadows = "micro_shadows";
626627

627628
shader_names->proximity_fade_distance = "proximity_fade_distance";
628629
shader_names->distance_fade_min = "distance_fade_min";
@@ -1128,6 +1129,7 @@ uniform sampler2D texture_flowmap : hint_anisotropy, %s;
11281129
uniform sampler2D texture_ambient_occlusion : hint_default_white, %s;
11291130
uniform vec4 ao_texture_channel;
11301131
uniform float ao_light_affect : hint_range(0.0, 1.0, 0.01);
1132+
uniform float micro_shadows : hint_range(0.0, 1.0, 0.01);
11311133
)",
11321134
texfilter_str);
11331135
}
@@ -1949,6 +1951,7 @@ void fragment() {)";
19491951
}
19501952

19511953
code += " AO_LIGHT_AFFECT = ao_light_affect;\n";
1954+
code += " MICRO_SHADOWS = micro_shadows;\n";
19521955
}
19531956

19541957
if (features[FEATURE_SUBSURFACE_SCATTERING]) {
@@ -2245,6 +2248,15 @@ float BaseMaterial3D::get_ao_light_affect() const {
22452248
return ao_light_affect;
22462249
}
22472250

2251+
void BaseMaterial3D::set_micro_shadows(float p_micro_shadows) {
2252+
micro_shadows = p_micro_shadows;
2253+
_material_set_param(shader_names->micro_shadows, p_micro_shadows);
2254+
}
2255+
2256+
float BaseMaterial3D::get_micro_shadows() const {
2257+
return micro_shadows;
2258+
}
2259+
22482260
void BaseMaterial3D::set_clearcoat(float p_clearcoat) {
22492261
clearcoat = p_clearcoat;
22502262
_material_set_param(shader_names->clearcoat, p_clearcoat);
@@ -3508,6 +3520,9 @@ void BaseMaterial3D::_bind_methods() {
35083520
ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &BaseMaterial3D::set_ao_light_affect);
35093521
ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &BaseMaterial3D::get_ao_light_affect);
35103522

3523+
ClassDB::bind_method(D_METHOD("set_micro_shadows", "amount"), &BaseMaterial3D::set_micro_shadows);
3524+
ClassDB::bind_method(D_METHOD("get_micro_shadows"), &BaseMaterial3D::get_micro_shadows);
3525+
35113526
ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &BaseMaterial3D::set_alpha_scissor_threshold);
35123527
ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &BaseMaterial3D::get_alpha_scissor_threshold);
35133528

@@ -3657,6 +3672,7 @@ void BaseMaterial3D::_bind_methods() {
36573672
ADD_GROUP("Ambient Occlusion", "ao_");
36583673
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled", PROPERTY_HINT_GROUP_ENABLE), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION);
36593674
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect");
3675+
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ao_micro_shadows", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_micro_shadows", "get_micro_shadows");
36603676
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION);
36613677
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2);
36623678
ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel");
@@ -3971,6 +3987,7 @@ BaseMaterial3D::BaseMaterial3D(bool p_orm) :
39713987
set_distance_fade_max_distance(10);
39723988

39733989
set_ao_light_affect(0.0);
3990+
set_micro_shadows(0.85);
39743991

39753992
set_metallic_texture_channel(TEXTURE_CHANNEL_RED);
39763993
set_roughness_texture_channel(TEXTURE_CHANNEL_RED);

scene/resources/material.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ class BaseMaterial3D : public Material {
502502
StringName distance_fade_min;
503503
StringName distance_fade_max;
504504
StringName ao_light_affect;
505+
StringName micro_shadows;
505506

506507
StringName metallic_texture_channel;
507508
StringName ao_texture_channel;
@@ -564,6 +565,7 @@ class BaseMaterial3D : public Material {
564565
float alpha_antialiasing_edge = 0.0f;
565566
bool grow_enabled = false;
566567
float ao_light_affect = 0.0f;
568+
float micro_shadows = 0.85f;
567569
float grow = 0.0f;
568570
int particles_anim_h_frames = 0;
569571
int particles_anim_v_frames = 0;
@@ -677,6 +679,9 @@ class BaseMaterial3D : public Material {
677679
void set_ao_light_affect(float p_ao_light_affect);
678680
float get_ao_light_affect() const;
679681

682+
void set_micro_shadows(float p_micro_shadows);
683+
float get_micro_shadows() const;
684+
680685
void set_clearcoat(float p_clearcoat);
681686
float get_clearcoat() const;
682687

servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
747747
actions.renames["BACKLIGHT"] = "backlight";
748748
actions.renames["AO"] = "ao";
749749
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
750+
actions.renames["MICRO_SHADOWS"] = "micro_shadows";
750751
actions.renames["EMISSION"] = "emission";
751752
actions.renames["POINT_COORD"] = "gl_PointCoord";
752753
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
@@ -795,6 +796,7 @@ void SceneShaderForwardClustered::init(const String p_defines) {
795796
actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
796797
actions.usage_defines["AO"] = "#define AO_USED\n";
797798
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
799+
actions.usage_defines["MICRO_SHADOWS"] = "#define MICRO_SHADOWS_USED\n";
798800
actions.usage_defines["UV"] = "#define UV_USED\n";
799801
actions.usage_defines["UV2"] = "#define UV2_USED\n";
800802
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";

servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
682682
actions.renames["BACKLIGHT"] = "backlight_highp";
683683
actions.renames["AO"] = "ao_highp";
684684
actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect_highp";
685+
actions.renames["MICRO_SHADOWS"] = "micro_shadows_highp";
685686
actions.renames["EMISSION"] = "emission_highp";
686687
actions.renames["POINT_COORD"] = "gl_PointCoord";
687688
actions.renames["INSTANCE_CUSTOM"] = "instance_custom";
@@ -730,6 +731,7 @@ void SceneShaderForwardMobile::init(const String p_defines) {
730731
actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
731732
actions.usage_defines["AO"] = "#define AO_USED\n";
732733
actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n";
734+
actions.usage_defines["MICRO_SHADOWS"] = "#define MICRO_SHADOWS_USED\n";
733735
actions.usage_defines["UV"] = "#define UV_USED\n";
734736
actions.usage_defines["UV2"] = "#define UV2_USED\n";
735737
actions.usage_defines["BONE_INDICES"] = "#define BONES_USED\n";

servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,7 +1203,9 @@ void fragment_shader(in SceneData scene_data) {
12031203
#endif
12041204

12051205
float ao = 1.0;
1206+
float direct_ao = 0.0;
12061207
float ao_light_affect = 0.0;
1208+
float micro_shadows = 0.0;
12071209

12081210
float alpha_highp = float(instances.data[instance_index].flags >> INSTANCE_FLAGS_FADE_SHIFT) / float(255.0);
12091211

@@ -2130,7 +2132,7 @@ void fragment_shader(in SceneData scene_data) {
21302132
#endif // AMBIENT_LIGHT_DISABLED
21312133

21322134
// convert ao to direct light ao
2133-
ao = mix(1.0, ao, ao_light_affect);
2135+
direct_ao = mix(1.0, ao, ao_light_affect);
21342136

21352137
//this saves some VGPRs
21362138
vec3 f0 = F0(metallic, specular, albedo);
@@ -2534,6 +2536,12 @@ void fragment_shader(in SceneData scene_data) {
25342536
shadow = 1.0;
25352537
#endif
25362538

2539+
#ifdef MICRO_SHADOWS_USED
2540+
float NdotL = dot(normal, directional_lights.data[i].direction);
2541+
// Disable microshadowing when facing away from light.
2542+
shadow *= NdotL >= 0.0 ? compute_micro_shadowing(NdotL, ao, micro_shadows) : 1.0;
2543+
#endif
2544+
25372545
float size_A = sc_use_directional_soft_shadows() ? directional_lights.data[i].size : 0.0;
25382546

25392547
light_compute(normal, directional_lights.data[i].direction, normalize(view), size_A,
@@ -2820,7 +2828,7 @@ void fragment_shader(in SceneData scene_data) {
28202828
normal_output_buffer.a = 0.0;
28212829
depth_output_buffer.r = -vertex.z;
28222830

2823-
orm_output_buffer.r = ao;
2831+
orm_output_buffer.r = direct_ao;
28242832
orm_output_buffer.g = roughness;
28252833
orm_output_buffer.b = metallic;
28262834
orm_output_buffer.a = sss_strength;
@@ -2861,8 +2869,8 @@ void fragment_shader(in SceneData scene_data) {
28612869
diffuse_light *= albedo; // ambient must be multiplied by albedo at the end
28622870

28632871
// apply direct light AO
2864-
diffuse_light *= ao;
2865-
direct_specular_light *= ao;
2872+
diffuse_light *= direct_ao;
2873+
direct_specular_light *= direct_ao;
28662874

28672875
// apply metallic
28682876
diffuse_light *= 1.0 - metallic;

servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,13 @@ vec3 get_energy_compensation(vec3 f0, float env) {
470470
return 1.0 + f0 * (1.0 / env - 1.0);
471471
}
472472

473+
// Brinck and Maximov 2016, "The Technical Art of Uncharted 4"
474+
float compute_micro_shadowing(float NoL, float ao, float opacity) {
475+
float aperture = 2.0 * ao * ao;
476+
float microshadow = clamp(NoL + aperture - 1.0, 0.0, 1.0);
477+
return mix(1.0, microshadow, opacity);
478+
}
479+
473480
/* Set 2 Skeleton & Instancing (can change per item) */
474481

475482
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {

servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,9 @@ void main() {
11231123
#endif
11241124

11251125
float ao_highp = 1.0;
1126+
float direct_ao_highp = 0.0;
11261127
float ao_light_affect_highp = 0.0;
1128+
float micro_shadows_highp = 0.0;
11271129

11281130
float alpha_highp = 1.0;
11291131

@@ -1234,6 +1236,8 @@ void main() {
12341236
hvec2 anisotropy_flow = hvec2(anisotropy_flow_highp);
12351237
half ao = half(ao_highp);
12361238
half ao_light_affect = half(ao_light_affect_highp);
1239+
half direct_ao = half(direct_ao_highp);
1240+
half micro_shadows = half(micro_shadows_highp);
12371241
half alpha = half(alpha_highp);
12381242
half normal_map_depth = half(normal_map_depth_highp);
12391243
half sss_strength = half(sss_strength_highp);
@@ -1786,7 +1790,7 @@ void main() {
17861790
#endif // !AMBIENT_LIGHT_DISABLED
17871791

17881792
// convert ao to direct light ao
1789-
ao = mix(half(1.0), ao, ao_light_affect);
1793+
direct_ao = mix(half(1.0), ao, ao_light_affect);
17901794

17911795
//this saves some VGPRs
17921796
hvec3 f0 = F0(metallic, specular, albedo);
@@ -2029,6 +2033,12 @@ void main() {
20292033
shadow = half(1.0);
20302034
#endif
20312035

2036+
#ifdef MICRO_SHADOWS_USED
2037+
float NdotL = dot(normal, directional_lights.data[i].direction);
2038+
// Disable microshadowing when facing away from light.
2039+
shadow *= NdotL >= 0.0 ? compute_micro_shadowing(NdotL, ao, micro_shadows) : 1.0;
2040+
#endif
2041+
20322042
float size_A = sc_use_light_soft_shadows() ? directional_lights.data[i].size : 0.0;
20332043

20342044
light_compute(normal, hvec3(directional_lights.data[i].direction), view, saturateHalf(size_A),
@@ -2161,7 +2171,7 @@ void main() {
21612171
normal_output_buffer.a = 0.0;
21622172
depth_output_buffer.r = -vertex.z;
21632173

2164-
orm_output_buffer.r = ao;
2174+
orm_output_buffer.r = direct_ao;
21652175
orm_output_buffer.g = roughness;
21662176
orm_output_buffer.b = metallic;
21672177
orm_output_buffer.a = sss_strength;
@@ -2176,8 +2186,8 @@ void main() {
21762186
diffuse_light *= albedo; // ambient must be multiplied by albedo at the end
21772187

21782188
// apply direct light AO
2179-
diffuse_light *= ao;
2180-
direct_specular_light *= ao;
2189+
diffuse_light *= direct_ao;
2190+
direct_specular_light *= direct_ao;
21812191

21822192
// apply metallic
21832193
diffuse_light *= half(1.0) - metallic;

servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,13 @@ layout(set = 1, binding = 13 + 9) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_RE
383383
layout(set = 1, binding = 13 + 10) uniform sampler SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT;
384384
layout(set = 1, binding = 13 + 11) uniform sampler SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT;
385385

386+
// Brinck and Maximov 2016, "The Technical Art of Uncharted 4"
387+
float compute_micro_shadowing(float NoL, float ao, float opacity) {
388+
float aperture = 2.0 * ao * ao;
389+
float microshadow = clamp(NoL + aperture - 1.0, 0.0, 1.0);
390+
return mix(1.0, microshadow, opacity);
391+
}
392+
386393
/* Set 2 Skeleton & Instancing (can change per item) */
387394

388395
layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms {

0 commit comments

Comments
 (0)