@@ -930,23 +930,35 @@ void reflection_process(uint ref_index, vec3 vertex, hvec3 ref_vec, hvec3 normal
930930
931931 vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4 (ref_vec, 0.0 )).xyz;
932932
933+ float mip = sqrt (roughness) * MAX_ROUGHNESS_LOD;
934+ float mip_min = pow (roughness, 2.0 ) * MAX_ROUGHNESS_LOD; // Ensures fully rough materials don't have reflection contact hardening.
933935 if (reflections.data[ref_index].box_project) { // box project
934936
935937 vec3 nrdir = normalize (local_ref_vec);
936938 vec3 rbmax = (box_extents - local_pos) / nrdir;
937939 vec3 rbmin = (- box_extents - local_pos) / nrdir;
938940
939941 vec3 rbminmax = mix (rbmin, rbmax, greaterThan (nrdir, vec3 (0.0 , 0.0 , 0.0 )));
942+ float distance_to_hit_point = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
940943
941- float fa = min (min (rbminmax.x, rbminmax.y), rbminmax.z);
942- vec3 posonbox = local_pos + nrdir * fa;
944+ vec3 posonbox = local_pos + nrdir * distance_to_hit_point;
943945 local_ref_vec = posonbox - reflections.data[ref_index].box_offset;
946+
947+ float fresnel = 1.0 - max (dot (normal, - normalize (vertex)), 0.0 );
948+ fresnel = pow (fresnel, 4.0 );
949+
950+ float reflection_roughness = distance_to_hit_point / MAX_ROUGHNESS_LOD; // Remap distance to be relative to amount of mips.
951+ reflection_roughness *= 1.0 - fresnel;
952+ reflection_roughness += ((1.0 - fresnel) * sqrt (roughness)); // Increase roughness when viewing angle is perpendicular to avoid overly sharp reflections on rough surfaces.
953+
954+ float mip_offset = clamp (reflection_roughness, 0.0 , 1.0 ); // Compute new mip level based on the mip offset value (this is mostly arbitrary).
955+ mip = mix (mip_min, mip, mip_offset);
944956 }
945957
946958 hvec4 reflection;
947959 half reflection_blend = max (half(0.0 ), blend - reflection_accum.a);
948960
949- 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();
961+ 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();
950962 reflection.rgb *= half(reflections.data[ref_index].exposure_normalization);
951963 reflection.a = reflection_blend;
952964
0 commit comments