diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-05-29 23:03:57 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-05-29 23:04:30 +0300 |
commit | 5773f587622ebf58f6aa3bf4ae60431e8b0f39ef (patch) | |
tree | e7f22a4c51464dc443f68a964bc32b18c55e7e42 /source/blender/draw/engines/eevee/shaders | |
parent | 1fa216487d69c79ef81ccf679090e2bfea5b64fd (diff) |
Eevee: Replace Cubemaps by octahedron maps for env. probes.
This enables us to use 2D texture arrays for multiple probes.
There is a little artifact with very high roughness caused elongated pixel due to the projection (along every 90° meridian).
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders')
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl | 57 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/probe_filter_frag.glsl | 39 |
2 files changed, 79 insertions, 17 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 bff7c05537a..ca3cec62bdb 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -4,7 +4,7 @@ uniform vec3 cameraPos; uniform vec3 eye; uniform mat4 ProjectionMatrix; -uniform samplerCube probeFiltered; +uniform sampler2D probeFiltered; uniform float lodMax; uniform vec3 shCoefs[9]; @@ -42,6 +42,44 @@ in vec3 viewNormal; #define HEMI 3.0 #define AREA 4.0 +vec2 mapping_octahedron(vec3 cubevec, vec2 texel_size) +{ + /* 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); + } + + /* mapping to [0;1]ˆ2 texture space */ + vec2 uvs = cubevec.xy * (0.5) + 0.5; + + /* edge filtering fix */ + uvs *= 1.0 - 2.0 * texel_size; + uvs += texel_size; + + return uvs; +} + +vec4 textureLod_octahedron(sampler2D tex, vec3 cubevec, float lod) +{ + vec2 texelSize = 1.0 / vec2(textureSize(tex, int(lodMax))); + + vec2 uvs = mapping_octahedron(cubevec, texelSize); + + return textureLod(tex, uvs, lod); +} + +vec4 texture_octahedron(sampler2DArray tex, vec4 cubevec) +{ + vec2 texelSize = 1.0 / vec2(textureSize(tex, 0)); + + vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize); + + return texture(tex, vec3(uvs, cubevec.w)); +} + void light_shade( LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0, out vec3 diffuse, out vec3 specular) @@ -139,20 +177,7 @@ void light_visibility(LightData ld, ShadingData sd, out float vis) 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); - - /* 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 */ - - float z = texture(shadowCubes, vec3(uvs, shid)).r; + float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r; float esm_test = min(1.0, exp(-5.0 * dist) * z); float sh_test = step(0, z - dist); @@ -194,7 +219,7 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, /* 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; + vec3 Li = textureLod_octahedron(probeFiltered, spec_dir, roughness * lodMax).rgb; indirect_radiance += Li * F_ibl(f0, brdf_lut.rg); indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo; diff --git a/source/blender/draw/engines/eevee/shaders/probe_filter_frag.glsl b/source/blender/draw/engines/eevee/shaders/probe_filter_frag.glsl index bee674e3e76..33714c5293c 100644 --- a/source/blender/draw/engines/eevee/shaders/probe_filter_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/probe_filter_frag.glsl @@ -1,17 +1,54 @@ uniform samplerCube probeHdr; uniform float roughnessSquared; +uniform float texelSize; uniform float lodFactor; uniform float lodMax; +uniform float paddingSize; in vec3 worldPosition; 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() { + vec2 uvs = gl_FragCoord.xy * texelSize; + + /* Add a N pixel border to ensure filtering is correct + * for N mipmap levels. */ + uvs += uvs * texelSize * paddingSize * 2.0; + uvs -= texelSize * paddingSize; + + /* 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 = 1.0 - uvs; + } + + /* clamp to [0-1] */ + uvs = fract(uvs); + + /* get cubemap vector */ + vec3 cubevec = octahedral_to_cubemap_proj(uvs); + vec3 N, T, B, V; - vec3 R = normalize(worldPosition); + vec3 R = normalize(cubevec); /* Isotropic assumption */ N = V = R; |