Eevee: Improve compilation time (reduce branching).
authorClément Foucault <foucault.clem@gmail.com>
Sat, 9 Jun 2018 18:48:19 +0000 (20:48 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Sat, 9 Jun 2018 19:11:03 +0000 (21:11 +0200)
This patch reduce the branching in the lamp loop, improving compilation time
noticeably (2372ms to 1785ms for the default shader).

This should not change the appearance of the shader.

Performance impact is negligeable.

source/blender/draw/CMakeLists.txt
source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/eevee/eevee_volumes.c
source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl [deleted file]
source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl

index 9c3aa34b5d80b30edac038ee96499697da14a147..b7eaecb7ab6e6f636c9492032d8a8b817249e7dc 100644 (file)
@@ -201,7 +201,6 @@ data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/shadow_copy_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC)
-data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/octahedron_lib.glsl SRC)
index 52c8ec985b86816358da8fb65ca0de20f255f9eb..3ce60e0ed75481d6fe4fa4ce88f0d5e668eacc18 100644 (file)
@@ -83,7 +83,6 @@ extern char datatoc_ltc_lib_glsl[];
 extern char datatoc_bsdf_lut_frag_glsl[];
 extern char datatoc_btdf_lut_frag_glsl[];
 extern char datatoc_bsdf_common_lib_glsl[];
-extern char datatoc_bsdf_direct_lib_glsl[];
 extern char datatoc_bsdf_sampling_lib_glsl[];
 extern char datatoc_common_uniforms_lib_glsl[];
 extern char datatoc_common_hair_lib_glsl[];
@@ -552,7 +551,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
                        datatoc_irradiance_lib_glsl,
                        datatoc_lightprobe_lib_glsl,
                        datatoc_ltc_lib_glsl,
-                       datatoc_bsdf_direct_lib_glsl,
                        datatoc_lamps_lib_glsl,
                        /* Add one for each Closure */
                        datatoc_lit_surface_frag_glsl,
@@ -574,7 +572,6 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E
                        datatoc_irradiance_lib_glsl,
                        datatoc_lightprobe_lib_glsl,
                        datatoc_ltc_lib_glsl,
-                       datatoc_bsdf_direct_lib_glsl,
                        datatoc_lamps_lib_glsl,
                        datatoc_volumetric_lib_glsl,
                        datatoc_volumetric_frag_glsl);
index 2d074eea522b9b22c968db75590b1e34ef6fd8cb..560f898b27583a0837027dadcdf1a552011af9f6 100644 (file)
@@ -65,7 +65,6 @@ static struct {
 } e_data = {NULL}; /* Engine data */
 
 extern char datatoc_bsdf_common_lib_glsl[];
-extern char datatoc_bsdf_direct_lib_glsl[];
 extern char datatoc_common_uniforms_lib_glsl[];
 extern char datatoc_common_view_lib_glsl[];
 extern char datatoc_octahedron_lib_glsl[];
@@ -92,7 +91,6 @@ static void eevee_create_shader_volumes(void)
                datatoc_common_view_lib_glsl,
                datatoc_common_uniforms_lib_glsl,
                datatoc_bsdf_common_lib_glsl,
