Skip to content

Commit e9a71e6

Browse files
lander-vrCalinou
andcommitted
Add contact hardening and fresnel based roughness to reflection probes reflections when using box projection
Co-authored-by: Calinou <[email protected]>
1 parent 5dd7696 commit e9a71e6

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

drivers/gles3/shaders/scene.glsl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,20 +1666,32 @@ void reflection_process(samplerCube reflection_map,
16661666
vec3 ref_normal = normalize(reflect(vertex, normal));
16671667
ref_normal = (local_matrix * vec4(ref_normal, 0.0)).xyz;
16681668

1669+
float mip = sqrt(roughness) * MAX_ROUGHNESS_LOD;
1670+
float mip_min = pow(roughness, 2.0) * MAX_ROUGHNESS_LOD; // Ensures fully rough materials don't have reflection contact hardening.
16691671
if (use_box_project) { //box project
16701672

16711673
vec3 nrdir = normalize(ref_normal);
16721674
vec3 rbmax = (box_extents - local_pos) / nrdir;
16731675
vec3 rbmin = (-box_extents - local_pos) / nrdir;
16741676

16751677
vec3 rbminmax = mix(rbmin, rbmax, vec3(greaterThan(nrdir, vec3(0.0, 0.0, 0.0))));
1678+
float distance_to_hit_point = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
16761679

1677-
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
1678-
vec3 posonbox = local_pos + nrdir * fa;
1680+
vec3 posonbox = local_pos + nrdir * distance_to_hit_point;
16791681
ref_normal = posonbox - box_offset.xyz;
1682+
1683+
float fresnel = 1.0 - max(dot(normal, -normalize(vertex)), 0.0);
1684+
fresnel = pow(fresnel, 2.0);
1685+
1686+
float reflection_roughness = distance_to_hit_point * (1.0 - fresnel); // Adjust contact hardening strength by viewing angle.
1687+
reflection_roughness /= MAX_ROUGHNESS_LOD;
1688+
reflection_roughness += ((1.0 - fresnel) * sqrt(roughness)); // Increase roughness when viewing angle is perpendicular to avoid overly sharp reflections on rough surfaces.
1689+
1690+
float mip_offset = clamp(reflection_roughness, 0.0, 1.0); // Compute new mip level based on the mip offset value (this is mostly arbitrary).
1691+
mip = mix(mip_min, mip, mip_offset);
16801692
}
16811693

1682-
reflection.rgb = srgb_to_linear(textureLod(reflection_map, ref_normal, roughness * MAX_ROUGHNESS_LOD).rgb);
1694+
reflection.rgb = srgb_to_linear(textureLod(reflection_map, ref_normal, mip).rgb);
16831695

16841696
if (exterior) {
16851697
reflection.rgb = mix(skybox, reflection.rgb, blend);

servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -915,23 +915,35 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal,
915915

916916
vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz;
917917

918+
float mip = sqrt(roughness) * MAX_ROUGHNESS_LOD;
919+
float mip_min = pow(roughness, 2.0) * MAX_ROUGHNESS_LOD; // Ensures fully rough materials don't have reflection contact hardening.
918920
if (reflections.data[ref_index].box_project) { //box project
919921

920922
vec3 nrdir = normalize(local_ref_vec);
921923
vec3 rbmax = (box_extents - local_pos) / nrdir;
922924
vec3 rbmin = (-box_extents - local_pos) / nrdir;
923925

924926
vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0)));
927+
float distance_to_hit_point = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
925928

926-
float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
927-
vec3 posonbox = local_pos + nrdir * fa;
929+
vec3 posonbox = local_pos + nrdir * distance_to_hit_point;
928930
local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
931+
932+
float fresnel = 1.0 - max(dot(normal, -normalize(vertex)), 0.0);
933+
fresnel = pow(fresnel, 2.0);
934+
935+
float reflection_roughness = distance_to_hit_point * (1.0 - fresnel); // Adjust contact hardening strength by viewing angle.
936+
reflection_roughness /= MAX_ROUGHNESS_LOD;
937+
reflection_roughness += ((1.0 - fresnel) * sqrt(roughness)); // Increase roughness when viewing angle is perpendicular to avoid overly sharp reflections on rough surfaces.
938+
939+
float mip_offset = clamp(reflection_roughness, 0.0, 1.0); // Compute new mip level based on the mip offset value (this is mostly arbitrary).
940+
mip = mix(mip_min, mip, mip_offset);
929941
}
930942

931943
vec4 reflection;
932944
float reflection_blend = max(0.0, blend - reflection_accum.a);
933945

934-
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), sqrt(roughness) * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier();
946+
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4(local_ref_vec, reflections.data[ref_index].index), mip).rgb * sc_luminance_multiplier();
935947
reflection.rgb *= reflections.data[ref_index].exposure_normalization;
936948
reflection.a = reflection_blend;
937949

0 commit comments

Comments
 (0)