diff options
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.glsl | 150 |
1 files changed, 76 insertions, 74 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 10758f74bf2..6dc02d26321 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -13,98 +13,102 @@ uniform vec3 aoParameters; #define aoSamples aoParameters.y #define aoFactor aoParameters.z -float get_max_horizon(vec2 co, vec3 x, float h, float lod) +void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h) { - float depth = textureLod(maxzBuffer, co, floor(lod)).r; + co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */ + co2 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */ - /* Background case */ - /* this is really slow and is only a problem - * if the far clip plane is near enough to notice */ - // depth += step(1.0, depth) * 1e20; + float depth1 = textureLod(maxzBuffer, co1.xy, floor(lod)).r; + float depth2 = textureLod(maxzBuffer, co1.zw, floor(lod)).r; + float depth3 = textureLod(maxzBuffer, co2.xy, floor(lod)).r; + float depth4 = textureLod(maxzBuffer, co2.zw, floor(lod)).r; - vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */ - vec3 omega_s = s - x; - float len = length(omega_s); + vec4 len, s_h; - float max_h = max(h, omega_s.z / len); - /* Blend weight after half the aoDistance to fade artifacts */ - float blend = saturate((1.0 - len / aoDistance) * 2.0); + vec3 s1 = get_view_space_from_depth(co1.xy, depth1); /* s View coordinate */ + vec3 omega_s1 = s1 - x; + len.x = length(omega_s1); + s_h.x = omega_s1.z / len.x; - return mix(h, max_h, blend); -} + vec3 s2 = get_view_space_from_depth(co1.zw, depth2); /* s View coordinate */ + vec3 omega_s2 = s2 - x; + len.y = length(omega_s2); + s_h.y = omega_s2.z / len.y; -void search_step( - vec2 t_phi, vec3 x, vec2 x_, float rand, vec2 pixel_ratio, - inout float j, inout float ofs, inout float h1, inout float h2) -{ - ofs += ofs; /* Step size is doubled each iteration */ + vec3 s3 = get_view_space_from_depth(co2.xy, depth3); /* s View coordinate */ + vec3 omega_s3 = s3 - x; + len.z = length(omega_s3); + s_h.z = omega_s3.z / len.z; - vec2 s_ = t_phi * ofs * rand * pixel_ratio; /* s^ Screen coordinate */ - vec2 co; + vec3 s4 = get_view_space_from_depth(co2.zw, depth4); /* s View coordinate */ + vec3 omega_s4 = s4 - x; + len.w = length(omega_s4); + s_h.w = omega_s4.z / len.w; - co = x_ + s_; - h1 = get_max_horizon(co, x, h1, j); - - co = x_ - s_; - h2 = get_max_horizon(co, x, h2, j); + /* Blend weight after half the aoDistance to fade artifacts */ + vec4 blend = saturate((1.0 - len / aoDistance) * 2.0); - j += 0.5; + h = mix(h, max(h, s_h.x), blend.x); + h = mix(h, max(h, s_h.y), blend.y); + h = mix(h, max(h, s_h.z), blend.z); + h = mix(h, max(h, s_h.w), blend.w); } -void search_horizon( - vec2 t_phi, vec3 x, vec2 x_, float rand, - float max_dist, vec2 pixel_ratio, float pixel_len, - inout float h1, inout float h2) +#define MAX_ITER 16 +#define MAX_LOD 6 +#define QUALITY 0.75 +vec2 search_horizon_sweep(vec2 t_phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir) { - float ofs = 1.5 * pixel_len; - float j = 0.0; - -#if 0 /* manually unrolled bellow */ - for (int i = 0; i < MAX_THETA_STEP; i++) { - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) - return; - } -#endif - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; - - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + max_dir *= max_v2(abs(t_phi)); - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + /* Convert to pixel space. */ + t_phi /= vec2(textureSize(maxzBuffer, 0)); - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + /* Avoid division by 0 */ + t_phi += vec2(1e-5); - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + jitter *= 0.25; - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + /* Compute end points */ + vec2 corner1 = min(vec2(1.0) - uvs, max_dir); /* Top right */ + vec2 corner2 = max(vec2(0.0) - uvs, -max_dir); /* Bottom left */ + vec2 iter1 = corner1 / t_phi; + vec2 iter2 = corner2 / t_phi; - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + vec2 min_iter = max(-iter1, -iter2); + vec2 max_iter = max( iter1, iter2); - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + vec2 times = vec2(-min_v2(min_iter), min_v2(max_iter)); - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + vec2 h = vec2(-1.0); /* init at cos(pi) */ - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + /* This is freaking sexy optimized. */ + for (float i = 0.0, ofs = 4.0, time = -1.0; + i < MAX_ITER && time > times.x; + i++, time -= ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs)) + { + vec4 t = max(times.xxxx, vec4(time) - (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs); + vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy; + vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww; + get_max_horizon_grouped(cos1, cos2, pos, min(MAX_LOD, i * QUALITY), h.y); + } - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); - if (ofs > max_dist) return; + for (float i = 0.0, ofs = 4.0, time = 1.0; + i < MAX_ITER && time < times.y; + i++, time += ofs, ofs = min(exp2(MAX_LOD) * 4.0, ofs + ofs)) + { + vec4 t = min(times.yyyy, vec4(time) + (vec4(0.25, 0.5, 0.75, 1.0) - jitter) * ofs); + vec4 cos1 = uvs.xyxy + t_phi.xyxy * t.xxyy; + vec4 cos2 = uvs.xyxy + t_phi.xyxy * t.zzww; + get_max_horizon_grouped(cos1, cos2, pos, min(MAX_LOD, i * QUALITY), h.x); + } - search_step(t_phi, x, x_, rand, pixel_ratio, j, ofs, h1, h2); + return h; } void integrate_slice( float iter, vec3 x, vec3 normal, vec2 x_, vec2 noise, - float max_dist, vec2 pixel_ratio, float pixel_len, + vec2 max_dir, vec2 pixel_ratio, float pixel_len, inout float visibility, inout vec3 bent_normal) { float phi = M_PI * ((noise.r + iter) / aoSamples); @@ -113,12 +117,11 @@ void integrate_slice( vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ /* Search maximum horizon angles h1 and h2 */ - float h1 = -1.0, h2 = -1.0; /* init at cos(pi) */ - search_horizon(t_phi, x, x_, noise.g, max_dist, pixel_ratio, pixel_len, h1, h2); + vec2 horiz = search_horizon_sweep(t_phi, x, x_, noise.g, max_dir); /* (Slide 54) */ - h1 = -fast_acos(h1); - h2 = fast_acos(h2); + float h1 = -fast_acos(horiz.x); + float h2 = fast_acos(horiz.y); /* Projecting Normal to Plane P defined by t_phi and omega_o */ vec3 h = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */ @@ -173,6 +176,7 @@ void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility float pixel_len = length(pixel_size); 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]); /* Integral over PI */ visibility = 0.0; @@ -183,7 +187,7 @@ void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility #endif for (float i = 0.0; i < MAX_PHI_STEP; i++) { if (i >= aoSamples) break; - integrate_slice(i, x, normal, x_, noise, max_dist, pixel_ratio, pixel_len, visibility, bent_normal); + integrate_slice(i, x, normal, x_, noise, max_dir, pixel_ratio, pixel_len, visibility, bent_normal); } /* aoSamples can be 0.0 to temporary disable the effect. */ @@ -203,9 +207,7 @@ void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility float gtao_multibounce(float visibility, vec3 albedo) { /* Median luminance. Because Colored multibounce looks bad. */ - float lum = albedo.x * 0.3333; - lum += albedo.y * 0.3333; - lum += albedo.z * 0.3333; + float lum = dot(albedo, vec3(0.3333)); float a = 2.0404 * lum - 0.3324; float b = -4.7951 * lum + 0.6417; |