 
         vec3 filtered = vec3(0,0,0);
         if (roughness > 0.4) {
-          const float m0 = 0.5 * roughness;
-          const float step = 1.0 * roughness;
-          for(float x = -m0; x <= m0; x += step) {
-              for(float y = -m0; y <= m0; y += step ) {
-                for(float z = -m0; z <= m0; z += step ) {
-                    const mat3 rotx = rotate(vec3(1.0, 0.0, 0.0), x);
-                    const mat3 roty = rotate(vec3(0.0, 1.0, 0.0), y);
-                    const mat3 rotz = rotate(vec3(0.0, 0.0, 1.0), z);
-                    filtered += textureLod(environment_samplers[i], rotx * roty * rotz * corrected_R, mip_level).rgb;
-                  }
-              }
-          }
-          filtered /= 8.0;
+          filtered = sample_environment(environment_samplers[i], corrected_R, mip_level, 0.5 * roughness, 1.0 * roughness);
         } else {
           filtered = textureLod(environment_samplers[i], corrected_R, mip_level).rgb;
         }

vec3 fresnel_schlick_roughness(float cosTheta, vec3 F0, float roughness);
float fog_attenuation(const float dist, const float factor);

bool inside_box(const vec3 point, const vec3 position, const vec3 extent) {
  vec3 mi = position - extent;
  vec3 ma = position + extent;


        vec3 specular_environment = mix(refraction, filtered, F_env * brdf.x + brdf.y) * horiz * environments[i].strength;

        vec3 irradiance = sample_environment(environment_samplers[i], corrected_N, num_levels - 1.5, 0.5, 1.0);

        const vec3 diffuse_environment = irradiance * albedo * environments[i].strength;

