Eevee: Improve compilation time (reduce branching).

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.
This commit is contained in:
Clément Foucault 2018-06-09 20:48:19 +02:00
parent 45a5ddb57b
commit 147eef9741
6 changed files with 73 additions and 229 deletions

View 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)

View 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);

View 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,

View File

@ -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

View 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);
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_sphere(ld, 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));
}
#else
if (ld.l_type == SUN) {
return direct_diffuse_sun(ld, N);
}
else {
return direct_diffuse_point(N, l_vector);
}
#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);
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_sphere(ld, 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);
}
#else
if (ld.l_type == SUN) {
return direct_ggx_sun(ld, N, V, roughness, f0);
}
else {
return direct_ggx_point(N, V, l_vector, roughness, f0);
}
#endif
}
#endif
#define MAX_SSS_SAMPLES 65
#define SSS_LUT_SIZE 64.0

View 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 ----------------- */