EEVEE Next: Ambient Occlusion #108398

Merged
Miguel Pozo merged 29 commits from pragma37/blender:pull-eevee-next-ao into main 2023-06-30 19:37:37 +02:00
12 changed files with 58 additions and 40 deletions
Showing only changes of commit 343b89a5f8 - Show all commits

View File

@ -61,6 +61,10 @@ void AmbientOcclusion::init()
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ;
horizons_tx_.ensure_2d(GPU_RGBA8, inst_.film.render_extent_get(), usage);
/* Compute pixel size. Size is multiplied by 2 because it is applied in NDC [-1..1] range. */
rt_data_.pixel_size = float2(2.0f) / float2(inst_.film.render_extent_get());
pragma37 marked this conversation as resolved Outdated

I'm almost tempted to remove this pass altogether. It might just become a subpass of the raytracing pipeline.

I'm almost tempted to remove this pass altogether. It might just become a subpass of the raytracing pipeline.
rt_data_.push_update();
}
void AmbientOcclusion::sync()

View File

@ -47,6 +47,14 @@ class AmbientOcclusion {
void sync();
void render(View &view);
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
{
inst_.hiz_buffer.bind_resources(pass);
pass->bind_ubo(AO_BUF_SLOT, &data_);
pass->bind_ubo(RAYTRACE_BUF_SLOT, &rt_data_);
pass->bind_texture(AO_HORIZONS_TEX_SLOT, data_.enabled ? &horizons_tx_ : &dummy_horizons_tx_);
}
};
/** \} */

View File

@ -150,6 +150,7 @@ void ForwardPipeline::sync()
inst_.shadows.bind_resources(&opaque_ps_);
inst_.sampling.bind_resources(&opaque_ps_);
inst_.cryptomatte.bind_resources(&opaque_ps_);
inst_.ao.bind_resources(&opaque_ps_);
}
opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided");
@ -175,6 +176,7 @@ void ForwardPipeline::sync()
inst_.lights.bind_resources(&sub);
inst_.shadows.bind_resources(&sub);
inst_.sampling.bind_resources(&sub);
inst_.ao.bind_resources(&sub);
}
}
@ -328,6 +330,7 @@ void DeferredLayer::begin_sync()
inst_.sampling.bind_resources(&gbuffer_ps_);
inst_.cryptomatte.bind_resources(&gbuffer_ps_);
inst_.ao.bind_resources(&gbuffer_ps_);
}
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_EQUAL |
@ -370,6 +373,7 @@ void DeferredLayer::end_sync()
inst_.shadows.bind_resources(&eval_light_ps_);
inst_.sampling.bind_resources(&eval_light_ps_);
inst_.hiz_buffer.bind_resources(&eval_light_ps_);
inst_.ao.bind_resources(&eval_light_ps_);
eval_light_ps_.barrier(GPU_BARRIER_TEXTURE_FETCH | GPU_BARRIER_SHADER_IMAGE_ACCESS);
eval_light_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3);

View File

@ -254,6 +254,13 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu
info.define("MAT_RENDER_PASS_SUPPORT");
}
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_AO) &&
ELEM(pipeline_type, MAT_PIPE_FORWARD, MAT_PIPE_DEFERRED) &&
ELEM(geometry_type, MAT_GEOM_MESH, MAT_GEOM_CURVES))
{
info.define("MAT_AO");
}
if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) {
info.define("MAT_TRANSPARENT");
/* Transparent material do not have any velocity specific pipeline. */

View File

@ -24,21 +24,23 @@ float cone_cosine(float r)
* http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx
*/
#if defined(MESH_SHADER)
/* TODO(Miguel Pozo) */
pragma37 marked this conversation as resolved Outdated

Prefer a function that returns an empty occlusion data.

Prefer a function that returns an empty occlusion data.
#if defined(MAT_GEOM_MESH)
# if !defined(USE_ALPHA_HASH)
# if !defined(DEPTH_SHADER)
# if !defined(USE_ALPHA_BLEND)
# if !defined(MAT_TRANSPARENT)
# if !defined(USE_REFRACTION)
# define ENABLE_DEFERED_AO
# define ENABLE_DEFERRED_AO
# endif
# endif
# endif
# endif
#endif
#ifndef ENABLE_DEFERED_AO
#ifndef ENABLE_DEFERRED_AO
pragma37 marked this conversation as resolved Outdated

Remove these and prefer individual member assignment.

Remove these and prefer individual member assignment.
# if defined(STEP_RESOLVE)
# define ENABLE_DEFERED_AO
# define ENABLE_DEFERRED_AO
# endif
#endif
@ -440,9 +442,9 @@ OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
/* Default to fully opened cone. */
OcclusionData data = NO_OCCLUSION_DATA;
#ifdef ENABLE_DEFERED_AO
if ((ao_buf.settings & AO_ENABLED) != 0) {
data = unpack_occlusion_data(texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0));
#ifdef ENABLE_DEFERRED_AO
if (ao_buf.enabled) {
data = unpack_occlusion_data(texelFetch(horizons_tx, ivec2(gl_FragCoord.xy), 0));
}
#else
/* For blended surfaces. */
@ -457,30 +459,3 @@ OcclusionData occlusion_load(vec3 vP, float custom_occlusion)
#ifndef GPU_FRAGMENT_SHADER
# undef gl_FragCoord
#endif
float ambient_occlusion_eval(vec3 normal,
float max_distance,
const float inverted,
const float sample_count)
{
/* Avoid multiline define causing compiler issues. */
/* clang-format off */
#if defined(GPU_FRAGMENT_SHADER) && (defined(MESH_SHADER) || defined(HAIR_SHADER)) && !defined(DEPTH_SHADER) && !defined(VOLUMETRICS)
/* clang-format on */
vec3 bent_normal;
vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy);
OcclusionData data = occlusion_search(
viewPosition, hiz_tx, max_distance, inverted, sample_count);
vec3 V = cameraVec(worldPosition);
vec3 N = normalize(normal);
vec3 Ng = safe_normalize(cross(dFdx(worldPosition), dFdy(worldPosition)));
float unused_error, visibility;
vec3 unused;
occlusion_eval(data, V, N, Ng, inverted, visibility, unused_error, unused);
return visibility;
#else
return 1.0;
#endif
}

