Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-05-29 13:32:05 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-05-29 16:52:27 +0300
commitdbed33479a9f55e42b70ea03fe796b10337a21c7 (patch)
tree63657d2bf0c63f7fd56a658db074386af616dd5b /source/blender
parent932399612bdd444cdf7438ef04427864564b41b4 (diff)
Eevee: Remove non-ltc area light code + optimisation.
Reduce size ShadingData struct leads to some improvement even with more computation.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl71
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl111
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl96
-rw-r--r--source/blender/draw/engines/eevee/shaders/ltc_lib.glsl9
4 files changed, 81 insertions, 206 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index feaddd3c0e3..a9be6ca5478 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -66,21 +66,11 @@ struct ShadowCascadeData {
vec4 bias;
};
-struct AreaData {
- vec3 corner[4];
- float solid_angle;
-};
-
struct ShadingData {
vec3 V; /* View vector */
vec3 N; /* World Normal of the fragment */
vec3 W; /* World Position of the fragment */
- vec3 R; /* Reflection vector */
- vec3 L; /* Current Light vector (normalized) */
- vec3 spec_dominant_dir; /* dominant direction of the specular rays */
vec3 l_vector; /* Current Light vector */
- float l_distance; /* distance(l_position, W) */
- AreaData area_data; /* If current light is an area light */
};
/* ------- Convenience functions --------- */
@@ -213,21 +203,6 @@ vec3 spherical_harmonics_L2(vec3 N, vec3 shcoefs[9])
return sh;
}
-float rectangle_solid_angle(AreaData ad)
-{
- vec3 n0 = normalize(cross(ad.corner[0], ad.corner[1]));
- vec3 n1 = normalize(cross(ad.corner[1], ad.corner[2]));
- vec3 n2 = normalize(cross(ad.corner[2], ad.corner[3]));
- vec3 n3 = normalize(cross(ad.corner[3], ad.corner[0]));
-
- float g0 = acos(dot(-n0, n1));
- float g1 = acos(dot(-n1, n2));
- float g2 = acos(dot(-n2, n3));
- float g3 = acos(dot(-n3, n0));
-
- return max(0.0, (g0 + g1 + g2 + g3 - 2.0 * M_PI));
-}
-
vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness)
{
float smoothness = 1.0 - roughness;
@@ -235,52 +210,6 @@ vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness)
return normalize(mix(N, R, fac));
}
-/* From UE4 paper */
-vec3 mrp_sphere(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out float energy_conservation)
-{
- roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */
-
- /* energy preservation */
- float sphere_angle = saturate(ld.l_radius / sd.l_distance);
- energy_conservation = pow(roughness / saturate(roughness + 0.5 * sphere_angle), 2.0);
-
- /* sphere light */
- float inter_dist = dot(sd.l_vector, dir);
- vec3 closest_point_on_ray = inter_dist * dir;
- vec3 center_to_ray = closest_point_on_ray - sd.l_vector;
-
- /* closest point on sphere */
- vec3 closest_point_on_sphere = sd.l_vector + center_to_ray * saturate(ld.l_radius * inverse_distance(center_to_ray));
-
- return normalize(closest_point_on_sphere);
-}
-
-vec3 mrp_area(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out float energy_conservation)
-{
- roughness = max(3e-3, roughness); /* Artifacts appear with roughness below this threshold */
-
- /* FIXME : This needs to be fixed */
- energy_conservation = pow(roughness / saturate(roughness + 0.5 * sd.area_data.solid_angle), 2.0);
-
- vec3 refproj = line_plane_intersect(sd.W, dir, ld.l_position, ld.l_forward);
-
- /* Project the point onto the light plane */
- vec3 refdir = refproj - ld.l_position;
- vec2 mrp = vec2(dot(refdir, ld.l_right), dot(refdir, ld.l_up));
-
- /* clamp to light shape bounds */
- vec2 area_half_size = vec2(ld.l_sizex, ld.l_sizey);
- mrp = clamp(mrp, -area_half_size, area_half_size);
-
- /* go back in world space */
- vec3 closest_point_on_rectangle = sd.l_vector + mrp.x * ld.l_right + mrp.y * ld.l_up;
-
- float len = length(closest_point_on_rectangle);
- energy_conservation /= len * len;
-
- return closest_point_on_rectangle / len;
-}
-
/* Fresnel */
vec3 F_schlick(vec3 f0, float cos_theta)
{
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
index 9097f4aca5a..07fff8ac2d2 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl
@@ -13,8 +13,10 @@
float direct_diffuse_point(LightData ld, ShadingData sd)
{
- float bsdf = max(0.0, dot(sd.N, sd.L));
- bsdf /= sd.l_distance * sd.l_distance;
+ float dist = length(sd.l_vector);
+ vec3 L = sd.l_vector / dist;
+ float bsdf = max(0.0, dot(sd.N, L));
+ bsdf /= dist * dist;
return bsdf;
}
@@ -23,9 +25,11 @@ float direct_diffuse_point(LightData ld, ShadingData sd)
* http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
float direct_diffuse_sphere(LightData ld, ShadingData sd)
{
+ float dist = length(sd.l_vector);
+ vec3 L = sd.l_vector / dist;
float radius = max(ld.l_sizex, 0.0001);
- float costheta = clamp(dot(sd.N, sd.L), -0.999, 0.999);
- float h = min(ld.l_radius / sd.l_distance , 0.9999);
+ float costheta = clamp(dot(sd.N, L), -0.999, 0.999);
+ float h = min(ld.l_radius / dist , 0.9999);
float h2 = h*h;
float costheta2 = costheta * costheta;
float bsdf;
@@ -51,26 +55,21 @@ float direct_diffuse_sphere(LightData ld, ShadingData sd)
* http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */
float direct_diffuse_rectangle(LightData ld, ShadingData sd)
{
-#ifdef USE_LTC
- float bsdf = ltc_evaluate(sd.N, sd.V, mat3(1.0), sd.area_data.corner);
+ vec3 corners[4];
+ corners[0] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
+ corners[1] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[2] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[3] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+
+ float bsdf = ltc_evaluate(sd.N, sd.V, mat3(1.0), corners);
bsdf *= M_1_2PI;
-#else
- float bsdf = sd.area_data.solid_angle * 0.2 * (
- max(0.0, dot(normalize(sd.area_data.corner[0]), sd.N)) +
- max(0.0, dot(normalize(sd.area_data.corner[1]), sd.N)) +
- max(0.0, dot(normalize(sd.area_data.corner[2]), sd.N)) +
- max(0.0, dot(normalize(sd.area_data.corner[3]), sd.N)) +
- max(0.0, dot(sd.L, sd.N))
- );
- bsdf *= M_1_PI;
-#endif
return bsdf;
}
/* infinitly far away point source, no decay */
float direct_diffuse_sun(LightData ld, ShadingData sd)
{
- float bsdf = max(0.0, dot(sd.N, sd.L));
+ float bsdf = max(0.0, dot(sd.N, -ld.l_forward));
bsdf *= M_1_PI; /* Normalize */
return bsdf;
}
@@ -85,25 +84,29 @@ float direct_diffuse_unit_disc(vec3 N, vec3 L)
/* ----------- GGx ------------ */
vec3 direct_ggx_point(ShadingData sd, float roughness, vec3 f0)
{
- float bsdf = bsdf_ggx(sd.N, sd.L, sd.V, roughness);
- bsdf /= sd.l_distance * sd.l_distance;
+ float dist = length(sd.l_vector);
+ vec3 L = sd.l_vector / dist;
+ float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
+ bsdf /= dist * dist;
/* Fresnel */
- float VH = max(dot(sd.V, normalize(sd.V + sd.L)), 0.0);
+ float VH = max(dot(sd.V, normalize(sd.V + L)), 0.0);
return F_schlick(f0, VH) * bsdf;
}
vec3 direct_ggx_sphere(LightData ld, ShadingData sd, float roughness, vec3 f0)
{
-#ifdef USE_LTC
- float NV = max(dot(sd.N, sd.V), 1e-8);
- vec3 P = line_aligned_plane_intersect(vec3(0.0), sd.spec_dominant_dir, sd.l_vector);
+ vec3 L = normalize(sd.l_vector);
+ vec3 spec_dir = get_specular_dominant_dir(sd.N, reflect(-sd.V, sd.N), roughness);
+ vec3 P = line_aligned_plane_intersect(vec3(0.0), spec_dir, sd.l_vector);
vec3 Px = normalize(P - sd.l_vector) * ld.l_radius;
- vec3 Py = cross(Px, sd.L);
+ vec3 Py = cross(Px, L);
- vec2 uv = lut_coords(NV, sqrt(roughness));
- mat3 ltcmat = ltc_matrix(uv);
+ vec2 uv = lut_coords(dot(sd.N, sd.V), sqrt(roughness));
+ vec3 brdf_lut = texture(brdfLut, uv).rgb;
+ vec4 ltc_lut = texture(ltcMat, uv).rgba;
+ mat3 ltc_mat = ltc_matrix(ltc_lut);
// #define HIGHEST_QUALITY
#ifdef HIGHEST_QUALITY
@@ -120,64 +123,44 @@ vec3 direct_ggx_sphere(LightData ld, ShadingData sd, float roughness, vec3 f0)
points[5] = sd.l_vector + Pxy2;
points[6] = sd.l_vector + Py;
points[7] = sd.l_vector + Pxy1;
- float bsdf = ltc_evaluate_circle(sd.N, sd.V, ltcmat, points);
+ float bsdf = ltc_evaluate_circle(sd.N, sd.V, ltc_mat, points);
#else
vec3 points[4];
points[0] = sd.l_vector + Px;
points[1] = sd.l_vector - Py;
points[2] = sd.l_vector - Px;
points[3] = sd.l_vector + Py;
- float bsdf = ltc_evaluate(sd.N, sd.V, ltcmat, points);
+ float bsdf = ltc_evaluate(sd.N, sd.V, ltc_mat, points);
/* sqrt(pi/2) difference between square and disk area */
bsdf *= 1.25331413731;
#endif
- vec3 lut = texture(brdfLut, uv).rgb;
- bsdf *= lut.b; /* Bsdf intensity */
- bsdf *= M_1_2PI * M_1_PI;
- vec3 spec = F_area(f0, lut.xy) * bsdf;
-#else
- float energy_conservation;
- vec3 L = mrp_sphere(ld, sd, sd.spec_dominant_dir, roughness, energy_conservation);
- float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
+ bsdf *= brdf_lut.b; /* Bsdf intensity */
+ bsdf *= M_1_2PI * M_1_PI;
- bsdf *= energy_conservation / (sd.l_distance * sd.l_distance);
- bsdf *= max(ld.l_radius * ld.l_radius, 1e-16); /* radius is already inside energy_conservation */
+ vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
- /* Fresnel */
- float VH = max(dot(sd.V, normalize(sd.V + sd.L)), 0.0);
- vec3 spec = F_schlick(f0, VH) * bsdf;
-#endif
return spec;
}
vec3 direct_ggx_rectangle(LightData ld, ShadingData sd, float roughness, vec3 f0)
{
-#ifdef USE_LTC
- float NV = max(dot(sd.N, sd.V), 1e-8);
- vec2 uv = lut_coords(NV, sqrt(roughness));
- mat3 ltcmat = ltc_matrix(uv);
-
- float bsdf = ltc_evaluate(sd.N, sd.V, ltcmat, sd.area_data.corner);
- vec3 lut = texture(brdfLut, uv).rgb;
- bsdf *= lut.b; /* Bsdf intensity */
+ vec3 corners[4];
+ corners[0] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
+ corners[1] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[2] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
+ corners[3] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
+
+ vec2 uv = lut_coords(dot(sd.N, sd.V), sqrt(roughness));
+ vec3 brdf_lut = texture(brdfLut, uv).rgb;
+ vec4 ltc_lut = texture(ltcMat, uv).rgba;
+ mat3 ltc_mat = ltc_matrix(ltc_lut);
+ float bsdf = ltc_evaluate(sd.N, sd.V, ltc_mat, corners);
+ bsdf *= brdf_lut.b; /* Bsdf intensity */
bsdf *= M_1_2PI;
- vec3 spec = F_area(f0, lut.xy) * bsdf;
-#else
- float energy_conservation;
- vec3 L = mrp_area(ld, sd, sd.spec_dominant_dir, roughness, energy_conservation);
- float bsdf = bsdf_ggx(sd.N, L, sd.V, roughness);
+ vec3 spec = F_area(f0, brdf_lut.xy) * bsdf;
- bsdf *= energy_conservation;
- /* fade mrp artifacts */
- bsdf *= max(0.0, dot(-sd.spec_dominant_dir, ld.l_forward));
- bsdf *= max(0.0, -dot(L, ld.l_forward));
-
- /* Fresnel */
- float VH = max(dot(sd.V, normalize(sd.V + sd.L)), 0.0);
- vec3 spec = F_schlick(f0, VH) * bsdf;
-#endif
return spec;
}
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index ecfc670c0d6..bff7c05537a 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -42,36 +42,38 @@ in vec3 viewNormal;
#define HEMI 3.0
#define AREA 4.0
-vec3 light_diffuse(LightData ld, ShadingData sd, vec3 albedo)
+void light_shade(
+ LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0,
+ out vec3 diffuse, out vec3 specular)
{
+#ifdef USE_LTC
if (ld.l_type == SUN) {
- return direct_diffuse_sun(ld, sd) * albedo;
+ diffuse = direct_diffuse_sun(ld, sd) * albedo;
+ /* TODO disk area light */
+ specular = direct_ggx_point(sd, roughness, f0);
}
else if (ld.l_type == AREA) {
- return direct_diffuse_rectangle(ld, sd) * albedo;
+ diffuse = direct_diffuse_rectangle(ld, sd) * albedo;
+ specular = direct_ggx_rectangle(ld, sd, roughness, f0);
}
else {
- return direct_diffuse_sphere(ld, sd) * albedo;
+ diffuse = direct_diffuse_sphere(ld, sd) * albedo;
+ specular = direct_ggx_sphere(ld, sd, roughness, f0);
}
-}
-
-vec3 light_specular(LightData ld, ShadingData sd, float roughness, vec3 f0)
-{
+#else
if (ld.l_type == SUN) {
- return direct_ggx_point(sd, roughness, f0);
- }
- else if (ld.l_type == AREA) {
- return direct_ggx_rectangle(ld, sd, roughness, f0);
+ diffuse = direct_diffuse_sun(ld, sd) * albedo;
}
else {
- // return direct_ggx_point(sd, roughness, f0);
- return direct_ggx_sphere(ld, sd, roughness, f0);
+ diffuse = direct_diffuse_point(ld, sd) * albedo;
}
+ specular = direct_ggx_point(sd, roughness, f0);
+#endif
}
-float light_visibility(LightData ld, ShadingData sd)
+void light_visibility(LightData ld, ShadingData sd, out float vis)
{
- float vis = 1.0;
+ vis = 1.0;
if (ld.l_type == SPOT) {
float z = dot(ld.l_forward, sd.l_vector);
@@ -84,10 +86,10 @@ float light_visibility(LightData ld, ShadingData sd)
float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
vis *= spotmask;
- vis *= step(0.0, -dot(sd.L, ld.l_forward));
+ vis *= step(0.0, -dot(sd.l_vector, ld.l_forward));
}
else if (ld.l_type == AREA) {
- vis *= step(0.0, -dot(sd.L, ld.l_forward));
+ vis *= step(0.0, -dot(sd.l_vector, ld.l_forward));
}
/* shadowing */
@@ -157,41 +159,6 @@ float light_visibility(LightData ld, ShadingData sd)
vis *= esm_test;
}
-
- return vis;
-}
-
-vec3 light_fresnel(LightData ld, ShadingData sd, vec3 f0)
-{
- vec3 H = normalize(sd.L + sd.V);
- float NH = max(dot(sd.N, H), 1e-8);
-
- return F_schlick(f0, NH);
-}
-
-/* Calculation common to all bsdfs */
-float light_common(inout LightData ld, inout ShadingData sd)
-{
- float vis = 1.0;
-
- if (ld.l_type == SUN) {
- sd.L = -ld.l_forward;
- }
- else {
- sd.L = sd.l_vector / sd.l_distance;
- }
-
- if (ld.l_type == AREA) {
- sd.area_data.corner[0] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey;
- sd.area_data.corner[1] = sd.l_vector + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey;
- sd.area_data.corner[2] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey;
- sd.area_data.corner[3] = sd.l_vector + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey;
-#ifndef USE_LTC
- sd.area_data.solid_angle = rectangle_solid_angle(sd.area_data);
-#endif
- }
-
- return vis;
}
vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, float ao)
@@ -204,8 +171,6 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness,
? normalize(cameraPos - worldPosition)
: normalize(eye);
sd.W = worldPosition;
- sd.R = reflect(-sd.V, sd.N);
- sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughnessSquared);
vec3 radiance = vec3(0.0);
vec3 indirect_radiance = vec3(0.0);
@@ -213,25 +178,24 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness,
/* Analitic Lights */
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
LightData ld = lights_data[i];
+ vec3 diff, spec;
+ float vis;
sd.l_vector = ld.l_position - worldPosition;
- sd.l_distance = length(sd.l_vector);
- light_common(ld, sd);
-
- float vis = light_visibility(ld, sd);
- vec3 spec = light_specular(ld, sd, roughnessSquared, f0);
- vec3 diff = light_diffuse(ld, sd, albedo);
+ light_visibility(ld, sd, vis);
+ light_shade(ld, sd, albedo, roughnessSquared, f0, diff, spec);
radiance += vis * (diff + spec) * ld.l_color;
}
- /* Envmaps */
- vec2 uv = lut_coords(dot(sd.N, sd.V), sqrt(roughness));
- vec2 brdf_lut = texture(brdfLut, uv).rg;
- vec3 Li = textureLod(probeFiltered, sd.spec_dominant_dir, roughness * lodMax).rgb;
- indirect_radiance += Li * F_ibl(f0, brdf_lut);
+ vec3 spec_dir = get_specular_dominant_dir(sd.N, reflect(-sd.V, sd.N), roughnessSquared);
+ /* Envmaps */
+ vec2 uv = lut_coords(dot(sd.N, sd.V), roughness);
+ vec3 brdf_lut = texture(brdfLut, uv).rgb;
+ vec3 Li = textureLod(probeFiltered, spec_dir, roughness * lodMax).rgb;
+ indirect_radiance += Li * F_ibl(f0, brdf_lut.rg);
indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
return radiance + indirect_radiance * ao;
diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
index 5ea13cab271..4b02e8c222f 100644
--- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl
@@ -145,14 +145,13 @@ int clip_quad_to_horizon(inout vec3 L[5])
return n;
}
-mat3 ltc_matrix(vec2 coord)
+mat3 ltc_matrix(vec4 lut)
{
/* load inverse matrix */
- vec4 t = texture(ltcMat, coord);
mat3 Minv = mat3(
- vec3( 1, 0, t.y),
- vec3( 0, t.z, 0),
- vec3(t.w, 0, t.x)
+ vec3( 1, 0, lut.y),
+ vec3( 0, lut.z, 0),
+ vec3(lut.w, 0, lut.x)
);
return Minv;