EEVEE-Next: More work into supporting horizon scan in AO node
This is only part of making inverted scan work. There are still issues with background not being considered outside objects.
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma BLENDER_REQUIRE(gpu_shader_math_vector_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl)
|
||||
#pragma BLENDER_REQUIRE(eevee_horizon_scan_eval_lib.glsl)
|
||||
|
||||
void main()
|
||||
@@ -45,7 +44,8 @@ void main()
|
||||
uniform_buf.ao.distance,
|
||||
uniform_buf.ao.thickness,
|
||||
uniform_buf.ao.angle_bias,
|
||||
10);
|
||||
10,
|
||||
false);
|
||||
|
||||
imageStore(
|
||||
out_ao_img, ivec3(texel, out_ao_img_layer_index), vec4(saturate(ctx.occlusion_result.r)));
|
||||
|
||||
@@ -76,7 +76,8 @@ void main()
|
||||
1.0e16,
|
||||
uniform_buf.ao.thickness,
|
||||
uniform_buf.ao.angle_bias,
|
||||
8);
|
||||
8,
|
||||
false);
|
||||
|
||||
float occlusion = 0.0;
|
||||
vec4 radiance = vec4(1.0, 0.0, 1.0, 1.0);
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#ifdef RAYTRACE_REFRACT
|
||||
# define HORIZON_REFRACT
|
||||
#endif
|
||||
#if defined(MAT_DEFERRED) || defined(MAT_FORWARD)
|
||||
/* Enable AO node computation for material shaders. */
|
||||
# define HORIZON_OCCLUSION
|
||||
#endif
|
||||
|
||||
vec3 horizon_scan_sample_radiance(vec2 uv)
|
||||
{
|
||||
@@ -275,6 +279,7 @@ void horizon_scan_occluder_intersection_ray_sphere_clip(Ray ray,
|
||||
/**
|
||||
* Scans the horizon in many directions and returns the indirect lighting radiance.
|
||||
* Returned lighting is stored inside the context in `_accum` members already normalized.
|
||||
* If `reversed` is set to true, the input normal must be negated.
|
||||
*/
|
||||
void horizon_scan_eval(vec3 vP,
|
||||
inout HorizonScanContext context,
|
||||
@@ -283,7 +288,8 @@ void horizon_scan_eval(vec3 vP,
|
||||
float search_distance,
|
||||
float global_thickness,
|
||||
float angle_bias,
|
||||
const int sample_count)
|
||||
const int sample_count,
|
||||
const bool reversed)
|
||||
{
|
||||
vec3 vV = drw_view_incident_vector(vP);
|
||||
|
||||
@@ -318,33 +324,44 @@ void horizon_scan_eval(vec3 vP,
|
||||
/* Always cross at least one pixel. */
|
||||
float time = 1.0 + square((float(j) + noise.y) / float(sample_count)) * ssray.max_time;
|
||||
|
||||
if (reversed) {
|
||||
/* We need to cross at least 2 pixels to avoid artifacts form the HiZ storing only the
|
||||
* max depth. The HiZ would need to contain the min depth instead to avoid this. */
|
||||
time += 1.0;
|
||||
}
|
||||
|
||||
float lod = 1.0 + (float(j >> 2) / (1.0 + uniform_buf.ao.quality));
|
||||
|
||||
vec2 sample_uv = ssray.origin.xy + ssray.direction.xy * time;
|
||||
float sample_depth = textureLod(hiz_tx, sample_uv * uniform_buf.hiz.uv_scale, lod).r;
|
||||
|
||||
if (sample_depth == 1.0) {
|
||||
if (sample_depth == 1.0 && !reversed) {
|
||||
/* Skip background. Avoids making shadow on the geometry near the far plane. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* TODO(fclem): Re-introduce bias. But this is difficult to do per closure. */
|
||||
bool front_facing = true; // vN.z > 0.0;
|
||||
|
||||
/* Bias depth a bit to avoid self shadowing issues. */
|
||||
const float bias = 2.0 * 2.4e-7;
|
||||
sample_depth += front_facing ? bias : -bias;
|
||||
sample_depth += reversed ? -bias : bias;
|
||||
|
||||
vec3 vP_sample = drw_point_screen_to_view(vec3(sample_uv, sample_depth));
|
||||
vec3 vV_sample = drw_view_incident_vector(vP_sample);
|
||||
|
||||
Ray ray;
|
||||
ray.origin = vP_sample;
|
||||
ray.direction = -vV;
|
||||
ray.direction = -vV_sample;
|
||||
ray.max_time = global_thickness;
|
||||
|
||||
if (reversed) {
|
||||
/* Make the ray start above the surface and end exactly at the surface. */
|
||||
ray.max_time = 2.0 * distance(vP, vP_sample);
|
||||
ray.origin = vP_sample + vV_sample * ray.max_time;
|
||||
ray.direction = -vV_sample;
|
||||
}
|
||||
|
||||
Sphere sphere = shape_sphere(vP, search_distance);
|
||||
|
||||
vec3 vP_front, vP_back;
|
||||
vec3 vP_front = ray.origin, vP_back = ray.origin + ray.direction * ray.max_time;
|
||||
horizon_scan_occluder_intersection_ray_sphere_clip(ray, sphere, vP_front, vP_back);
|
||||
|
||||
vec3 vL_front = normalize(vP_front - vP);
|
||||
|
||||
@@ -232,6 +232,36 @@ float ambient_occlusion_eval(vec3 normal,
|
||||
// clang-format off
|
||||
#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_AMBIENT_OCCLUSION) && !defined(MAT_DEPTH) && !defined(MAT_SHADOW)
|
||||
// clang-format on
|
||||
# if 0 /* TODO(fclem): Finish inverted horizon scan. */
|
||||
/* TODO(fclem): Replace eevee_ambient_occlusion_lib by eevee_horizon_scan_eval_lib when this is
|
||||
* finished. */
|
||||
vec3 vP = drw_point_world_to_view(g_data.P);
|
||||
vec3 vN = drw_normal_world_to_view(normal);
|
||||
|
||||
ivec2 texel = ivec2(gl_FragCoord.xy);
|
||||
vec2 noise;
|
||||
noise.x = interlieved_gradient_noise(vec2(texel), 3.0, 0.0);
|
||||
noise.y = utility_tx_fetch(utility_tx, vec2(texel), UTIL_BLUE_NOISE_LAYER).r;
|
||||
noise = fract(noise + sampling_rng_2D_get(SAMPLING_AO_U));
|
||||
|
||||
ClosureOcclusion occlusion;
|
||||
occlusion.N = (inverted != 0.0) ? -vN : vN;
|
||||
|
||||
HorizonScanContext ctx;
|
||||
ctx.occlusion = occlusion;
|
||||
|
||||
horizon_scan_eval(vP,
|
||||
ctx,
|
||||
noise,
|
||||
uniform_buf.ao.pixel_size,
|
||||
max_distance,
|
||||
uniform_buf.ao.thickness,
|
||||
uniform_buf.ao.angle_bias,
|
||||
10,
|
||||
inverted != 0.0);
|
||||
|
||||
return saturate(ctx.occlusion_result.r);
|
||||
# else
|
||||
vec3 vP = drw_point_world_to_view(g_data.P);
|
||||
ivec2 texel = ivec2(gl_FragCoord.xy);
|
||||
OcclusionData data = ambient_occlusion_search(
|
||||
@@ -245,6 +275,7 @@ float ambient_occlusion_eval(vec3 normal,
|
||||
vec3 unused;
|
||||
ambient_occlusion_eval(data, texel, V, N, Ng, inverted, visibility, unused_error, unused);
|
||||
return visibility;
|
||||
# endif
|
||||
#else
|
||||
return 1.0;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user