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:
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl87
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl15
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c4
4 files changed, 71 insertions, 37 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 0017307ba34..473990e1683 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -80,12 +80,13 @@ float search_horizon(vec3 vI,
vec2 uv_start,
vec2 uv_dir,
sampler2D depth_tx,
+ const float inverted,
float radius,
const float sample_count)
{
float sample_count_inv = 1.0 / sample_count;
/* Init at cos(M_PI). */
- float h = -1.0;
+ float h = (inverted != 0.0) ? 1.0 : -1.0;
/* TODO(fclem) samples steps should be using the same approach as raytrace. (DDA line algo.) */
for (float i = 0.0; i < sample_count; i++) {
@@ -97,7 +98,8 @@ float search_horizon(vec3 vI,
float depth = textureLod(depth_tx, uv * mipRatio[mip].xy, floor(lod)).r;
/* Bias depth a bit to avoid self shadowing issues. */
- depth += 2.0 * 2.4e-7;
+ const float bias = 2.0 * 2.4e-7;
+ depth += (inverted != 0.0) ? -bias : bias;
vec3 s = get_view_space_from_depth(uv, depth);
vec3 omega_s = s - vP;
@@ -109,26 +111,29 @@ float search_horizon(vec3 vI,
/* TODO(fclem) parameter. */
float dist_fac = sqr(saturate(dist_ratio * 2.0 - 1.0));
- /* TODO This need to take the stride distance into account. Now it works because stride is
- * constant. */
/* Thickness heuristic (Eq. 9). */
- if (s_h < h) {
- /* TODO(fclem) parameter. */
- const float thickness_fac = 0.2;
- s_h = mix(h, s_h, thickness_fac);
+ if (inverted != 0.0) {
+ h = min(h, s_h);
}
else {
- s_h = max(h, s_h);
+ /* TODO This need to take the stride distance into account. Now it works because stride is
+ * constant. */
+ if (s_h < h) {
+ /* TODO(fclem) parameter. */
+ const float thickness_fac = 0.2;
+ s_h = mix(h, s_h, thickness_fac);
+ }
+ else {
+ s_h = max(h, s_h);
+ }
+ h = mix(s_h, h, dist_fac);
}
- h = mix(s_h, h, dist_fac);
}
return fast_acos(h);
}
-OcclusionData occlusion_search(vec3 vP,
- sampler2D depth_tx,
- float radius,
- const float dir_sample_count)
+OcclusionData occlusion_search(
+ vec3 vP, sampler2D depth_tx, float radius, const float inverted, const float dir_sample_count)
{
if ((int(aoSettings) & USE_AO) == 0) {
return NO_OCCLUSION_DATA;
@@ -142,7 +147,8 @@ OcclusionData occlusion_search(vec3 vP,
vec3 avg_dir = vec3(0.0);
float avg_apperture = 0.0;
- OcclusionData data = NO_OCCLUSION_DATA;
+ OcclusionData data = (inverted != 0.0) ? OcclusionData(vec4(0, 0, 0, 0), 1.0) :
+ NO_OCCLUSION_DATA;
for (int i = 0; i < 2; i++) {
/* View > NDC > Uv space. */
@@ -155,11 +161,11 @@ OcclusionData occlusion_search(vec3 vP,
/* No need to trace more. */
uv_dir -= uv_ofs;
- if (max_px_dir > 0.0) {
+ if (max_px_dir > 1.0) {
data.horizons[0 + i * 2] = search_horizon(
- vI, vP, noise.y, uv + uv_ofs, uv_dir, depth_tx, radius, dir_sample_count);
+ vI, vP, noise.y, uv + uv_ofs, uv_dir, depth_tx, inverted, radius, dir_sample_count);
data.horizons[1 + i * 2] = -search_horizon(
- vI, vP, noise.y, uv - uv_ofs, -uv_dir, depth_tx, radius, dir_sample_count);
+ vI, vP, noise.y, uv - uv_ofs, -uv_dir, depth_tx, inverted, radius, dir_sample_count);
}
/* Rotate 90 degrees. */
dir = vec2(-dir.y, dir.x);
@@ -168,8 +174,29 @@ OcclusionData occlusion_search(vec3 vP,
return data;
}
-void occlusion_eval(
- OcclusionData data, vec3 V, vec3 N, vec3 Ng, out float visibility, out vec3 bent_normal)
+vec2 clamp_horizons_to_hemisphere(vec2 horizons, float angle_N, const float inverted)
+{
+ /* Add a little bias to fight self shadowing. */
+ const float max_angle = M_PI_2 - 0.05;
+
+ if (inverted != 0.0) {
+ horizons.x = max(horizons.x, angle_N + max_angle);
+ horizons.y = min(horizons.y, angle_N - max_angle);
+ }
+ else {
+ horizons.x = min(horizons.x, angle_N + max_angle);
+ horizons.y = max(horizons.y, angle_N - max_angle);
+ }
+ return horizons;
+}
+
+void occlusion_eval(OcclusionData data,
+ vec3 V,
+ vec3 N,
+ vec3 Ng,
+ const float inverted,
+ out float visibility,
+ out vec3 bent_normal)
{
if ((int(aoSettings) & USE_AO) == 0) {
visibility = data.custom_occlusion;
@@ -177,7 +204,9 @@ void occlusion_eval(
return;
}
- if (min_v4(abs(data.horizons)) == M_PI) {
+ bool early_out = (inverted != 0.0) ? (max_v4(abs(data.horizons)) == 0.0) :
+ (min_v4(abs(data.horizons)) == M_PI);
+ if (early_out) {
visibility = dot(N, Ng) * 0.5 + 0.5;
visibility = min(visibility, data.custom_occlusion);
@@ -215,10 +244,8 @@ void occlusion_eval(
/* Gamma, angle between normalized projected normal and view vector. */
float angle_Ng = sign(Ng_sin) * fast_acos(Ng_cos);
float angle_N = sign(N_sin) * fast_acos(N_cos);
- /* Add a little bias to fight self shadowing. */
- const float max_angle = M_PI_2 - 0.05;
/* Clamp horizons to hemisphere around shading normal. */
- h = clamp(h, angle_N - max_angle, angle_N + max_angle);
+ h = clamp_horizons_to_hemisphere(h, angle_N, inverted);
float bent_angle = (h.x + h.y) * 0.5;
/* NOTE: here we multiply z by 0.5 as it shows less difference with the geometric normal.
@@ -228,10 +255,10 @@ void occlusion_eval(
/* Clamp to geometric normal only for integral to keep smooth bent normal. */
/* This is done to match Cycles ground truth but adds some computation. */
- h = clamp(h, angle_Ng - max_angle, angle_Ng + max_angle);
+ h = clamp_horizons_to_hemisphere(h, angle_Ng, inverted);
/* Inner integral (Eq. 7). */
- float a = dot(-cos(2.0 * h - angle_N) + cos(angle_N) + 2.0 * h * sin(angle_N), vec2(0.25));
+ float a = dot(-cos(2.0 * h - angle_N) + N_cos + 2.0 * h * N_sin, vec2(0.25));
/* Correct normal not on plane (Eq. 8). */
visibility += proj_N_len * a;
@@ -274,7 +301,7 @@ float diffuse_occlusion(OcclusionData data, vec3 V, vec3 N, vec3 Ng)
{
vec3 unused;
float visibility;
- occlusion_eval(data, V, N, Ng, visibility, unused);
+ occlusion_eval(data, V, N, Ng, 0.0, visibility, unused);
/* Scale by user factor */
visibility = pow(saturate(visibility), aoFactor);
return visibility;
@@ -284,7 +311,7 @@ float diffuse_occlusion(
OcclusionData data, vec3 V, vec3 N, vec3 Ng, vec3 albedo, out vec3 bent_normal)
{
float visibility;
- occlusion_eval(data, V, N, Ng, visibility, bent_normal);
+ occlusion_eval(data, V, N, Ng, 0.0, visibility, bent_normal);
visibility = gtao_multibounce(visibility, albedo);
/* Scale by user factor */
@@ -328,7 +355,7 @@ float specular_occlusion(
{
vec3 visibility_dir;
float visibility;
- occlusion_eval(data, V, N, N, visibility, visibility_dir);
+ occlusion_eval(data, V, N, N, 0.0, visibility, visibility_dir);
specular_dir = normalize(mix(specular_dir, visibility_dir, roughness * (1.0 - visibility)));
@@ -363,7 +390,7 @@ OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
}
#else
/* For blended surfaces and */
- data = occlusion_search(vP, maxzBuffer, aoDistance, 8.0);
+ data = occlusion_search(vP, maxzBuffer, aoDistance, 0.0, 8.0);
#endif
data.custom_occlusion = custom_occlusion;
diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
index 1cabceebcc8..369b0735cd2 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl
@@ -118,7 +118,7 @@ void main()
OcclusionData data = NO_OCCLUSION_DATA;
/* Do not trace for background */
if (depth != 1.0) {
- data = occlusion_search(vP, maxzBuffer, aoDistance, 8.0);
+ data = occlusion_search(vP, maxzBuffer, aoDistance, 0.0, 8.0);
}
FragColor = pack_occlusion_data(data);
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
index f3eea9869e5..4721b9f0132 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
@@ -1,19 +1,24 @@
#ifndef VOLUMETRICS
-void node_ambient_occlusion(
- vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
+void node_ambient_occlusion(vec4 color,
+ float dist,
+ vec3 normal,
+ const float inverted,
+ out vec4 result_color,
+ out float result_ao)
{
vec3 bent_normal;
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
- OcclusionData data = occlusion_load(viewPosition, 1.0);
+ OcclusionData data = occlusion_search(viewPosition, maxzBuffer, dist, inverted, 8.0);
vec3 V = cameraVec;
vec3 N = normalize(normal);
vec3 Ng = safe_normalize(cross(dFdx(worldPosition), dFdy(worldPosition)));
- result_ao = diffuse_occlusion(data, V, N, Ng);
+ vec3 unused;
+ occlusion_eval(data, V, N, Ng, inverted, result_ao, unused);
result_color = result_ao * color;
}
#else
/* Stub ambient occlusion because it is not compatible with volumetrics. */
-# define node_ambient_occlusion(a, b, c, d, e) (e = CLOSURE_DEFAULT)
+# define node_ambient_occlusion(a, b, c, d, e, f) (e = vec4(0); f = 0.0)
#endif
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
index 5d3a9dfc025..36971d4e799 100644
--- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -46,7 +46,9 @@ static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat,
GPU_material_flag_set(mat, GPU_MATFLAG_DIFFUSE);
- return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out);
+ float inverted = node->custom2 ? 1.0f : 0.0f;
+
+ return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out, GPU_constant(&inverted));
}
static void node_shader_init_ambient_occlusion(bNodeTree *UNUSED(ntree), bNode *node)