-               datatoc_bsdf_direct_lib_glsl,
                datatoc_octahedron_lib_glsl,
                datatoc_irradiance_lib_glsl,
                datatoc_lamps_lib_glsl,
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
deleted file mode 100644 (file)
index aad71b3..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Bsdf direct light function */
-/* in other word, how materials react to scene lamps */
-
-/* Naming convention
- * V       View vector (normalized)
- * N       World Normal (normalized)
- * L       Outgoing Light Vector (Surface to Light in World Space) (normalized)
- * Ldist   Distance from surface to the light
- * W       World Pos
- */
-
-/* ------------ Diffuse ------------- */
-
-float direct_diffuse_point(vec3 N, vec4 l_vector)
-{
-       float dist = l_vector.w;
-       vec3 L = l_vector.xyz / dist;
-       float bsdf = max(0.0, dot(N, L));
-       bsdf /= dist * dist;
-       return bsdf;
-}
-
-/* infinitly far away point source, no decay */
-float direct_diffuse_sun(LightData ld, vec3 N)
-{
-       float bsdf = max(0.0, dot(N, -ld.l_forward));
-       bsdf *= M_1_PI; /* Normalize */
-       return bsdf;
-}
-
-#ifdef USE_LTC
-float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector)
-{
-       float NL = dot(N, l_vector.xyz / l_vector.w);
-
-       return ltc_evaluate_disk_simple(ld.l_radius / l_vector.w, NL);
-}
-
-float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector)
-{
-       vec3 corners[4];
-       corners[0] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up *  ld.l_sizey);
-       corners[1] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey);
-       corners[2] = normalize(l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up * -ld.l_sizey);
-       corners[3] = normalize(l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up *  ld.l_sizey);
-
-       return ltc_evaluate_quad(corners, N);
-}
-
-float direct_diffuse_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
-{
-       vec3 points[3];
-       points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
-       points[1] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up * -ld.l_sizey;
-       points[2] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up *  ld.l_sizey;
-
-       return ltc_evaluate_disk(N, V, mat3(1), points);
-}
-
-float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V)
-{
-       float NL = dot(N, -ld.l_forward);
-
-       return ltc_evaluate_disk_simple(ld.l_radius, NL);
-}
-#endif
-
-/* ----------- GGx ------------ */
-vec3 direct_ggx_point(vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
-{
-       roughness = max(1e-3, roughness);
-       float dist = l_vector.w;
-       vec3 L = l_vector.xyz / dist;
-       float bsdf = bsdf_ggx(N, L, V, roughness);
-       bsdf /= dist * dist;
-
-       /* Fresnel */
-       float VH = max(dot(V, normalize(V + L)), 0.0);
-       return F_schlick(f0, VH) * bsdf;
-}
-
-vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0)
-{
-       roughness = max(1e-3, roughness);
-       float bsdf = bsdf_ggx(N, -ld.l_forward, V, roughness);
-       float VH = dot(V, -ld.l_forward) * 0.5 + 0.5;
-       return F_schlick(f0, VH) * bsdf;
-}
-
-#ifdef USE_LTC
-vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
-{
-       roughness = clamp(roughness, 0.0008, 0.999); /* Fix low roughness artifacts. */
-
-       vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
-       vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
-       vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
-       mat3 ltc_mat = ltc_matrix(ltc_lut);
-
-       /* Make orthonormal basis. */
-       vec3 L = l_vector.xyz / l_vector.w;
-       vec3 Px, Py;
-       make_orthonormal_basis(L, Px, Py);
-       Px *= ld.l_radius;
-       Py *= ld.l_radius;
-
-       vec3 points[3];
-       points[0] = l_vector.xyz - Px - Py;
-       points[1] = l_vector.xyz + Px - Py;
-       points[2] = l_vector.xyz + Px + Py;
-
-       float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points);
-       bsdf *= brdf_lut.b; /* Bsdf intensity */
-
-       vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
-
-       return spec;
-}
-
-vec3 direct_ggx_ellipse(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
-{
-       vec3 points[3];
-       points[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
-       points[1] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up * -ld.l_sizey;
-       points[2] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up *  ld.l_sizey;
-
-       vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
-       vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
-       vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
-       mat3 ltc_mat = ltc_matrix(ltc_lut);
-
-       float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points);
-       bsdf *= brdf_lut.b; /* Bsdf intensity */
-
-       vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
-
-       return spec;
-}
-
-vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
-{
-       vec3 corners[4];
-       corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up *  ld.l_sizey;
-       corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
-       corners[2] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up * -ld.l_sizey;
-       corners[3] = l_vector.xyz + ld.l_right *  ld.l_sizex + ld.l_up *  ld.l_sizey;
-
-       vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
-       vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
-       vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
-       mat3 ltc_mat = ltc_matrix(ltc_lut);
-
-       ltc_transform_quad(N, V, ltc_mat, corners);
-       float bsdf = ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0));
-       bsdf *= brdf_lut.b; /* Bsdf intensity */
-
-       vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
-
-       return spec;
-}
-
-vec3 direct_ggx_unit_disc(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0)
-{
-       roughness = clamp(roughness, 0.0004, 0.999); /* Fix low roughness artifacts. */
-
-       vec2 uv = lut_coords(dot(N, V), sqrt(roughness));
-       vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb;
-       vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba;
-       mat3 ltc_mat = ltc_matrix(ltc_lut);
-
-       vec3 Px = ld.l_right * ld.l_radius;
-       vec3 Py = ld.l_up * ld.l_radius;
-
-       vec3 points[3];
-       points[0] = -ld.l_forward - Px - Py;
-       points[1] = -ld.l_forward + Px - Py;
-       points[2] = -ld.l_forward + Px + Py;
-
-       float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points);
-       bsdf *= brdf_lut.b; /* Bsdf intensity */
-
-       vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
-
-       return spec;
-}
-#endif
index 0e6f976187aec433605b3b2a74f88d72c0610b44..ec5f6f4472f361d3f7f0679a95c46d5e2b7bd135 100644 (file)
@@ -249,55 +249,70 @@ float light_visibility(LightData ld, vec3 W,
        return vis;
 }
 
