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>2018-01-16 20:21:56 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-01-16 20:22:25 +0300
commit9fd28c776938fe420782a6339e9da7c619724dae (patch)
treec24866ccd3f0670d82f5686362bbfb3f2e8741d5 /source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
parentc372113489cbcd072aaba5abe50e6fa125f35cea (diff)
Eevee: AO: Removes samples and denoise options.
This comes with a lot of code simplification that leads to a small performance improvement.
Diffstat (limited to 'source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl')
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl157
1 files changed, 36 insertions, 121 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 5ec72833379..302b7596cc3 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -30,87 +30,29 @@
#ifndef UTIL_TEX
#define UTIL_TEX
uniform sampler2DArray utilTex;
+#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0)
#endif /* UTIL_TEX */
uniform vec4 aoParameters[2];
-uniform sampler2DArray horizonBuffer;
-
-/* Cannot use textureSize(horizonBuffer) when rendering to it */
-uniform ivec2 aoHorizonTexSize;
+uniform sampler2D horizonBuffer;
#define aoDistance aoParameters[0].x
-#define aoSamples aoParameters[0].y
+#define aoSamples aoParameters[0].y /* UNUSED */
#define aoFactor aoParameters[0].z
-#define aoInvSamples aoParameters[0].w
+#define aoInvSamples aoParameters[0].w /* UNUSED */
#define aoOffset aoParameters[1].x /* UNUSED */
#define aoBounceFac aoParameters[1].y
#define aoQuality aoParameters[1].z
#define aoSettings aoParameters[1].w
+/* aoSettings flags */
#define USE_AO 1
#define USE_BENT_NORMAL 2
#define USE_DENOISE 4
-vec2 pack_horizons(vec2 v) { return v * 0.5 + 0.5; }
-vec2 unpack_horizons(vec2 v) { return v * 2.0 - 1.0; }
-
-/* Returns the texel coordinate in horizonBuffer
- * for a given fullscreen coord */
-ivec2 get_hr_co(ivec2 fs_co)
-{
- bvec2 quarter = notEqual(fs_co & ivec2(1), ivec2(0));
-
- ivec2 hr_co = fs_co / 2;
- hr_co += ivec2(quarter) * (aoHorizonTexSize / 2);
-
- return hr_co;
-}
-
-/* Returns the texel coordinate in fullscreen (depthBuffer)
- * for a given horizonBuffer coord */
-ivec2 get_fs_co(ivec2 hr_co)
-{
- hr_co *= 2;
- bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize);
-
- hr_co -= ivec2(quarter) * (aoHorizonTexSize - 1);
-
- return hr_co;
-}
-
-/* Returns the phi angle in horizonBuffer
- * for a given horizonBuffer coord */
-float get_phi(ivec2 hr_co, ivec2 fs_co, float sample)
-{
- bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize / 2);
- ivec2 tex_co = ((int(aoSettings) & USE_DENOISE) != 0) ? hr_co - ivec2(quarter) * (aoHorizonTexSize / 2) : fs_co;
- float blue_noise = texture(utilTex, vec3((vec2(tex_co) + 0.5) / LUT_SIZE, 2.0)).r;
-
- float phi = sample * aoInvSamples;
-
- if ((int(aoSettings) & USE_DENOISE) != 0) {
- /* Interleaved jitter for spatial 2x2 denoising */
- phi += 0.25 * aoInvSamples * (float(quarter.x) + 2.0 * float(quarter.y));
- blue_noise *= 0.25;
- }
- /* Blue noise is scaled to cover the rest of the range. */
- phi += aoInvSamples * blue_noise;
- phi *= M_PI;
-
- return phi;
-}
-
-/* Returns direction jittered offset for a given fullscreen coord */
-float get_offset(ivec2 fs_co, float sample)
-{
- float offset = sample * aoInvSamples;
-
- /* Interleaved jitter for spatial 2x2 denoising */
- offset += 0.25 * dot(vec2(1.0), vec2(fs_co & 1));
- offset += texture(utilTex, vec3((vec2(fs_co / 2) + 0.5 + 16.0) / LUT_SIZE, 2.0)).r;
- return offset;
-}
+vec4 pack_horizons(vec4 v) { return v * 0.5 + 0.5; }
+vec4 unpack_horizons(vec4 v) { return v * 2.0 - 1.0; }
/* Returns maximum screen distance an AO ray can travel for a given view depth */
vec2 get_max_dir(float view_depth)
@@ -120,6 +62,13 @@ vec2 get_max_dir(float view_depth)
return vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * max_dist;
}
+vec2 get_ao_dir(float jitter)
+{
+ /* Only half a turn because we integrate in slices. */
+ jitter *= M_PI;
+ return vec2(cos(jitter), sin(jitter));
+}
+
void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h)
{
co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */
@@ -161,10 +110,8 @@ void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float
h = mix(h, max(h, s_h.w), blend.w);
}
-vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir)
+vec2 search_horizon_sweep(vec2 t_phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir)
{
- vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
-
max_dir *= max_v2(abs(t_phi));
/* Convert to pixel space. */
@@ -214,11 +161,8 @@ vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_
return h;
}
-void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibility, inout vec3 bent_normal)
+void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibility, inout vec3 bent_normal)
{
- /* TODO OPTI Could be precomputed. */
- vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
-
/* Projecting Normal to Plane P defined by t_phi and omega_o */
vec3 np = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */
vec3 t = vec3(-t_phi, 0.0);
@@ -251,71 +195,43 @@ void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibili
bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5);
}
-void denoise_ao(vec3 normal, float frag_depth, inout float visibility, inout vec3 bent_normal)
+void gtao_deferred(vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal)
{
- vec2 d_sign = vec2(ivec2(gl_FragCoord.xy) & 1) - 0.5;
-
- if ((int(aoSettings) & USE_DENOISE) == 0) {
- d_sign *= 0.0;
- }
-
- /* 2x2 Bilateral Filter using derivatives. */
- vec2 n_step = step(-0.2, -abs(vec2(length(dFdx(normal)), length(dFdy(normal)))));
- vec2 z_step = step(-0.1, -abs(vec2(dFdx(frag_depth), dFdy(frag_depth))));
-
- visibility -= dFdx(visibility) * d_sign.x * z_step.x * n_step.x;
- visibility -= dFdy(visibility) * d_sign.y * z_step.y * n_step.y;
+ /* Fetch early, hide latency! */
+ vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0);
- bent_normal -= dFdx(bent_normal) * d_sign.x * z_step.x * n_step.x;
- bent_normal -= dFdy(bent_normal) * d_sign.y * z_step.y * n_step.y;
-}
-
-void gtao_deferred(vec3 normal, vec3 position, float frag_depth, out float visibility, out vec3 bent_normal)
-{
+ vec4 dirs;
+ dirs.xy = get_ao_dir(noise.x * 0.5);
+ dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5);
vec2 uvs = get_uvs_from_view(position);
- vec4 texel_size = vec4(-1.0, -1.0, 1.0, 1.0) / vec2(textureSize(depthBuffer, 0)).xyxy;
-
- ivec2 fs_co = ivec2(gl_FragCoord.xy);
- ivec2 hr_co = get_hr_co(fs_co);
-
bent_normal = vec3(0.0);
visibility = 0.0;
- for (float i = 0.0; i < MAX_PHI_STEP; i++) {
- if (i >= aoSamples) break;
+ horizons = unpack_horizons(horizons);
- vec2 horiz = unpack_horizons(texelFetch(horizonBuffer, ivec3(hr_co, int(i)), 0).rg);
- float phi = get_phi(hr_co, fs_co, i);
+ integrate_slice(normal, dirs.xy, horizons.xy, visibility, bent_normal);
+ integrate_slice(normal, dirs.zw, horizons.zw, visibility, bent_normal);
- integrate_slice(normal, phi, horiz.xy, visibility, bent_normal);
- }
+ visibility *= 0.5; /* We integrated 2 slices. */
- visibility *= aoInvSamples;
bent_normal = normalize(bent_normal);
}
-void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility, out vec3 bent_normal)
+void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3 bent_normal)
{
vec2 uvs = get_uvs_from_view(position);
-
- float homcco = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3];
- float max_dist = aoDistance / homcco; /* Search distance */
- vec2 max_dir = max_dist * vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]);
+ vec2 max_dir = get_max_dir(position.z);
+ vec2 dir = get_ao_dir(noise.x);
bent_normal = vec3(0.0);
visibility = 0.0;
- for (float i = 0.0; i < MAX_PHI_STEP; i++) {
- if (i >= aoSamples) break;
-
- float phi = M_PI * (i + noise.x) * aoInvSamples;
- vec2 horizons = search_horizon_sweep(phi, position, uvs, noise.g, max_dir);
-
- integrate_slice(normal, phi, horizons, visibility, bent_normal);
- }
+ /* Only trace in 2 directions. May lead to a darker result but since it's mostly for
+ * alpha blended objects that will have overdraw, we limit the performance impact. */
+ vec2 horizons = search_horizon_sweep(dir, position, uvs, noise.y, max_dir);
+ integrate_slice(normal, dir, horizons, visibility, bent_normal);
- visibility *= aoInvSamples;
bent_normal = normalize(bent_normal);
}
@@ -337,7 +253,7 @@ float gtao_multibounce(float visibility, vec3 albedo)
}
/* Use the right occlusion */
-float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, out vec3 bent_normal)
+float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal)
{
#ifndef USE_REFRACTION
if ((int(aoSettings) & USE_AO) > 0) {
@@ -345,11 +261,10 @@ float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, ou
vec3 vnor = mat3(ViewMatrix) * N;
#ifdef ENABLE_DEFERED_AO
- gtao_deferred(vnor, vpos, gl_FragCoord.z, visibility, bent_normal);
+ gtao_deferred(vnor, vpos, rand, gl_FragCoord.z, visibility, bent_normal);
#else
- gtao(vnor, vpos, randuv, visibility, bent_normal);
+ gtao(vnor, vpos, rand, visibility, bent_normal);
#endif
- denoise_ao(vnor, gl_FragCoord.z, visibility, bent_normal);
/* Prevent some problems down the road. */
visibility = max(1e-3, visibility);