View File

@ -9,6 +9,7 @@
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl)
void main()
{

View File

@ -199,12 +199,25 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac)
}
float ambient_occlusion_eval(vec3 normal,
float distance,
float max_distance,
const float inverted,
const float sample_count)
{
/* TODO */
#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_AO) && !defined(MAT_DEPTH) && !defined(MAT_SHADOW)
vec3 vP = transform_point(ViewMatrix, g_data.P);
OcclusionData data = occlusion_search(vP, hiz_tx, max_distance, inverted, sample_count);
vec3 V = cameraVec(g_data.P);
vec3 N = g_data.N;
vec3 Ng = g_data.Ng;
float unused_error, visibility;
vec3 unused;
occlusion_eval(data, V, N, Ng, inverted, visibility, unused_error, unused);
return visibility;
#else
return 1.0;
#endif
}
#ifndef GPU_METAL

View File

@ -10,6 +10,7 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl)
fclem marked this conversation as resolved Outdated

Why is this needed?

Why is this needed?

Because the AO lib is required by the AO node in the nodetree lib.
But I can’t include the AO lib directly from the nodetree lib since then it ends up also in the depth, shadow and world passes.
AFAIK there’s no way to make a conditional BLENDER_REQUIRE, so the other option would be to put the whole AO lib behind a define (which would be kind of annoying in most code editors).

Because the AO lib is required by the AO node in the nodetree lib. But I can’t include the AO lib directly from the nodetree lib since then it ends up also in the depth, shadow and world passes. AFAIK there’s no way to make a conditional BLENDER_REQUIRE, so the other option would be to put the whole AO lib behind a define (which would be kind of annoying in most code editors).
#pragma BLENDER_REQUIRE(eevee_surf_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)

View File

@ -8,6 +8,7 @@
#pragma BLENDER_REQUIRE(common_hair_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)

View File

@ -9,7 +9,7 @@ GPU_SHADER_CREATE_INFO(eevee_raytrace_lib)
GPU_SHADER_CREATE_INFO(eevee_ao_lib)
.additional_info("eevee_raytrace_lib", "eevee_utility_texture")
.sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_buffer_tx")
.sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx")
.uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf");
GPU_SHADER_CREATE_INFO(eevee_ao)

View File

@ -41,6 +41,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light)
"eevee_deferred_base",
"eevee_hiz_data",
"eevee_render_pass_out",
"eevee_ao_lib",
"draw_view",
"draw_fullscreen")
.do_static_compilation(true);

View File

@ -108,7 +108,8 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred)
"eevee_utility_texture",
"eevee_sampling_data",
"eevee_render_pass_out",
"eevee_cryptomatte_out");
"eevee_cryptomatte_out",
"eevee_ao_lib");
GPU_SHADER_CREATE_INFO(eevee_surf_forward)
.vertex_out(eevee_surf_iface)
@ -122,7 +123,8 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward)
"eevee_camera",
"eevee_utility_texture",
"eevee_sampling_data",
"eevee_shadow_data"
"eevee_shadow_data",
"eevee_ao_lib"
/* Optionally added depending on the material. */
// "eevee_render_pass_out",
// "eevee_cryptomatte_out",
@ -131,6 +133,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward)
);
GPU_SHADER_CREATE_INFO(eevee_surf_depth)
.define("MAT_DEPTH")
.vertex_out(eevee_surf_iface)
.fragment_source("eevee_surf_depth_frag.glsl")
.additional_info("eevee_sampling_data", "eevee_camera", "eevee_utility_texture");