diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-05-20 14:16:14 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-05-20 17:58:07 +0300 |
commit | d9d65a06d3db36efd5848cf7ae3e08c72c2c296b (patch) | |
tree | 74157d860a6191d92b70df8c8b3f667bc9302ca4 /source/blender/draw/engines/eevee/shaders | |
parent | 4c3382d55f98c721f6116919acce4abba8f01f11 (diff) |
Eevee: Move cube shadows to octahedron shadowmaps.
We render linear distance to the light in a R32 texture and store it into an octahedron projection inside a 2D texture array.
This render the sampling function much more simpler and without edge artifacts.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
7 files changed, 117 insertions, 67 deletions
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 1e29aed739d..1c124c06744 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -11,8 +11,7 @@ uniform vec3 shCoefs[9]; #ifndef USE_LTC uniform sampler2D brdfLut; #endif -uniform sampler2DArrayShadow shadowCubes; -uniform sampler2DArrayShadow shadowMaps; +uniform sampler2DArray shadowCubes; uniform sampler2DArrayShadow shadowCascades; layout(std140) uniform light_block { @@ -130,75 +129,30 @@ float light_visibility(LightData ld, ShadingData sd) vis *= texture(shadowCascades, vec4(shpos.xy, shid * float(MAX_CASCADE_NUM) + cascade, shpos.z)); } - else if (ld.l_shadowid >= MAX_SHADOW_CUBE) { - /* Shadow Map */ - float shid = ld.l_shadowid - MAX_SHADOW_CUBE; - ShadowMapData smd = shadows_map_data[int(shid)]; - vec4 shpos = smd.shadowmat * vec4(sd.W, 1.0); - shpos.z -= smd.sh_map_bias * shpos.w; - shpos.xyz /= shpos.w; - - if (shpos.w > 0.0 && min(shpos.x, shpos.y) > 0.0 && max(shpos.x, shpos.y) < 1.0) { - vis *= texture(shadowMaps, vec4(shpos.xy, shid, shpos.z)); - } - } else { /* Shadow Cube */ float shid = ld.l_shadowid; ShadowCubeData scd = shadows_cube_data[int(shid)]; - float face; - vec2 uvs; - vec3 Linv = sd.L; - vec3 Labs = abs(Linv); - vec3 maj_axis; - - if (max(Labs.y, Labs.z) < Labs.x) { - if (Linv.x > 0.0) { - face = 1.0; - uvs = vec2(1.0, -1.0) * Linv.zy / -Linv.x; - maj_axis = vec3(1.0, 0.0, 0.0); - } - else { - face = 0.0; - uvs = -Linv.zy / Linv.x; - maj_axis = vec3(-1.0, 0.0, 0.0); - } - } - else if (max(Labs.x, Labs.z) < Labs.y) { - if (Linv.y > 0.0) { - face = 2.0; - uvs = vec2(-1.0, 1.0) * Linv.xz / Linv.y; - maj_axis = vec3(0.0, 1.0, 0.0); - } - else { - face = 3.0; - uvs = -Linv.xz / -Linv.y; - maj_axis = vec3(0.0, -1.0, 0.0); - } - } - else { - if (Linv.z > 0.0) { - face = 5.0; - uvs = Linv.xy / Linv.z; - maj_axis = vec3(0.0, 0.0, 1.0); - } - else { - face = 4.0; - uvs = vec2(-1.0, 1.0) * Linv.xy / -Linv.z; - maj_axis = vec3(0.0, 0.0, -1.0); - } + vec3 cubevec = sd.W - ld.l_position; + float dist = length(cubevec); + + /* projection onto octahedron */ + cubevec /= dot( vec3(1), abs(cubevec) ); + + /* out-folding of the downward faces */ + if ( cubevec.z < 0.0 ) { + cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy); } + vec2 texelSize = vec2(1.0 / 512.0); - uvs = uvs * 0.5 + 0.5; + /* mapping to [0;1]ˆ2 texture space */ + vec2 uvs = cubevec.xy * (0.5) + 0.5; + uvs = uvs * (1.0 - 2.0 * texelSize) + 1.0 * texelSize; /* edge filtering fix */ - /* Depth in lightspace to compare against shadow map */ - float w = dot(maj_axis, sd.l_vector); - w -= scd.sh_map_bias * w; - bool is_persp = (ProjectionMatrix[3][3] == 0.0); - float shdepth = buffer_depth(is_persp, w, scd.sh_cube_far, scd.sh_cube_near); + float sh_test = step(0, texture(shadowCubes, vec3(uvs, shid)).r - dist); - vis *= texture(shadowCubes, vec4(uvs, shid * 6.0 + face, shdepth)); + vis *= sh_test; } return vis; diff --git a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl index 29335207851..0b7356d812b 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl @@ -1,3 +1,8 @@ +in float linearDistance; + +out vec4 FragColor; + void main() { + FragColor = vec4(linearDistance, 0.0, 0.0, 1.0); } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl index bac6a10eee1..c4738de2f31 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl @@ -1,21 +1,26 @@ -layout(triangles) in; -layout(triangle_strip, max_vertices=3) out; - layout(std140) uniform shadow_render_block { mat4 ShadowMatrix[6]; - int Layer; + vec4 lampPosition; + int layer; }; +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; + in vec4 vPos[]; +in float lDist[]; flat in int face[]; +out float linearDistance; + void main() { int f = face[0]; - gl_Layer = Layer + f; + gl_Layer = f; for (int v = 0; v < 3; ++v) { gl_Position = ShadowMatrix[f] * vPos[v]; + linearDistance = lDist[v]; EmitVertex(); } diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl new file mode 100644 index 00000000000..08453080ed2 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_frag.glsl @@ -0,0 +1,47 @@ + +uniform samplerCube shadowCube; + +out vec4 FragColor; + +vec3 octahedral_to_cubemap_proj(vec2 co) +{ + co = co * 2.0 - 1.0; + + vec2 abs_co = abs(co); + vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y)); + + if ( abs_co.x + abs_co.y > 1.0 ) { + v.xy = (abs(co.yx) - 1.0) * -sign(co.xy); + } + + return v; +} + +void main() { + const vec2 texelSize = vec2(1.0 / 512.0); + + vec2 uvs = gl_FragCoord.xy * texelSize; + + /* add a 2 pixel border to ensure filtering is correct */ + uvs.xy *= 1.0 + texelSize * 2.0; + uvs.xy -= texelSize; + + float pattern = 1.0; + + /* edge mirroring : only mirror if directly adjacent + * (not diagonally adjacent) */ + vec2 m = abs(uvs - 0.5) + 0.5; + vec2 f = floor(m); + if (f.x - f.y != 0.0) { + uvs.xy = 1.0 - uvs.xy; + } + + /* clamp to [0-1] */ + uvs.xy = fract(uvs.xy); + + /* get cubemap vector */ + vec3 cubevec = octahedral_to_cubemap_proj(uvs.xy); + + /* get cubemap vector */ + FragColor = texture(shadowCube, cubevec).rrrr; +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl new file mode 100644 index 00000000000..f14354ad4cd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_geom.glsl @@ -0,0 +1,22 @@ + +layout(std140) uniform shadow_render_block { + mat4 ShadowMatrix[6]; + vec4 lampPosition; + int layer; +}; + +layout(triangles) in; +layout(triangle_strip, max_vertices=3) out; + +in vec4 vPos[]; + +void main() { + gl_Layer = layer; + + for (int v = 0; v < 3; ++v) { + gl_Position = vPos[v]; + EmitVertex(); + } + + EndPrimitive(); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl new file mode 100644 index 00000000000..dee020f19b4 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/shadow_store_vert.glsl @@ -0,0 +1,8 @@ + +in vec3 pos; + +out vec4 vPos; + +void main() { + vPos = vec4(pos, 1.0); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl index ffb99f1b35c..323cf4d2a99 100644 --- a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl +++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl @@ -1,12 +1,21 @@ +layout(std140) uniform shadow_render_block { + mat4 ShadowMatrix[6]; + vec4 lampPosition; + int layer; +}; + uniform mat4 ShadowModelMatrix; in vec3 pos; out vec4 vPos; +out float lDist; + flat out int face; void main() { vPos = ShadowModelMatrix * vec4(pos, 1.0); + lDist = distance(lampPosition.xyz, vPos.xyz); face = gl_InstanceID; }
\ No newline at end of file |