@@ -915,23 +915,37 @@ 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 distance_to_hit_point = 0.0 ;
919+ float mip = sqrt (roughness) * MAX_ROUGHNESS_LOD;
920+ float mip_min = pow (roughness, 2.0 ) * MAX_ROUGHNESS_LOD; // Ensures fully rough materials don't have reflection contact hardening.
918921 if (reflections.data[ref_index].box_project) { // box project
919922
920923 vec3 nrdir = normalize (local_ref_vec);
921924 vec3 rbmax = (box_extents - local_pos) / nrdir;
922925 vec3 rbmin = (- box_extents - local_pos) / nrdir;
923926
924927 vec3 rbminmax = mix (rbmin, rbmax, greaterThan (nrdir, vec3 (0.0 , 0.0 , 0.0 )));
928+ distance_to_hit_point = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
925929
926930 float fa = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
927931 vec3 posonbox = local_pos + nrdir * fa;
928932 local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
933+
934+ float fresnel = 1.0 - max (dot (normal, - normalize (vertex)), 0.0 );
935+ fresnel = pow (fresnel, 2.0 );
936+
937+ float reflection_roughness = distance_to_hit_point * (1.0 - fresnel); // Adjust contact hardening strength by viewing angle.
938+ reflection_roughness /= MAX_ROUGHNESS_LOD;
939+ reflection_roughness += ((1.0 - fresnel) * sqrt (roughness)); // Increase roughness when viewing angle is perpendicular to avoid overly sharp reflections on rough surfaces.
940+
941+ float mip_offset = clamp (reflection_roughness, 0.0 , 1.0 ); // Compute new mip level based on the mip offset value (this is mostly arbitrary).
942+ mip = mix (mip_min, mip, mip_offset);
929943 }
930944
931945 vec4 reflection;
932946 float reflection_blend = max (0.0 , blend - reflection_accum.a);
933947
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();
948+ 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();
935949 reflection.rgb *= reflections.data[ref_index].exposure_normalization;
936950 reflection.a = reflection_blend;
937951
0 commit comments