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:
authorCampbell Barton <ideasman42@gmail.com>2017-10-09 12:49:27 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-10-09 12:49:27 +0300
commita5b4b0f21c1ae8c96e4fea9abdcfac2fab1cf300 (patch)
tree0658d8bdfb8ec03652aa04f82ee8a4d243ec6370 /source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
parentd68f698cf0321477c0734474150eb4bc43c4e85f (diff)
parentabcda06934aba054de8540b66b13c2bbc5f8f515 (diff)
Merge branch '28' into custom-manipulatorscustom-manipulators
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/lamps_lib.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl301
1 files changed, 301 insertions, 0 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
new file mode 100644
index 00000000000..c879e9c37f3
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl
@@ -0,0 +1,301 @@
+
+uniform sampler2DArray shadowTexture;
+
+layout(std140) uniform shadow_block {
+ ShadowData shadows_data[MAX_SHADOW];
+ ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE];
+ ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE];
+};
+
+layout(std140) uniform light_block {
+ LightData lights_data[MAX_LIGHT];
+};
+
+/* type */
+#define POINT 0.0
+#define SUN 1.0
+#define SPOT 2.0
+#define HEMI 3.0
+#define AREA 4.0
+
+/* ----------------------------------------------------------- */
+/* ----------------------- Shadow tests ---------------------- */
+/* ----------------------------------------------------------- */
+
+float shadow_test_esm(float z, float dist, float exponent)
+{
+ return saturate(exp(exponent * (z - dist)));
+}
+
+float shadow_test_pcf(float z, float dist)
+{
+ return step(0, z - dist);
+}
+
+float shadow_test_vsm(vec2 moments, float dist, float bias, float bleed_bias)
+{
+ float p = 0.0;
+
+ if (dist <= moments.x)
+ p = 1.0;
+
+ float variance = moments.y - (moments.x * moments.x);
+ variance = max(variance, bias / 10.0);
+
+ float d = moments.x - dist;
+ float p_max = variance / (variance + d * d);
+
+ /* Now reduce light-bleeding by removing the [0, x] tail and linearly rescaling (x, 1] */
+ p_max = clamp((p_max - bleed_bias) / (1.0 - bleed_bias), 0.0, 1.0);
+
+ return max(p, p_max);
+}
+
+
+/* ----------------------------------------------------------- */
+/* ----------------------- Shadow types ---------------------- */
+/* ----------------------------------------------------------- */
+
+float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W)
+{
+ vec3 cubevec = W - scd.position.xyz;
+ float dist = length(cubevec);
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ /* XXX : we check radial distance against a cubeface distance.
+ * We loose quite a bit of valid area. */
+ if (dist > sd.sh_far)
+ return 1.0;
+
+ cubevec /= dist;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture_octahedron(shadowTexture, vec4(cubevec, texid)).rg;
+#else
+ float z = texture_octahedron(shadowTexture, vec4(cubevec, texid)).r;
+#endif
+
+#if defined(SHADOW_VSM)
+ return shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
+#elif defined(SHADOW_ESM)
+ return shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
+#else
+ return shadow_test_pcf(z, dist - sd.sh_bias);
+#endif
+}
+
+float evaluate_cascade(ShadowData sd, mat4 shadowmat, vec3 W, float range, float texid)
+{
+ vec4 shpos = shadowmat * vec4(W, 1.0);
+ float dist = shpos.z * range;
+
+#if defined(SHADOW_VSM)
+ vec2 moments = texture(shadowTexture, vec3(shpos.xy, texid)).rg;
+#else
+ float z = texture(shadowTexture, vec3(shpos.xy, texid)).r;
+#endif
+
+ float vis;
+#if defined(SHADOW_VSM)
+ vis = shadow_test_vsm(moments, dist, sd.sh_bias, sd.sh_bleed);
+#elif defined(SHADOW_ESM)
+ vis = shadow_test_esm(z, dist - sd.sh_bias, sd.sh_exp);
+#else
+ vis = shadow_test_pcf(z, dist - sd.sh_bias);
+#endif
+
+ /* If fragment is out of shadowmap range, do not occlude */
+ if (shpos.z < 1.0 && shpos.z > 0.0) {
+ return vis;
+ }
+ else {
+ return 1.0;
+ }
+}
+
+float shadow_cascade(ShadowData sd, ShadowCascadeData scd, float texid, vec3 W)
+{
+ vec4 view_z = vec4(dot(W - cameraPos, cameraForward));
+ vec4 weights = smoothstep(scd.split_end_distances, scd.split_start_distances.yzwx, view_z);
+ weights.yzw -= weights.xyz;
+
+ vec4 vis = vec4(1.0);
+ float range = abs(sd.sh_far - sd.sh_near); /* Same factor as in get_cascade_world_distance(). */
+
+ /* Branching using (weights > 0.0) is reaally slooow on intel so avoid it for now. */
+ vis.x = evaluate_cascade(sd, scd.shadowmat[0], W, range, texid + 0);
+ vis.y = evaluate_cascade(sd, scd.shadowmat[1], W, range, texid + 1);
+ vis.z = evaluate_cascade(sd, scd.shadowmat[2], W, range, texid + 2);
+ vis.w = evaluate_cascade(sd, scd.shadowmat[3], W, range, texid + 3);
+
+ float weight_sum = dot(vec4(1.0), weights);
+ if (weight_sum > 0.9999) {
+ float vis_sum = dot(vec4(1.0), vis * weights);
+ return vis_sum / weight_sum;
+ }
+ else {
+ float vis_sum = dot(vec4(1.0), vis * step(0.001, weights));
+ return mix(1.0, vis_sum, weight_sum);
+ }
+}
+
+/* ----------------------------------------------------------- */
+/* --------------------- Light Functions --------------------- */
+/* ----------------------------------------------------------- */
+#define MAX_MULTI_SHADOW 4
+
+float light_visibility(LightData ld, vec3 W,
+#ifndef VOLUMETRICS
+ vec3 viewPosition,
+ vec3 viewNormal,
+#endif
+ vec4 l_vector)
+{
+ float vis = 1.0;
+
+ if (ld.l_type == SPOT) {
+ float z = dot(ld.l_forward, l_vector.xyz);
+ vec3 lL = l_vector.xyz / z;
+ float x = dot(ld.l_right, lL) / ld.l_sizex;
+ float y = dot(ld.l_up, lL) / ld.l_sizey;
+
+ float ellipse = 1.0 / sqrt(1.0 + x * x + y * y);
+
+ float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend);
+
+ vis *= spotmask;
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+ else if (ld.l_type == AREA) {
+ vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward));
+ }
+
+#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW)
+ /* shadowing */
+ if (ld.l_shadowid >= 0.0) {
+ ShadowData data = shadows_data[int(ld.l_shadowid)];
+
+ if (ld.l_type == SUN) {
+ /* TODO : MSM */
+ // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
+ vis *= shadow_cascade(
+ data, shadows_cascade_data[int(data.sh_data_start)],
+ data.sh_tex_start, W);
+ // }
+ }
+ else {
+ /* TODO : MSM */
+ // for (int i = 0; i < MAX_MULTI_SHADOW; ++i) {
+ vis *= shadow_cubemap(
+ data, shadows_cube_data[int(data.sh_data_start)],
+ data.sh_tex_start, W);
+ // }
+ }
+
+#ifndef VOLUMETRICS
+ /* Only compute if not already in shadow. */
+ if ((vis > 0.001) && (data.sh_contact_dist > 0.0)) {
+ vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0);
+ float trace_distance = (ld.l_type != SUN) ? min(data.sh_contact_dist, l_vector.w) : data.sh_contact_dist;
+
+ vec3 T, B;
+ make_orthonormal_basis(L.xyz / L.w, T, B);
+
+ vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ rand.yz *= rand.x * data.sh_contact_spread;
+
+ /* We use the full l_vector.xyz so that the spread is minimize
+ * if the shading point is further away from the light source */
+ vec3 ray_dir = L.xyz + T * rand.y + B * rand.z;
+ ray_dir = transform_direction(ViewMatrix, ray_dir);
+ ray_dir = normalize(ray_dir);
+ vec3 ray_origin = viewPosition + viewNormal * data.sh_contact_offset;
+ vec3 hit_pos = raycast(-1, ray_origin, ray_dir * trace_distance, data.sh_contact_thickness, rand.x, 0.75, 0.01);
+
+ if (hit_pos.z > 0.0) {
+ hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z);
+ float hit_dist = distance(viewPosition, hit_pos);
+ float dist_ratio = hit_dist / trace_distance;
+ return mix(0.0, vis, dist_ratio * dist_ratio * dist_ratio);
+ }
+ }
+#endif
+ }
+#endif
+
+ return vis;
+}
+
+float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector)
+{
+#ifdef USE_LTC
+ if (ld.l_type == SUN) {
+ /* TODO disk area light */
+ return direct_diffuse_sun(ld, N);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_diffuse_rectangle(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, V);
+ }
+ 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)
+{
+#ifdef USE_LTC
+ if (ld.l_type == SUN) {
+ /* TODO disk area light */
+ return direct_ggx_sun(ld, N, V, roughness, f0);
+ }
+ else if (ld.l_type == AREA) {
+ return direct_ggx_rectangle(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);
+ }
+ else {
+ return direct_ggx_point(N, V, l_vector, roughness, f0);
+ }
+#endif
+}
+
+#ifdef HAIR_SHADER
+void light_hair_common(
+ LightData ld, vec3 N, vec3 V, vec4 l_vector, vec3 norm_view,
+ out float occlu_trans, out float occlu,
+ out vec3 norm_lamp, out vec3 view_vec)
+{
+ const float transmission = 0.3; /* Uniform internal scattering factor */
+
+ vec3 lamp_vec;
+
+ if (ld.l_type == SUN || ld.l_type == AREA) {
+ lamp_vec = ld.l_forward;
+ }
+ else {
+ lamp_vec = -l_vector.xyz;
+ }
+
+ norm_lamp = cross(lamp_vec, N);
+ norm_lamp = normalize(cross(N, norm_lamp)); /* Normal facing lamp */
+
+ /* Rotate view vector onto the cross(tangent, light) plane */
+ view_vec = normalize(norm_lamp * dot(norm_view, V) + N * dot(N, V));
+
+ occlu = (dot(norm_view, norm_lamp) * 0.5 + 0.5);
+ occlu_trans = transmission + (occlu * (1.0 - transmission)); /* Includes transmission component */
+}
+#endif