+#ifdef USE_LTC
 float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
 {
-#ifdef USE_LTC
-       if (ld.l_type == SUN) {
-               return direct_diffuse_unit_disc(ld, N, V);
-       }
-       else if (ld.l_type == AREA_RECT) {
-               return direct_diffuse_rectangle(ld, N, V, l_vector);
+       if (ld.l_type == AREA_RECT) {
+               vec3 corners[4];
+               corners[0] = normalize((l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up *  ld.l_sizey);
+               corners[1] = normalize((l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey);
+               corners[2] = normalize((l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up * -ld.l_sizey);
+               corners[3] = normalize((l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up *  ld.l_sizey);
+
+               return ltc_evaluate_quad(corners, N);
        }
        else if (ld.l_type == AREA_ELLIPSE) {
-               return direct_diffuse_ellipse(ld, N, V, l_vector);
-       }
-       else {
-               return direct_diffuse_sphere(ld, N, l_vector);
-       }
-#else
-       if (ld.l_type == SUN) {
-               return direct_diffuse_sun(ld, N);
+               vec3 points[3];
+               points[0] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey;
+               points[1] = (l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up * -ld.l_sizey;
+               points[2] = (l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up *  ld.l_sizey;
+
+               return ltc_evaluate_disk(N, V, mat3(1.0), points);
        }
        else {
-               return direct_diffuse_point(N, l_vector);
+               float radius = ld.l_radius;
+               radius /= (ld.l_type == SUN) ? 1.0 : l_vector.w;
+               vec3 L = (ld.l_type == SUN) ? -ld.l_forward : (l_vector.xyz / l_vector.w);
+
+               return ltc_evaluate_disk_simple(radius, dot(N, L));
        }
-#endif
 }
 
-vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0)
+float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector)
 {
-#ifdef USE_LTC
-       if (ld.l_type == SUN) {
-               return direct_ggx_unit_disc(ld, N, V, roughness, f0);
-       }
-       else if (ld.l_type == AREA_RECT) {
-               return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0);
-       }
-       else if (ld.l_type == AREA_ELLIPSE) {
-               return direct_ggx_ellipse(ld, N, V, l_vector, roughness, f0);
-       }
-       else {
-               return direct_ggx_sphere(ld, N, V, l_vector, roughness, f0);
-       }
-#else
-       if (ld.l_type == SUN) {
-               return direct_ggx_sun(ld, N, V, roughness, f0);
+       if (ld.l_type == AREA_RECT) {
+               vec3 corners[4];
+               corners[0] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up *  ld.l_sizey;
+               corners[1] = (l_vector.xyz + ld.l_right * -ld.l_sizex) + ld.l_up * -ld.l_sizey;
+               corners[2] = (l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up * -ld.l_sizey;
+               corners[3] = (l_vector.xyz + ld.l_right *  ld.l_sizex) + ld.l_up *  ld.l_sizey;
+
+               ltc_transform_quad(N, V, ltc_matrix(ltc_mat), corners);
+
+               return ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0));
        }
        else {
-               return direct_ggx_point(N, V, l_vector, roughness, f0);
+               bool is_ellipse = (ld.l_type == AREA_ELLIPSE);
+               float radius_x = is_ellipse ? ld.l_sizex : ld.l_radius;
+               float radius_y = is_ellipse ? ld.l_sizey : ld.l_radius;
+
+               vec3 L = (ld.l_type == SUN) ? -ld.l_forward : l_vector.xyz;
+               vec3 Px = ld.l_right;
+               vec3 Py = ld.l_up;
+
+               if (ld.l_type == SPOT || ld.l_type == POINT) {
+                       make_orthonormal_basis(l_vector.xyz / l_vector.w, Px, Py);
+               }
+
+               vec3 points[3];
+               points[0] = (L + Px * -radius_x) + Py * -radius_y;
+               points[1] = (L + Px *  radius_x) + Py * -radius_y;
+               points[2] = (L + Px *  radius_x) + Py *  radius_y;
+
+               return ltc_evaluate_disk(N, V, ltc_matrix(ltc_mat), points);
        }
-#endif
 }
+#endif
 
 #define MAX_SSS_SAMPLES 65
 #define SSS_LUT_SIZE 64.0
index 4e65834e528ea0b9848c12328d6152de79006e97..ac1dd071a29e15f2b9267ef7200fadde019f8261 100644 (file)
@@ -182,6 +182,17 @@ void CLOSURE_NAME(
        /* -------------------- SCENE LAMPS LIGHTING ---------------------- */
        /* ---------------------------------------------------------------- */
 
+#ifdef CLOSURE_GLOSSY
+       vec2 lut_uv = lut_coords(dot(N, V), roughness);
+       vec4 ltc_mat = texture(utilTex, vec3(lut_uv, 0.0)).rgba;
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+       vec2 lut_uv_clear = lut_coords(dot(C_N, V), C_roughness);
+       vec4 ltc_mat_clear = texture(utilTex, vec3(lut_uv_clear, 0.0)).rgba;
+       vec3 out_spec_clear = vec3(0.0);
+#endif
+
        for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) {
                LightData ld = lights_data[i];
 
@@ -200,14 +211,24 @@ void CLOSURE_NAME(
        #endif
 
        #ifdef CLOSURE_GLOSSY
-               out_spec += l_color_vis * light_specular(ld, N, V, l_vector, roughnessSquared, f0) * ld.l_spec;
+               out_spec += l_color_vis * light_specular(ld, ltc_mat, N, V, l_vector) * ld.l_spec;
        #endif
 
        #ifdef CLOSURE_CLEARCOAT
-               out_spec += l_color_vis * light_specular(ld, C_N, V, l_vector, C_roughnessSquared, f0) * C_intensity * ld.l_spec;
+               out_spec_clear += l_color_vis * light_specular(ld, ltc_mat_clear, C_N, V, l_vector) * C_intensity * ld.l_spec;
        #endif
        }
 
+#ifdef CLOSURE_GLOSSY
+       vec3 brdf_lut_lamps = texture(utilTex, vec3(lut_uv, 1.0)).rgb;
+       out_spec *= F_area(f0, brdf_lut_lamps.xy) * brdf_lut_lamps.z;
+#endif
+
+#ifdef CLOSURE_CLEARCOAT
+       vec3 brdf_lut_lamps_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).rgb;
+       out_spec_clear *= F_area(f0, brdf_lut_lamps_clear.xy) * brdf_lut_lamps_clear.z;
+       out_spec += out_spec_clear;
+#endif
 
        /* ---------------------------------------------------------------- */
        /* ---------------- SPECULAR ENVIRONMENT LIGHTING ----------------- */