@@ -921,23 +921,35 @@ void reflection_process(uint ref_index, vec3 vertex, hvec3 ref_vec, hvec3 normal
921921
922922 vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4 (ref_vec, 0.0 )).xyz;
923923
924+ float mip = sqrt (roughness) * MAX_ROUGHNESS_LOD;
925+ float mip_min = pow (roughness, 2.0 ) * MAX_ROUGHNESS_LOD; // Ensures fully rough materials don't have reflection contact hardening.
924926 if (reflections.data[ref_index].box_project) { // box project
925927
926928 vec3 nrdir = normalize (local_ref_vec);
927929 vec3 rbmax = (box_extents - local_pos) / nrdir;
928930 vec3 rbmin = (- box_extents - local_pos) / nrdir;
929931
930932 vec3 rbminmax = mix (rbmin, rbmax, greaterThan (nrdir, vec3 (0.0 , 0.0 , 0.0 )));
933+ float distance_to_hit_point = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
931934
932- float fa = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
933- vec3 posonbox = local_pos + nrdir * fa;
935+ vec3 posonbox = local_pos + nrdir * distance_to_hit_point;
934936 local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
937+
938+ float fresnel = 1.0 - max (dot (normal, - normalize (vertex)), 0.0 );
939+ fresnel = pow (fresnel, 4.0 );
940+
941+ float reflection_roughness = distance_to_hit_point / MAX_ROUGHNESS_LOD; // Remap distance to be relative to amount of mips.
942+ reflection_roughness *= 1.0 - fresnel;
943+ reflection_roughness += ((1.0 - fresnel) * sqrt (roughness)); // Increase roughness when viewing angle is perpendicular to avoid overly sharp reflections on rough surfaces.
944+
945+ float mip_offset = clamp (reflection_roughness, 0.0 , 1.0 ); // Compute new mip level based on the mip offset value (this is mostly arbitrary).
946+ mip = mix (mip_min, mip, mip_offset);
935947 }
936948
937949 hvec4 reflection;
938950 half reflection_blend = max (half(0.0 ), blend - reflection_accum.a);
939951
940- reflection.rgb = hvec3(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();
952+ reflection.rgb = hvec3(textureLod(samplerCubeArray (reflection_atlas, DEFAULT_SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP), vec4 (local_ref_vec, reflections.data[ref_index].index), mip ).rgb) * sc_luminance_multiplier();
941953 reflection.rgb *= half(reflections.data[ref_index].exposure_normalization);
942954 reflection.a = reflection_blend;
943955
0 commit comments