From 168d3fd528c419b1f877362ef9ffecfc8c790a8a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 27 Feb 2019 12:34:56 +1100 Subject: Cleanup: file rename lamp -> light --- .../blender/draw/engines/eevee/eevee_materials.c | 6 +- source/blender/draw/engines/eevee/eevee_volumes.c | 4 +- .../draw/engines/eevee/shaders/lamps_lib.glsl | 451 --------------------- .../draw/engines/eevee/shaders/lights_lib.glsl | 451 +++++++++++++++++++++ 4 files changed, 456 insertions(+), 456 deletions(-) delete mode 100644 source/blender/draw/engines/eevee/shaders/lamps_lib.glsl create mode 100644 source/blender/draw/engines/eevee/shaders/lights_lib.glsl (limited to 'source/blender/draw/engines/eevee') diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index eec61ffd08c..5a808f2a01f 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -70,7 +70,7 @@ static struct { float noise_offsets[3]; } e_data = {NULL}; /* Engine data */ -extern char datatoc_lamps_lib_glsl[]; +extern char datatoc_lights_lib_glsl[]; extern char datatoc_lightprobe_lib_glsl[]; extern char datatoc_ambient_occlusion_lib_glsl[]; extern char datatoc_prepass_frag_glsl[]; @@ -553,7 +553,7 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_irradiance_lib_glsl, datatoc_lightprobe_lib_glsl, datatoc_ltc_lib_glsl, - datatoc_lamps_lib_glsl, + datatoc_lights_lib_glsl, /* Add one for each Closure */ datatoc_lit_surface_frag_glsl, datatoc_lit_surface_frag_glsl, @@ -576,7 +576,7 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, E datatoc_irradiance_lib_glsl, datatoc_lightprobe_lib_glsl, datatoc_ltc_lib_glsl, - datatoc_lamps_lib_glsl, + datatoc_lights_lib_glsl, datatoc_volumetric_lib_glsl, datatoc_volumetric_frag_glsl); diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 53c08c4d8f3..cf12863565f 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -66,7 +66,7 @@ extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_common_view_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_irradiance_lib_glsl[]; -extern char datatoc_lamps_lib_glsl[]; +extern char datatoc_lights_lib_glsl[]; extern char datatoc_volumetric_frag_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_vert_glsl[]; @@ -90,7 +90,7 @@ static void eevee_create_shader_volumes(void) datatoc_bsdf_common_lib_glsl, datatoc_octahedron_lib_glsl, datatoc_irradiance_lib_glsl, - datatoc_lamps_lib_glsl, + datatoc_lights_lib_glsl, datatoc_volumetric_lib_glsl); e_data.volumetric_clear_sh = DRW_shader_create_with_lib( diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl deleted file mode 100644 index e12d76596d3..00000000000 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ /dev/null @@ -1,451 +0,0 @@ - -uniform sampler2DArray shadowCubeTexture; -uniform sampler2DArray shadowCascadeTexture; - -#define LAMPS_LIB - -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 AREA_RECT 4.0 -/* Used to define the area light shape, doesn't directly correspond to a Blender light type. */ -#define AREA_ELLIPSE 100.0 - -#if defined(SHADOW_VSM) -#define ShadowSample vec2 -#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).rg -#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).rg -#elif defined(SHADOW_ESM) -#define ShadowSample float -#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r -#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r -#else -#define ShadowSample float -#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r -#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r -#endif - -#if defined(SHADOW_VSM) -#define get_depth_delta(dist, s) (dist - s.x) -#else -#define get_depth_delta(dist, s) (dist - s) -#endif - -/* ----------------------------------------------------------- */ -/* ----------------------- Shadow tests ---------------------- */ -/* ----------------------------------------------------------- */ - -#if defined(SHADOW_VSM) - -float shadow_test(ShadowSample moments, float dist, ShadowData sd) -{ - float p = 0.0; - - if (dist <= moments.x) { - p = 1.0; - } - - float variance = moments.y - (moments.x * moments.x); - variance = max(variance, sd.sh_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 - sd.sh_bleed) / (1.0 - sd.sh_bleed), 0.0, 1.0); - - return max(p, p_max); -} - -#elif defined(SHADOW_ESM) - -float shadow_test(ShadowSample z, float dist, ShadowData sd) -{ - return saturate(exp(sd.sh_exp * (z - dist + sd.sh_bias))); -} - -#else - -float shadow_test(ShadowSample z, float dist, ShadowData sd) -{ - return step(0, z - dist + sd.sh_bias); -} - -#endif - -/* ----------------------------------------------------------- */ -/* ----------------------- Shadow types ---------------------- */ -/* ----------------------------------------------------------- */ - -float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W) -{ - vec3 cubevec = W - scd.position.xyz; - float dist = length(cubevec); - - cubevec /= dist; - - ShadowSample s = sample_cube(cubevec, texid); - return shadow_test(s, dist, sd); -} - -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; - - ShadowSample s = sample_cascade(shpos.xy, texid); - float vis = shadow_test(s, dist, sd); - - /* 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, int scd_id, float texid, vec3 W) -{ - vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); - vec4 weights = smoothstep( - shadows_cascade_data[scd_id].split_end_distances, - shadows_cascade_data[scd_id].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. */ - /* TODO OPTI: Only do 2 samples and blend. */ - vis.x = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[0], W, range, texid + 0); - vis.y = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[1], W, range, texid + 1); - vis.z = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[2], W, range, texid + 2); - vis.w = evaluate_cascade(sd, shadows_cascade_data[scd_id].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 --------------------- */ -/* ----------------------------------------------------------- */ - -/* From Frostbite PBR Course - * Distance based attenuation - * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */ -float distance_attenuation(float dist_sqr, float inv_sqr_influence) -{ - float factor = dist_sqr * inv_sqr_influence; - float fac = saturate(1.0 - factor * factor); - return fac * fac; -} - -float spot_attenuation(LightData ld, vec3 l_vector) -{ - 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 = inversesqrt(1.0 + x * x + y * y); - float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); - return spotmask; -} - -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) { - vis *= spot_attenuation(ld, l_vector.xyz); - } - if (ld.l_type >= SPOT) { - vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); - } - if (ld.l_type != SUN) { - vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence); - } - -#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) - /* shadowing */ - if (ld.l_shadowid >= 0.0 && vis > 0.001) { - ShadowData data = shadows_data[int(ld.l_shadowid)]; - - if (ld.l_type == SUN) { - vis *= shadow_cascade( - data, int(data.sh_data_start), - data.sh_tex_start, W); - } - else { - 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 (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); - - vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); - rand.zw *= fast_sqrt(rand.y) * 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.z + B * rand.w; - ray_dir = transform_direction(ViewMatrix, ray_dir); - ray_dir = normalize(ray_dir); - - vec3 ray_ori = viewPosition; - - if (dot(viewNormal, ray_dir) <= 0.0) { - return vis; - } - - float bias = 0.5; /* Constant Bias */ - bias += 1.0 - abs(dot(viewNormal, ray_dir)); /* Angle dependent bias */ - bias *= gl_FrontFacing ? data.sh_contact_offset : -data.sh_contact_offset; - - vec3 nor_bias = viewNormal * bias; - ray_ori += nor_bias; - - ray_dir *= trace_distance; - ray_dir -= nor_bias; - - vec3 hit_pos = raycast(-1, ray_ori, ray_dir, data.sh_contact_thickness, rand.x, - 0.1, 0.001, false); - - 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 vis * saturate(dist_ratio * dist_ratio * dist_ratio); - } - } -#endif - } -#endif - - return vis; -} - -#ifdef USE_LTC -float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 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) { - 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 { - 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)); - } -} - -float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector) -{ - 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 { - 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 - -#define MAX_SSS_SAMPLES 65 -#define SSS_LUT_SIZE 64.0 -#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE)) -#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE)) - -#ifdef USE_TRANSLUCENCY -layout(std140) uniform sssProfile { - vec4 kernel[MAX_SSS_SAMPLES]; - vec4 radii_max_radius; - int sss_samples; -}; - -uniform sampler1D sssTexProfile; - -vec3 sss_profile(float s) { - s /= radii_max_radius.w; - return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb; -} -#endif - -vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) -{ -#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS) - return vec3(0.0); -#else - vec3 vis = vec3(1.0); - - if (ld.l_type == SPOT) { - vis *= spot_attenuation(ld, l_vector.xyz); - } - if (ld.l_type >= SPOT) { - vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); - } - if (ld.l_type != SUN) { - vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence); - } - - /* Only shadowed light can produce translucency */ - if (ld.l_shadowid >= 0.0 && vis.x > 0.001) { - ShadowData data = shadows_data[int(ld.l_shadowid)]; - float delta; - - vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0); - - vec3 T, B; - make_orthonormal_basis(L.xyz / L.w, T, B); - - vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); - rand.zw *= fast_sqrt(rand.y) * data.sh_blur; - - /* We use the full l_vector.xyz so that the spread is minimize - * if the shading point is further away from the light source */ - W = W + T * rand.z + B * rand.w; - - if (ld.l_type == SUN) { - int scd_id = int(data.sh_data_start); - vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); - - vec4 weights = step(shadows_cascade_data[scd_id].split_end_distances, view_z); - float id = abs(4.0 - dot(weights, weights)); - - if (id > 3.0) { - return vec3(0.0); - } - - float range = abs(data.sh_far - data.sh_near); /* Same factor as in get_cascade_world_distance(). */ - - vec4 shpos = shadows_cascade_data[scd_id].shadowmat[int(id)] * vec4(W, 1.0); - float dist = shpos.z * range; - - if (shpos.z > 1.0 || shpos.z < 0.0) { - return vec3(0.0); - } - - ShadowSample s = sample_cascade(shpos.xy, data.sh_tex_start + id); - delta = get_depth_delta(dist, s); - } - else { - vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz; - float dist = length(cubevec); - cubevec /= dist; - - ShadowSample s = sample_cube(cubevec, data.sh_tex_start); - delta = get_depth_delta(dist, s); - } - - /* XXX : Removing Area Power. */ - /* TODO : put this out of the shader. */ - float falloff; - if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { - vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); - if (ld.l_type == AREA_ELLIPSE) { - vis *= M_PI * 0.25; - } - vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ - vis /= (l_vector.w * l_vector.w); - falloff = dot(N, l_vector.xyz / l_vector.w); - } - else if (ld.l_type == SUN) { - vis /= 1.0f + (ld.l_radius * ld.l_radius * 0.5f); - vis *= ld.l_radius * ld.l_radius * M_PI; /* Removing area light power*/ - vis *= M_2PI * 0.78; /* Matching cycles with point light. */ - vis *= 0.082; /* XXX ad hoc, empirical */ - falloff = dot(N, -ld.l_forward); - } - else { - vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); - vis *= 1.5; /* XXX ad hoc, empirical */ - vis /= (l_vector.w * l_vector.w); - falloff = dot(N, l_vector.xyz / l_vector.w); - } - // vis *= M_1_PI; /* Normalize */ - - /* Applying profile */ - vis *= sss_profile(abs(delta) / scale); - - /* No transmittance at grazing angle (hide artifacts) */ - vis *= saturate(falloff * 2.0); - } - else { - vis = vec3(0.0); - } - - return vis; -#endif -} diff --git a/source/blender/draw/engines/eevee/shaders/lights_lib.glsl b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl new file mode 100644 index 00000000000..e12d76596d3 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/lights_lib.glsl @@ -0,0 +1,451 @@ + +uniform sampler2DArray shadowCubeTexture; +uniform sampler2DArray shadowCascadeTexture; + +#define LAMPS_LIB + +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 AREA_RECT 4.0 +/* Used to define the area light shape, doesn't directly correspond to a Blender light type. */ +#define AREA_ELLIPSE 100.0 + +#if defined(SHADOW_VSM) +#define ShadowSample vec2 +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).rg +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).rg +#elif defined(SHADOW_ESM) +#define ShadowSample float +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r +#else +#define ShadowSample float +#define sample_cube(vec, id) texture_octahedron(shadowCubeTexture, vec4(vec, id)).r +#define sample_cascade(vec, id) texture(shadowCascadeTexture, vec3(vec, id)).r +#endif + +#if defined(SHADOW_VSM) +#define get_depth_delta(dist, s) (dist - s.x) +#else +#define get_depth_delta(dist, s) (dist - s) +#endif + +/* ----------------------------------------------------------- */ +/* ----------------------- Shadow tests ---------------------- */ +/* ----------------------------------------------------------- */ + +#if defined(SHADOW_VSM) + +float shadow_test(ShadowSample moments, float dist, ShadowData sd) +{ + float p = 0.0; + + if (dist <= moments.x) { + p = 1.0; + } + + float variance = moments.y - (moments.x * moments.x); + variance = max(variance, sd.sh_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 - sd.sh_bleed) / (1.0 - sd.sh_bleed), 0.0, 1.0); + + return max(p, p_max); +} + +#elif defined(SHADOW_ESM) + +float shadow_test(ShadowSample z, float dist, ShadowData sd) +{ + return saturate(exp(sd.sh_exp * (z - dist + sd.sh_bias))); +} + +#else + +float shadow_test(ShadowSample z, float dist, ShadowData sd) +{ + return step(0, z - dist + sd.sh_bias); +} + +#endif + +/* ----------------------------------------------------------- */ +/* ----------------------- Shadow types ---------------------- */ +/* ----------------------------------------------------------- */ + +float shadow_cubemap(ShadowData sd, ShadowCubeData scd, float texid, vec3 W) +{ + vec3 cubevec = W - scd.position.xyz; + float dist = length(cubevec); + + cubevec /= dist; + + ShadowSample s = sample_cube(cubevec, texid); + return shadow_test(s, dist, sd); +} + +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; + + ShadowSample s = sample_cascade(shpos.xy, texid); + float vis = shadow_test(s, dist, sd); + + /* 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, int scd_id, float texid, vec3 W) +{ + vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); + vec4 weights = smoothstep( + shadows_cascade_data[scd_id].split_end_distances, + shadows_cascade_data[scd_id].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. */ + /* TODO OPTI: Only do 2 samples and blend. */ + vis.x = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[0], W, range, texid + 0); + vis.y = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[1], W, range, texid + 1); + vis.z = evaluate_cascade(sd, shadows_cascade_data[scd_id].shadowmat[2], W, range, texid + 2); + vis.w = evaluate_cascade(sd, shadows_cascade_data[scd_id].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 --------------------- */ +/* ----------------------------------------------------------- */ + +/* From Frostbite PBR Course + * Distance based attenuation + * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */ +float distance_attenuation(float dist_sqr, float inv_sqr_influence) +{ + float factor = dist_sqr * inv_sqr_influence; + float fac = saturate(1.0 - factor * factor); + return fac * fac; +} + +float spot_attenuation(LightData ld, vec3 l_vector) +{ + 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 = inversesqrt(1.0 + x * x + y * y); + float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); + return spotmask; +} + +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) { + vis *= spot_attenuation(ld, l_vector.xyz); + } + if (ld.l_type >= SPOT) { + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + if (ld.l_type != SUN) { + vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence); + } + +#if !defined(VOLUMETRICS) || defined(VOLUME_SHADOW) + /* shadowing */ + if (ld.l_shadowid >= 0.0 && vis > 0.001) { + ShadowData data = shadows_data[int(ld.l_shadowid)]; + + if (ld.l_type == SUN) { + vis *= shadow_cascade( + data, int(data.sh_data_start), + data.sh_tex_start, W); + } + else { + 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 (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); + + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + rand.zw *= fast_sqrt(rand.y) * 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.z + B * rand.w; + ray_dir = transform_direction(ViewMatrix, ray_dir); + ray_dir = normalize(ray_dir); + + vec3 ray_ori = viewPosition; + + if (dot(viewNormal, ray_dir) <= 0.0) { + return vis; + } + + float bias = 0.5; /* Constant Bias */ + bias += 1.0 - abs(dot(viewNormal, ray_dir)); /* Angle dependent bias */ + bias *= gl_FrontFacing ? data.sh_contact_offset : -data.sh_contact_offset; + + vec3 nor_bias = viewNormal * bias; + ray_ori += nor_bias; + + ray_dir *= trace_distance; + ray_dir -= nor_bias; + + vec3 hit_pos = raycast(-1, ray_ori, ray_dir, data.sh_contact_thickness, rand.x, + 0.1, 0.001, false); + + 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 vis * saturate(dist_ratio * dist_ratio * dist_ratio); + } + } +#endif + } +#endif + + return vis; +} + +#ifdef USE_LTC +float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 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) { + 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 { + 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)); + } +} + +float light_specular(LightData ld, vec4 ltc_mat, vec3 N, vec3 V, vec4 l_vector) +{ + 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 { + 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 + +#define MAX_SSS_SAMPLES 65 +#define SSS_LUT_SIZE 64.0 +#define SSS_LUT_SCALE ((SSS_LUT_SIZE - 1.0) / float(SSS_LUT_SIZE)) +#define SSS_LUT_BIAS (0.5 / float(SSS_LUT_SIZE)) + +#ifdef USE_TRANSLUCENCY +layout(std140) uniform sssProfile { + vec4 kernel[MAX_SSS_SAMPLES]; + vec4 radii_max_radius; + int sss_samples; +}; + +uniform sampler1D sssTexProfile; + +vec3 sss_profile(float s) { + s /= radii_max_radius.w; + return texture(sssTexProfile, saturate(s) * SSS_LUT_SCALE + SSS_LUT_BIAS).rgb; +} +#endif + +vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) +{ +#if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS) + return vec3(0.0); +#else + vec3 vis = vec3(1.0); + + if (ld.l_type == SPOT) { + vis *= spot_attenuation(ld, l_vector.xyz); + } + if (ld.l_type >= SPOT) { + vis *= step(0.0, -dot(l_vector.xyz, ld.l_forward)); + } + if (ld.l_type != SUN) { + vis *= distance_attenuation(l_vector.w * l_vector.w, ld.l_influence); + } + + /* Only shadowed light can produce translucency */ + if (ld.l_shadowid >= 0.0 && vis.x > 0.001) { + ShadowData data = shadows_data[int(ld.l_shadowid)]; + float delta; + + vec4 L = (ld.l_type != SUN) ? l_vector : vec4(-ld.l_forward, 1.0); + + vec3 T, B; + make_orthonormal_basis(L.xyz / L.w, T, B); + + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + rand.zw *= fast_sqrt(rand.y) * data.sh_blur; + + /* We use the full l_vector.xyz so that the spread is minimize + * if the shading point is further away from the light source */ + W = W + T * rand.z + B * rand.w; + + if (ld.l_type == SUN) { + int scd_id = int(data.sh_data_start); + vec4 view_z = vec4(dot(W - cameraPos, cameraForward)); + + vec4 weights = step(shadows_cascade_data[scd_id].split_end_distances, view_z); + float id = abs(4.0 - dot(weights, weights)); + + if (id > 3.0) { + return vec3(0.0); + } + + float range = abs(data.sh_far - data.sh_near); /* Same factor as in get_cascade_world_distance(). */ + + vec4 shpos = shadows_cascade_data[scd_id].shadowmat[int(id)] * vec4(W, 1.0); + float dist = shpos.z * range; + + if (shpos.z > 1.0 || shpos.z < 0.0) { + return vec3(0.0); + } + + ShadowSample s = sample_cascade(shpos.xy, data.sh_tex_start + id); + delta = get_depth_delta(dist, s); + } + else { + vec3 cubevec = W - shadows_cube_data[int(data.sh_data_start)].position.xyz; + float dist = length(cubevec); + cubevec /= dist; + + ShadowSample s = sample_cube(cubevec, data.sh_tex_start); + delta = get_depth_delta(dist, s); + } + + /* XXX : Removing Area Power. */ + /* TODO : put this out of the shader. */ + float falloff; + if (ld.l_type == AREA_RECT || ld.l_type == AREA_ELLIPSE) { + vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + if (ld.l_type == AREA_ELLIPSE) { + vis *= M_PI * 0.25; + } + vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ + vis /= (l_vector.w * l_vector.w); + falloff = dot(N, l_vector.xyz / l_vector.w); + } + else if (ld.l_type == SUN) { + vis /= 1.0f + (ld.l_radius * ld.l_radius * 0.5f); + vis *= ld.l_radius * ld.l_radius * M_PI; /* Removing area light power*/ + vis *= M_2PI * 0.78; /* Matching cycles with point light. */ + vis *= 0.082; /* XXX ad hoc, empirical */ + falloff = dot(N, -ld.l_forward); + } + else { + vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); + vis *= 1.5; /* XXX ad hoc, empirical */ + vis /= (l_vector.w * l_vector.w); + falloff = dot(N, l_vector.xyz / l_vector.w); + } + // vis *= M_1_PI; /* Normalize */ + + /* Applying profile */ + vis *= sss_profile(abs(delta) / scale); + + /* No transmittance at grazing angle (hide artifacts) */ + vis *= saturate(falloff * 2.0); + } + else { + vis = vec3(0.0); + } + + return vis; +#endif +} -- cgit v1.2.3