From 414851306d7b9647ad8aadc90cc3e43a3c305a95 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 26 May 2023 20:19:26 +0200 Subject: [PATCH 01/25] AO port initial state --- scripts/startup/bl_ui/properties_render.py | 30 ++ source/blender/draw/CMakeLists.txt | 5 + .../draw/engines/eevee_next/eevee_ao.cc | 102 ++++ .../draw/engines/eevee_next/eevee_ao.hh | 54 ++ .../draw/engines/eevee_next/eevee_defines.hh | 3 + .../draw/engines/eevee_next/eevee_instance.cc | 2 + .../draw/engines/eevee_next/eevee_instance.hh | 3 + .../draw/engines/eevee_next/eevee_pipeline.cc | 1 + .../draw/engines/eevee_next/eevee_shader.cc | 5 + .../draw/engines/eevee_next/eevee_shader.hh | 5 +- .../engines/eevee_next/eevee_shader_shared.hh | 33 ++ .../draw/engines/eevee_next/eevee_view.cc | 1 + .../eevee_next/shaders/eevee_ao_frag.glsl | 108 ++++ .../eevee_next/shaders/eevee_ao_lib.glsl | 486 ++++++++++++++++++ .../shaders/eevee_raytrace_lib.glsl | 254 +++++++++ .../eevee_next/shaders/infos/eevee_ao_info.hh | 21 + source/blender/gpu/CMakeLists.txt | 1 + 17 files changed, 1113 insertions(+), 1 deletion(-) create mode 100644 source/blender/draw/engines/eevee_next/eevee_ao.cc create mode 100644 source/blender/draw/engines/eevee_next/eevee_ao.hh create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl create mode 100644 source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index bf3c322f377..422b6571d87 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -142,6 +142,35 @@ class RENDER_PT_eevee_ambient_occlusion(RenderButtonsPanel, Panel): col.prop(props, "use_gtao_bounce") +class RENDER_PT_eevee_next_ambient_occlusion(RenderButtonsPanel, Panel): + bl_label = "Ambient Occlusion" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'} + + @classmethod + def poll(cls, context): + return (context.engine in cls.COMPAT_ENGINES) + + def draw_header(self, context): + scene = context.scene + props = scene.eevee + self.layout.prop(props, "use_gtao", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + scene = context.scene + props = scene.eevee + + layout.active = props.use_gtao + col = layout.column() + col.prop(props, "gtao_distance") + col.prop(props, "gtao_factor") + col.prop(props, "gtao_quality") + col.prop(props, "use_gtao_bent_normals") + col.prop(props, "use_gtao_bounce") + + class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel): bl_label = "Motion Blur" bl_options = {'DEFAULT_CLOSED'} @@ -888,6 +917,7 @@ classes = ( RENDER_PT_eevee_sampling, RENDER_PT_eevee_next_sampling, RENDER_PT_eevee_ambient_occlusion, + RENDER_PT_eevee_next_ambient_occlusion, RENDER_PT_eevee_bloom, RENDER_PT_eevee_depth_of_field, RENDER_PT_eevee_next_depth_of_field, diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index b5f018a5f09..59f356da3a5 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -138,6 +138,7 @@ set(SRC engines/eevee/eevee_subsurface.c engines/eevee/eevee_temporal_sampling.c engines/eevee/eevee_volumes.c + engines/eevee_next/eevee_ao.cc engines/eevee_next/eevee_camera.cc engines/eevee_next/eevee_cryptomatte.cc engines/eevee_next/eevee_depth_of_field.cc @@ -277,6 +278,7 @@ set(SRC engines/eevee/eevee_lut.h engines/eevee/eevee_private.h engines/eevee/engine_eevee_shared_defines.h + engines/eevee_next/eevee_ao.hh engines/eevee_next/eevee_camera.hh engines/eevee_next/eevee_cryptomatte.hh engines/eevee_next/eevee_depth_of_field.hh @@ -434,6 +436,8 @@ set(GLSL_SRC engines/eevee/shaders/infos/engine_eevee_legacy_shared.h engines/eevee/engine_eevee_shared_defines.h + engines/eevee_next/shaders/eevee_ao_frag.glsl + engines/eevee_next/shaders/eevee_ao_lib.glsl engines/eevee_next/shaders/eevee_attributes_lib.glsl engines/eevee_next/shaders/eevee_camera_lib.glsl engines/eevee_next/shaders/eevee_colorspace_lib.glsl @@ -482,6 +486,7 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_motion_blur_gather_comp.glsl engines/eevee_next/shaders/eevee_motion_blur_lib.glsl engines/eevee_next/shaders/eevee_nodetree_lib.glsl + engines/eevee_next/shaders/eevee_raytrace_lib.glsl engines/eevee_next/shaders/eevee_sampling_lib.glsl engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl engines/eevee_next/shaders/eevee_shadow_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc new file mode 100644 index 00000000000..9c0aee07170 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eevee + * + * Ground Truth Ambient Occlusion + * + */ + +/** + * Occlusion Algorithm Overview: + * + * We separate the computation into 2 steps. + * + * - First we scan the neighborhood pixels to find the maximum horizon angle. + * We save this angle in a RG8 array texture. + * + * - Then we use this angle to compute occlusion with the shading normal at + * the shading stage. This let us do correct shadowing for each diffuse / specular + * lobe present in the shader using the correct normal. + */ + +#pragma once + +#include "eevee_ao.hh" +#include "eevee_instance.hh" + +#include "GPU_capabilities.h" + +namespace blender::eevee { + +/* -------------------------------------------------------------------- */ +/** \name AmbientOcclusion + * \{ */ + +void AmbientOcclusion::init() +{ + dummy_horizons_tx_.ensure_2d( + GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ, float4(0)); + + debug_ = G.debug_value == 6; + + const Scene *scene = inst_.scene; + data_.enabled = (scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) || + (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO); + + if (!data_.enabled) { + /* Early return. */ + data_.push_update(); + horizons_tx_.free(); + return; + } + + data_.distance = scene->eevee.gtao_distance; + data_.factor = std::max(1e-4f, scene->eevee.gtao_factor); + data_.quality = scene->eevee.gtao_quality; + data_.use_bent_normals = scene->eevee.flag & SCE_EEVEE_GTAO_BENT_NORMALS; + data_.bounce_factor = (scene->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; + + data_.push_update(); + + eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ; + horizons_tx_.ensure_2d(GPU_RGBA8, inst_.film.render_extent_get(), usage); +} + +void AmbientOcclusion::sync() +{ + if (!data_.enabled) { + return; + } + + horizons_search_ps_.init(); + horizons_search_ps_.state_set(DRW_STATE_WRITE_COLOR); + horizons_search_ps_.shader_set(inst_.shaders.static_shader_get(AO)); + horizons_search_ps_.bind_ubo(RAYTRACE_BUF_SLOT, &rt_data_); + horizons_search_ps_.bind_ubo(AO_BUF_SLOT, &data_); + horizons_search_ps_.bind_texture("utility_tx", &inst_.pipelines.utility_tx); + inst_.hiz_buffer.bind_resources(&horizons_search_ps_); + + horizons_search_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3); +} + +void AmbientOcclusion::render(View &view) +{ + if (!data_.enabled) { + return; + } + + inst_.hiz_buffer.update(); + + fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(horizons_tx_)); + inst_.manager->submit(horizons_search_ps_, view); + + if (GPU_mip_render_workaround() || + GPU_type_matches_ex(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) + { + /* Fix dot corruption on intel HD5XX/HD6XX series. */ + GPU_flush(); + } +} + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh new file mode 100644 index 00000000000..a3b3abc454a --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eevee + * + * Ground Truth Ambient Occlusion + * + */ + +#pragma once + +#include "eevee_shader_shared.hh" + +namespace blender::eevee { + +class Instance; + +/* -------------------------------------------------------------------- */ +/** \name AmbientOcclusion + * \{ */ + +class AmbientOcclusion { + private: + class Instance &inst_; + + bool debug_; + + /* TODO: Move somewhere else. */ + UniformBuffer rt_data_; + + UniformBuffer data_; + + Texture dummy_horizons_tx_; + Texture horizons_tx_; + Texture horizons_debug_tx_; + + Framebuffer fb_ = {"GTAO"}; + + PassSimple horizons_search_ps_ = {"GTAO Horizons Search"}; + + public: + AmbientOcclusion(Instance &inst) : inst_(inst){}; + ~AmbientOcclusion(){}; + + void init(); + + void sync(); + + void render(View &view); +}; + +/** \} */ + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index 98c4b4b72bc..c9ca47fae68 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -96,6 +96,7 @@ /* Only during shadow rendering. */ #define SHADOW_RENDER_MAP_SLOT 13 #define RBUFS_UTILITY_TEX_SLOT 14 +#define AO_HORIZONS_TEX_SLOT 15 /* Images. */ #define RBUFS_COLOR_SLOT 0 @@ -112,6 +113,8 @@ #define CAMERA_BUF_SLOT 6 #define RBUFS_BUF_SLOT 7 +#define RAYTRACE_BUF_SLOT 8 +#define AO_BUF_SLOT 9 /* Storage Buffers. */ #define LIGHT_CULL_BUF_SLOT 0 diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 8d79f27e126..27080a83837 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -66,6 +66,7 @@ void Instance::init(const int2 &output_res, sampling.init(scene); camera.init(); film.init(output_res, output_rect); + ao.init(); velocity.init(); depth_of_field.init(); shadows.init(); @@ -116,6 +117,7 @@ void Instance::begin_sync() depth_of_field.sync(); motion_blur.sync(); hiz_buffer.sync(); + ao.sync(); main_view.sync(); world.sync(); film.sync(); diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 3a6f9bf38f8..546585e1850 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -16,6 +16,7 @@ #include "DNA_lightprobe_types.h" #include "DRW_render.h" +#include "eevee_ao.hh" #include "eevee_camera.hh" #include "eevee_cryptomatte.hh" #include "eevee_depth_of_field.hh" @@ -52,6 +53,7 @@ class Instance { PipelineModule pipelines; ShadowModule shadows; LightModule lights; + AmbientOcclusion ao; VelocityModule velocity; MotionBlurModule motion_blur; DepthOfField depth_of_field; @@ -98,6 +100,7 @@ class Instance { pipelines(*this), shadows(*this), lights(*this), + ao(*this), velocity(*this), motion_blur(*this), depth_of_field(*this), diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index a93a8288ab5..2f277e8ac50 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -410,6 +410,7 @@ void DeferredLayer::render(View &view, inst_.hiz_buffer.set_dirty(); inst_.shadows.set_view(view); + inst_.ao.render(view); inst_.gbuffer.acquire(extent, closure_bits_); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index bb34674dbf5..850ea6f451d 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -81,6 +81,11 @@ ShaderModule::~ShaderModule() const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_type) { switch (shader_type) { + case AO: + return "eevee_ao"; + case AO_DEBUG: + /* TODO */ + return "eevee_ao"; case FILM_FRAG: return "eevee_film_frag"; case FILM_COMP: diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index a2977b697c1..fadc0444117 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -27,7 +27,10 @@ namespace blender::eevee { /* Keep alphabetical order and clean prefix. */ enum eShaderType { - FILM_FRAG = 0, + AO = 0, + AO_DEBUG, + + FILM_FRAG, FILM_COMP, FILM_CRYPTOMATTE_POST, diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 7f449ee471b..75dcc834224 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -884,8 +884,41 @@ enum eClosureBits : uint32_t { CLOSURE_AMBIENT_OCCLUSION = (1u << 12u), }; +struct RayTracingData { + float2 pixel_size; + float quality; + float thickness; + float border_factor; /* This is the only one used */ + float max_roughness; + float firefly_factor; + float brdf_bias; + bool1 toggle; + int _pad0; + int _pad1; + int _pad2; +}; +BLI_STATIC_ASSERT_ALIGN(RayTracingData, 16) + /** \} */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Ambient Occlussion + * \{ */ + +struct AOData { + bool1 enabled; + bool1 use_bent_normals; + float distance; + float factor; + float bounce_factor; + float quality; + int _pad0; + int _pad1; +}; +BLI_STATIC_ASSERT_ALIGN(AOData, 16) + /* -------------------------------------------------------------------- */ /** \name Subsurface * \{ */ diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index 27b6a3aed2a..f19260c6066 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -124,6 +124,7 @@ void ShadingView::render() /* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */ inst_.lights.set_view(render_view_new_, extent_); + /* TODO(Miguel Pozo): Deferred and forward prepass should happen before the GBuffer pass. */ inst_.pipelines.deferred.render(render_view_new_, prepass_fb_, combined_fb_, extent_); // inst_.lightprobes.draw_cache_display(); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl new file mode 100644 index 00000000000..bd1f071cb43 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl @@ -0,0 +1,108 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) + +/** + * This shader only compute maximum horizon angles for each directions. + * The final integration is done at the resolve stage with the shading normal. + */ + +/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. + * This samples the depth buffer 4 time for each direction to get the most correct + * implicit normal reconstruction out of the depth buffer. */ +vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float depth_center) +{ + vec2 uv1 = uvs - ofs * 2.0; + vec2 uv2 = uvs - ofs; + vec2 uv3 = uvs + ofs; + vec2 uv4 = uvs + ofs * 2.0; + vec4 H; + H.x = textureLod(hiz_tx, uv1, 0.0).r; + H.y = textureLod(hiz_tx, uv2, 0.0).r; + H.z = textureLod(hiz_tx, uv3, 0.0).r; + H.w = textureLod(hiz_tx, uv4, 0.0).r; + /* Fix issue with depth precision. Take even larger diff. */ + vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); + if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { + return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); + } + /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ + vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); + if (deltas.x < deltas.y) { + return vP - get_view_space_from_depth(uv2, H.y); + } + else { + return get_view_space_from_depth(uv3, H.z) - vP; + } +} + +/* TODO(@fclem): port to a common place for other effects to use. */ +bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg) +{ + vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y))); + float depth_center = textureLod(hiz_tx, uvs, 0.0).r; + + vP = get_view_space_from_depth(uvs, depth_center); + + vec3 dPdx = view_position_derivative_from_depth(uvs, texel_size * vec2(1, 0), vP, depth_center); + vec3 dPdy = view_position_derivative_from_depth(uvs, texel_size * vec2(0, 1), vP, depth_center); + + vNg = safe_normalize(cross(dPdx, dPdy)); + + /* Background case. */ + if (depth_center == 1.0) { + return false; + } + + return true; +} + +#ifdef DEBUG_AO + +void main() +{ + vec3 vP, vNg; + vec2 uvs = uvcoordsvar.xy; + + if (!reconstruct_view_position_and_normal_from_depth(uvs * hiz_buf.uv_scale, vP, vNg)) { + /* Handle Background case. Prevent artifact due to uncleared Horizon Render Target. */ + FragColor = vec4(0.0); + } + else { + vec3 P = transform_point(ViewMatrixInverse, vP); + vec3 V = cameraVec(P); + vec3 vV = viewCameraVec(vP); + vec3 vN = normal_decode(texture(normalBuffer, uvs).rg, vV); + vec3 N = transform_direction(ViewMatrixInverse, vN); + vec3 Ng = transform_direction(ViewMatrixInverse, vNg); + + OcclusionData data = occlusion_load(vP, 1.0); + + if (min_v4(abs(data.horizons)) != M_PI) { + FragColor = vec4(diffuse_occlusion(data, V, N, Ng)); + } + else { + FragColor = vec4(1.0); + } + } +} + +#else + +void main() +{ + vec2 uvs = uvcoordsvar.xy; + float depth = textureLod(hiz_tx, uvs * hiz_buf.uv_scale, 0.0).r; + vec3 vP = get_view_space_from_depth(uvs, depth); + + OcclusionData data = NO_OCCLUSION_DATA; + /* Do not trace for background */ + if (depth != 1.0) { + data = occlusion_search(vP, hiz_tx, ao_buf.distance, 0.0, 8.0); + } + + out_horizons = pack_occlusion_data(data); +} +#endif diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl new file mode 100644 index 00000000000..6e5227e0e79 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -0,0 +1,486 @@ + +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_raytrace_lib.glsl) + +/* TODO(Miguel Pozo): Move somewhere else. */ + +/* Return a fitted cone angle given the input roughness */ +float cone_cosine(float r) +{ + /* Using phong gloss + * roughness = sqrt(2/(gloss+2)) */ + float gloss = -2 + 2 / (r * r); + /* Drobot 2014 in GPUPro5 */ + // return cos(2.0 * sqrt(2.0 / (gloss + 2))); + /* Uludag 2014 in GPUPro5 */ + // return pow(0.244, 1 / (gloss + 1)); + /* Jimenez 2016 in Practical Realtime Strategies for Accurate Indirect Occlusion. */ + return exp2(-3.32193 * r * r); +} + +/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx + */ + +#if defined(MESH_SHADER) +# if !defined(USE_ALPHA_HASH) +# if !defined(DEPTH_SHADER) +# if !defined(USE_ALPHA_BLEND) +# if !defined(USE_REFRACTION) +# define ENABLE_DEFERED_AO +# endif +# endif +# endif +# endif +#endif + +#ifndef ENABLE_DEFERED_AO +# if defined(STEP_RESOLVE) +# define ENABLE_DEFERED_AO +# endif +#endif + +#ifndef GPU_FRAGMENT_SHADER +# define gl_FragCoord vec4(0.0) +#endif + +#define NO_OCCLUSION_DATA OcclusionData(vec4(M_PI, -M_PI, M_PI, -M_PI), 1.0) + +struct OcclusionData { + /* 4 horizons angles, one in each direction around the view vector to form a cross pattern. */ + vec4 horizons; + /* Custom large scale occlusion. */ + float custom_occlusion; + +#ifdef GPU_METAL + /* Constructors required for OcclusionData(..) syntax. */ + inline OcclusionData() = default; + inline OcclusionData(vec4 in_horizons, float in_custom_occlusion) + : horizons(in_horizons), custom_occlusion(in_custom_occlusion) + { + } +#endif +}; + +vec4 pack_occlusion_data(OcclusionData data) +{ + return vec4(1.0 - data.horizons * vec4(1, -1, 1, -1) * M_1_PI); +} + +OcclusionData unpack_occlusion_data(vec4 v) +{ + return OcclusionData((1.0 - v) * vec4(1, -1, 1, -1) * M_PI, 0.0); +} + +vec2 get_ao_noise(void) +{ + vec2 noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy, UTIL_BLUE_NOISE_LAYER).xy; + + /* Decorrelate noise from AA. */ + /* TODO(@fclem): we should use a more general approach for more random number dimensions. */ + noise = fract(noise * 6.1803402007); + return noise; +} + +vec2 get_ao_dir(float jitter) +{ + /* Only a quarter of a turn because we integrate using 2 slices. + * We use this instead of using utiltex circle noise to improve cache hits + * since all tracing direction will be in the same quadrant. */ + jitter *= M_PI_2; + return vec2(cos(jitter), sin(jitter)); +} + +/* Certain intel drivers on macOS lose precision, resulting in rendering artifacts, + * when using standard pow(A, B) function. + * Using logarithmic identity provides higher precision results. */ +#if defined(GPU_INTEL) && defined(OS_MAC) +float occlusion_pow(float a, float b) +{ + return exp(b * log(a)); +} +#else +float occlusion_pow(float a, float b) +{ + return pow(a, b); +} +#endif + +/* Return horizon angle cosine. */ +float search_horizon(vec3 vI, + vec3 vP, + float noise, + ScreenSpaceRay ssray, + sampler2D depth_tx, + const float inverted, + float radius, + const float sample_count) +{ + /* Init at cos(M_PI). */ + float h = (inverted != 0.0) ? 1.0 : -1.0; + + ssray.max_time -= 1.0; + + if (ssray.max_time <= 2.0) { + /* Produces self shadowing under this threshold. */ + return fast_acos(h); + } + + float prev_time, time = 0.0; + for (float iter = 0.0; time < ssray.max_time && iter < sample_count; iter++) { + prev_time = time; + /* Gives us good precision at center and ensure we cross at least one pixel per iteration. */ + time = 1.0 + iter + sqr((iter + noise) / sample_count) * ssray.max_time; + float stride = time - prev_time; + float lod = (log2(stride) - noise) / (1.0 + ao_buf.quality); + + vec2 uv = ssray.origin.xy + ssray.direction.xy * time; + float depth = textureLod(depth_tx, uv * hiz_buf.uv_scale, floor(lod)).r; + + if (depth == 1.0 && inverted == 0.0) { + /* Skip background. Avoids making shadow on the geometry near the far plane. */ + continue; + } + + /* Bias depth a bit to avoid self shadowing issues. */ + 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; + float len = length(omega_s); + /* Sample's horizon angle cosine. */ + float s_h = dot(vI, omega_s / len); + /* Blend weight to fade artifacts. */ + float dist_ratio = abs(len) / radius; + /* Sphere falloff. */ + float dist_fac = sqr(saturate(dist_ratio)); + /* Unbiased, gives too much hard cut behind objects */ + // float dist_fac = step(0.999, dist_ratio); + + if (inverted != 0.0) { + h = min(h, s_h); + } + else { + h = mix(max(h, s_h), h, dist_fac); + } + } + return fast_acos(h); +} + +OcclusionData occlusion_search( + vec3 vP, sampler2D depth_tx, float radius, const float inverted, const float dir_sample_count) +{ + if (!ao_buf.enabled) { + return NO_OCCLUSION_DATA; + } + + vec2 noise = get_ao_noise(); + vec2 dir = get_ao_dir(noise.x); + vec2 uv = get_uvs_from_view(vP); + vec3 vI = ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)); + vec3 avg_dir = vec3(0.0); + float avg_apperture = 0.0; + + OcclusionData data = (inverted != 0.0) ? OcclusionData(vec4(0, 0, 0, 0), 1.0) : + NO_OCCLUSION_DATA; + + for (int i = 0; i < 2; i++) { + Ray ray; + ray.origin = vP; + ray.direction = vec3(dir * radius, 0.0); + + ScreenSpaceRay ssray; + + ssray = raytrace_screenspace_ray_create(ray); + data.horizons[0 + i * 2] = search_horizon( + vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); + + ray.direction = -ray.direction; + + ssray = raytrace_screenspace_ray_create(ray); + data.horizons[1 + i * 2] = -search_horizon( + vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); + + /* Rotate 90 degrees. */ + dir = vec2(-dir.y, dir.x); + } + + return data; +} + +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 float visibility_error, + out vec3 bent_normal) +{ + /* No error by default. */ + visibility_error = 1.0; + + if (!ao_buf.enabled) { + visibility = data.custom_occlusion; + bent_normal = N; + return; + } + + bool early_out = (inverted != 0.0) ? (max_v4(abs(data.horizons)) == 0.0) : + (min_v4(abs(data.horizons)) == M_PI); + if (early_out) { + visibility = saturate(dot(N, Ng) * 0.5 + 0.5); + visibility = min(visibility, data.custom_occlusion); + + if (!ao_buf.use_bent_normals) { + bent_normal = N; + } + else { + bent_normal = safe_normalize(N + Ng); + } + return; + } + + vec2 noise = get_ao_noise(); + vec2 dir = get_ao_dir(noise.x); + + visibility_error = 0.0; + visibility = 0.0; + bent_normal = N * 0.001; + + for (int i = 0; i < 2; i++) { + vec3 T = transform_direction(ViewMatrixInverse, vec3(dir, 0.0)); + /* Setup integration domain around V. */ + vec3 B = normalize(cross(V, T)); + T = normalize(cross(B, V)); + + float proj_N_len; + vec3 proj_N = normalize_len(N - B * dot(N, B), proj_N_len); + vec3 proj_Ng = normalize(Ng - B * dot(Ng, B)); + + vec2 h = (i == 0) ? data.horizons.xy : data.horizons.zw; + + float N_sin = dot(proj_N, T); + float Ng_sin = dot(proj_Ng, T); + float N_cos = saturate(dot(proj_N, V)); + float Ng_cos = saturate(dot(proj_Ng, V)); + /* 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); + /* Clamp horizons to hemisphere around shading normal. */ + 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. + * Also modulate by projected normal length to reduce issues with slanted surfaces. + * All of this is ad-hoc and not really grounded. */ + bent_normal += proj_N_len * (T * sin(bent_angle) + V * 0.5 * cos(bent_angle)); + + /* 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_horizons_to_hemisphere(h, angle_Ng, inverted); + + /* Inner integral (Eq. 7). */ + 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; + /* Using a very low number of slices (2) leads to over-darkening of surfaces orthogonal to + * the view. This is particularly annoying for sharp reflections occlusion. So we compute how + * much the error is and correct the visibility later. */ + visibility_error += proj_N_len; + + /* Rotate 90 degrees. */ + dir = vec2(-dir.y, dir.x); + } + /* We integrated 2 directions. */ + visibility *= 0.5; + visibility_error *= 0.5; + + visibility = min(visibility, data.custom_occlusion); + + if (!ao_buf.use_bent_normals) { + bent_normal = N; + } + else { + /* NOTE: using pow(visibility, 6.0) produces NaN (see #87369). */ + float tmp = saturate(pow6(visibility)); + bent_normal = normalize(mix(bent_normal, N, tmp)); + } +} + +/* Multibounce approximation base on surface albedo. + * Page 78 in the .pdf version. */ +float gtao_multibounce(float visibility, vec3 albedo) +{ + if (ao_buf.bounce_factor == 0.0) { + return visibility; + } + + /* Median luminance. Because Colored multibounce looks bad. */ + float lum = dot(albedo, vec3(0.3333)); + + float a = 2.0404 * lum - 0.3324; + float b = -4.7951 * lum + 0.6417; + float c = 2.7552 * lum + 0.6903; + + float x = visibility; + return max(x, ((x * a + b) * x + c) * x); +} + +float diffuse_occlusion(OcclusionData data, vec3 V, vec3 N, vec3 Ng) +{ + vec3 unused; + float unused_error; + float visibility; + occlusion_eval(data, V, N, Ng, 0.0, visibility, unused_error, unused); + /* Scale by user factor */ + visibility = occlusion_pow(saturate(visibility), ao_buf.factor); + return visibility; +} + +float diffuse_occlusion( + OcclusionData data, vec3 V, vec3 N, vec3 Ng, vec3 albedo, out vec3 bent_normal) +{ + float visibility; + float unused_error; + occlusion_eval(data, V, N, Ng, 0.0, visibility, unused_error, bent_normal); + + visibility = gtao_multibounce(visibility, albedo); + /* Scale by user factor */ + visibility = occlusion_pow(saturate(visibility), ao_buf.factor); + return visibility; +} + +/** + * Approximate the area of intersection of two spherical caps + * radius1 : First cap’s radius (arc length in radians) + * radius2 : Second caps’ radius (in radians) + * dist : Distance between caps (radians between centers of caps) + * NOTE: Result is divided by pi to save one multiply. + */ +float spherical_cap_intersection(float radius1, float radius2, float dist) +{ + /* From "Ambient Aperture Lighting" by Chris Oat + * Slide 15. */ + float max_radius = max(radius1, radius2); + float min_radius = min(radius1, radius2); + float sum_radius = radius1 + radius2; + float area; + if (dist <= max_radius - min_radius) { + /* One cap in completely inside the other */ + area = 1.0 - cos(min_radius); + } + else if (dist >= sum_radius) { + /* No intersection exists */ + area = 0; + } + else { + float diff = max_radius - min_radius; + area = smoothstep(0.0, 1.0, 1.0 - saturate((dist - diff) / (sum_radius - diff))); + area *= 1.0 - cos(min_radius); + } + return area; +} + +float specular_occlusion( + OcclusionData data, vec3 V, vec3 N, float roughness, inout vec3 specular_dir) +{ + vec3 visibility_dir; + float visibility_error; + float visibility; + occlusion_eval(data, V, N, N, 0.0, visibility, visibility_error, visibility_dir); + + /* Correct visibility error for very sharp surfaces. */ + visibility *= mix(safe_rcp(visibility_error), 1.0, roughness); + + specular_dir = normalize(mix(specular_dir, visibility_dir, roughness * (1.0 - visibility))); + + /* Visibility to cone angle (eq. 18). */ + float vis_angle = fast_acos(sqrt(1 - visibility)); + /* Roughness to cone angle (eq. 26). */ + float spec_angle = max(0.00990998744964599609375, fast_acos(cone_cosine(roughness))); + /* Angle between cone axes. */ + float cone_cone_dist = fast_acos(saturate(dot(visibility_dir, specular_dir))); + float cone_nor_dist = fast_acos(saturate(dot(N, specular_dir))); + + float isect_solid_angle = spherical_cap_intersection(vis_angle, spec_angle, cone_cone_dist); + float specular_solid_angle = spherical_cap_intersection(M_PI_2, spec_angle, cone_nor_dist); + float specular_occlusion = isect_solid_angle / specular_solid_angle; + /* Mix because it is unstable in unoccluded areas. */ + float tmp = saturate(pow8(visibility)); + visibility = mix(specular_occlusion, 1.0, tmp); + + /* Scale by user factor */ + visibility = occlusion_pow(saturate(visibility), ao_buf.factor); + return visibility; +} + +/* Use the right occlusion. */ +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)); + } +#else + /* For blended surfaces. */ + data = occlusion_search(vP, hiz_tx, ao_buf.distance, 0.0, 8.0); +#endif + + data.custom_occlusion = custom_occlusion; + + return data; +} + +#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 +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl new file mode 100644 index 00000000000..c4f93fd5f6c --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl @@ -0,0 +1,254 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +/* Fix for #104266 wherein AMD GPUs running Metal erroneously discard a successful hit. */ +#if defined(GPU_METAL) && defined(GPU_ATI) +# define METAL_AMD_RAYTRACE_WORKAROUND 1 +#endif + +/** + * Screen-Space Raytracing functions. + */ + +struct Ray { + vec3 origin; + /* Ray direction premultiplied by its maximum length. */ + vec3 direction; +}; + +/* Inputs expected to be in viewspace. */ +void raytrace_clip_ray_to_near_plane(inout Ray ray) +{ + float near_dist = get_view_z_from_depth(0.0); + if ((ray.origin.z + ray.direction.z) > near_dist) { + ray.direction *= abs((near_dist - ray.origin.z) / ray.direction.z); + } +} + +/* Screenspace ray ([0..1] "uv" range) where direction is normalize to be as small as one + * full-resolution pixel. The ray is also clipped to all frustum sides. + */ +struct ScreenSpaceRay { + vec4 origin; + vec4 direction; + float max_time; +}; + +void raytrace_screenspace_ray_finalize(inout ScreenSpaceRay ray) +{ + /* Constant bias (due to depth buffer precision). Helps with self intersection. */ + /* Magic numbers for 24bits of precision. + * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */ + const float bias = -2.4e-7 * 2.0; + ray.origin.zw += bias; + ray.direction.zw += bias; + + ray.direction -= ray.origin; + /* If the line is degenerate, make it cover at least one pixel + * to not have to handle zero-pixel extent as a special case later */ + if (len_squared(ray.direction.xy) < 0.00001) { + ray.direction.xy = vec2(0.0, 0.00001); + } + float ray_len_sqr = len_squared(ray.direction.xyz); + /* Make ray.direction cover one pixel. */ + bool is_more_vertical = abs(ray.direction.x / rt_buf.pixel_size.x) < + abs(ray.direction.y / rt_buf.pixel_size.y); + ray.direction /= (is_more_vertical) ? abs(ray.direction.y) : abs(ray.direction.x); + ray.direction *= (is_more_vertical) ? rt_buf.pixel_size.y : rt_buf.pixel_size.x; + /* Clip to segment's end. */ + ray.max_time = sqrt(ray_len_sqr * safe_rcp(len_squared(ray.direction.xyz))); + /* Clipping to frustum sides. */ + float clip_dist = line_unit_box_intersect_dist_safe(ray.origin.xyz, ray.direction.xyz); + ray.max_time = min(ray.max_time, clip_dist); + /* Convert to texture coords [0..1] range. */ + ray.origin = ray.origin * 0.5 + 0.5; + ray.direction *= 0.5; +} + +ScreenSpaceRay raytrace_screenspace_ray_create(Ray ray) +{ + ScreenSpaceRay ssray; + ssray.origin.xyz = project_point(ProjectionMatrix, ray.origin); + ssray.direction.xyz = project_point(ProjectionMatrix, ray.origin + ray.direction); + + raytrace_screenspace_ray_finalize(ssray); + return ssray; +} + +ScreenSpaceRay raytrace_screenspace_ray_create(Ray ray, float thickness) +{ + ScreenSpaceRay ssray; + ssray.origin.xyz = project_point(ProjectionMatrix, ray.origin); + ssray.direction.xyz = project_point(ProjectionMatrix, ray.origin + ray.direction); + /* Interpolate thickness in screen space. + * Calculate thickness further away to avoid near plane clipping issues. */ + ssray.origin.w = get_depth_from_view_z(ray.origin.z - thickness) * 2.0 - 1.0; + ssray.direction.w = get_depth_from_view_z(ray.origin.z + ray.direction.z - thickness) * 2.0 - + 1.0; + + raytrace_screenspace_ray_finalize(ssray); + return ssray; +} + +struct RayTraceParameters { + /** ViewSpace thickness the objects. */ + float thickness; + /** Jitter along the ray to avoid banding artifact when steps are too large. */ + float jitter; + /** Determine how fast the sample steps are getting bigger. */ + float trace_quality; + /** Determine how we can use lower depth mipmaps to make the tracing faster. */ + float roughness; +}; + +/* Returns true on hit. */ +/* TODO(fclem): remove the back-face check and do it the SSR resolve code. */ +bool raytrace(Ray ray, + RayTraceParameters params, + const bool discard_backface, + const bool allow_self_intersection, + out vec3 hit_position) +{ + /* Clip to near plane for perspective view where there is a singularity at the camera origin. */ + if (ProjectionMatrix[3][3] == 0.0) { + raytrace_clip_ray_to_near_plane(ray); + } + + ScreenSpaceRay ssray = raytrace_screenspace_ray_create(ray, params.thickness); + /* Avoid no iteration. */ + if (!allow_self_intersection && ssray.max_time < 1.1) { + hit_position = ssray.origin.xyz + ssray.direction.xyz; + return false; + } + + ssray.max_time = max(1.1, ssray.max_time); + + float prev_delta = 0.0, prev_time = 0.0; + float depth_sample = get_depth_from_view_z(ray.origin.z); + float delta = depth_sample - ssray.origin.z; + + float lod_fac = saturate(fast_sqrt(params.roughness) * 2.0 - 0.4); + + /* Cross at least one pixel. */ + float t = 1.001, time = 1.001; + bool hit = false; +#ifdef METAL_AMD_RAYTRACE_WORKAROUND + bool hit_failsafe = true; +#endif + const float max_steps = 255.0; + for (float iter = 1.0; !hit && (time < ssray.max_time) && (iter < max_steps); iter++) { + float stride = 1.0 + iter * params.trace_quality; + float lod = log2(stride) * lod_fac; + + prev_time = time; + prev_delta = delta; + + time = min(t + stride * params.jitter, ssray.max_time); + t += stride; + + vec4 ss_p = ssray.origin + ssray.direction * time; + depth_sample = textureLod(hiz_tx, ss_p.xy * hiz_buf.uv_scale, floor(lod)).r; + + delta = depth_sample - ss_p.z; + /* Check if the ray is below the surface ... */ + hit = (delta < 0.0); + /* ... and above it with the added thickness. */ + hit = hit && (delta > ss_p.z - ss_p.w || abs(delta) < abs(ssray.direction.z * stride * 2.0)); + +#ifdef METAL_AMD_RAYTRACE_WORKAROUND + /* For workaround, perform discard backface and background check only within + * the iteration where the first successful ray intersection is registered. + * We flag failures to discard ray hits later. */ + bool hit_valid = !(discard_backface && prev_delta < 0.0) && (depth_sample != 1.0); + if (hit && !hit_valid) { + hit_failsafe = false; + } +#endif + } + +#ifndef METAL_AMD_RAYTRACE_WORKAROUND + /* Discard back-face hits. */ + hit = hit && !(discard_backface && prev_delta < 0.0); + /* Reject hit if background. */ + hit = hit && (depth_sample != 1.0); +#endif + /* Refine hit using intersection between the sampled heightfield and the ray. + * This simplifies nicely to this single line. */ + time = mix(prev_time, time, saturate(prev_delta / (prev_delta - delta))); + + hit_position = ssray.origin.xyz + ssray.direction.xyz * time; + +#ifdef METAL_AMD_RAYTRACE_WORKAROUND + /* Check failed ray flag to discard bad hits. */ + if (!hit_failsafe) { + return false; + } +#endif + return hit; +} + +#if 0 +bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out vec3 hit_position) +{ + /* Clip to near plane for perspective view where there is a singularity at the camera origin. */ + if (ProjectionMatrix[3][3] == 0.0) { + raytrace_clip_ray_to_near_plane(ray); + } + + ScreenSpaceRay ssray = raytrace_screenspace_ray_create(ray); + + /* Planar Reflections have X mirrored. */ + ssray.origin.x = 1.0 - ssray.origin.x; + ssray.direction.x = -ssray.direction.x; + + float prev_delta = 0.0, prev_time = 0.0; + float depth_sample = texture(planarDepth, vec3(ssray.origin.xy, planar_ref_id)).r; + float delta = depth_sample - ssray.origin.z; + + float t = 0.0, time = 0.0; + /* On very sharp reflections, the ray can be perfectly aligned with the view direction + * making the tracing useless. Bypass tracing in this case. */ + bool hit = false; + const float max_steps = 255.0; + for (float iter = 1.0; !hit && (time < ssray.max_time) && (iter < max_steps); iter++) { + float stride = 1.0 + iter * params.trace_quality; + + prev_time = time; + prev_delta = delta; + + time = min(t + stride * params.jitter, ssray.max_time); + t += stride; + + vec4 ss_ray = ssray.origin + ssray.direction * time; + + depth_sample = texture(planarDepth, vec3(ss_ray.xy, planar_ref_id)).r; + + delta = depth_sample - ss_ray.z; + /* Check if the ray is below the surface. */ + hit = (delta < 0.0); + } + /* Reject hit if background. */ + hit = hit && (depth_sample != 1.0); + /* Refine hit using intersection between the sampled heightfield and the ray. + * This simplifies nicely to this single line. */ + time = mix(prev_time, time, saturate(prev_delta / (prev_delta - delta))); + + hit_position = ssray.origin.xyz + ssray.direction.xyz * time; + /* Planar Reflections have X mirrored. */ + hit_position.x = 1.0 - hit_position.x; + + return hit; +} +#endif + +float screen_border_mask(vec2 hit_co) +{ + const float margin = 0.003; + float atten = rt_buf.border_factor + margin; /* Screen percentage */ + hit_co = smoothstep(0.0, atten, hit_co) * (1.0 - smoothstep(1.0 - atten, 1.0, hit_co)); + + float screenfade = hit_co.x * hit_co.y; + + return screenfade; +} diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh new file mode 100644 index 00000000000..23ba5a0dfa4 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "eevee_defines.hh" +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(eevee_raytrace_lib) + .additional_info("draw_view", "eevee_shared", "eevee_hiz_data") + .uniform_buf(RAYTRACE_BUF_SLOT, "RayTracingData", "rt_buf"); + +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") + .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); + +GPU_SHADER_CREATE_INFO(eevee_ao) + .additional_info("eevee_ao_lib") + .additional_info("draw_fullscreen") + .fragment_source("eevee_ao_frag.glsl") + .fragment_out(0, Type::VEC4, "out_horizons") + .sampler(0, ImageType::FLOAT_2D, "normal_tx") + .do_static_compilation(true); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 29fca7a0531..cb495bf5525 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -643,6 +643,7 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) set(SRC_SHADER_CREATE_INFOS ../draw/engines/basic/shaders/infos/basic_depth_info.hh + ../draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_film_info.hh -- 2.30.2 From a11d70fb3d87a5b7b2bc98ef262ff1e4ce14c140 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 26 May 2023 20:43:02 +0200 Subject: [PATCH 02/25] Fix overlap with HiZ buffer --- source/blender/draw/engines/eevee_next/eevee_defines.hh | 4 +++- source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh | 5 ++--- .../draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index c9ca47fae68..a3b76e853ce 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -96,7 +96,8 @@ /* Only during shadow rendering. */ #define SHADOW_RENDER_MAP_SLOT 13 #define RBUFS_UTILITY_TEX_SLOT 14 -#define AO_HORIZONS_TEX_SLOT 15 +#define HIZ_TEX_SLOT 15 +#define AO_HORIZONS_TEX_SLOT 16 /* Images. */ #define RBUFS_COLOR_SLOT 0 @@ -111,6 +112,7 @@ #define VELOCITY_CAMERA_CURR_BUF 4 #define VELOCITY_CAMERA_NEXT_BUF 5 +#define HIZ_BUF_SLOT 5 #define CAMERA_BUF_SLOT 6 #define RBUFS_BUF_SLOT 7 #define RAYTRACE_BUF_SLOT 8 diff --git a/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh index 790e0e25d5b..cee03f461bd 100644 --- a/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh +++ b/source/blender/draw/engines/eevee_next/eevee_hizbuffer.hh @@ -76,11 +76,10 @@ class HiZBuffer { DRW_shgroup_uniform_block_ref(grp, "hiz_buf", &data_); } - /* TODO(fclem): Hardcoded bind slots. */ template void bind_resources(draw::detail::PassBase *pass) { - pass->bind_texture("hiz_tx", &hiz_tx_); - pass->bind_ubo("hiz_buf", &data_); + pass->bind_texture(HIZ_TEX_SLOT, &hiz_tx_); + pass->bind_ubo(HIZ_BUF_SLOT, &data_); } }; diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh index 7bf87d8744b..20b974a106a 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_hiz_info.hh @@ -6,8 +6,8 @@ #include "gpu_shader_create_info.hh" GPU_SHADER_CREATE_INFO(eevee_hiz_data) - .sampler(15, ImageType::FLOAT_2D, "hiz_tx") - .uniform_buf(5, "HiZData", "hiz_buf"); + .sampler(HIZ_TEX_SLOT, ImageType::FLOAT_2D, "hiz_tx") + .uniform_buf(HIZ_BUF_SLOT, "HiZData", "hiz_buf"); GPU_SHADER_CREATE_INFO(eevee_hiz_update) .do_static_compilation(true) -- 2.30.2 From 343b89a5f83d790c940d22b04f3399f5ba5f05cd Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Mon, 29 May 2023 18:09:58 +0200 Subject: [PATCH 03/25] AO node support tmp --- .../draw/engines/eevee_next/eevee_ao.cc | 4 ++ .../draw/engines/eevee_next/eevee_ao.hh | 8 ++++ .../draw/engines/eevee_next/eevee_pipeline.cc | 4 ++ .../draw/engines/eevee_next/eevee_shader.cc | 7 +++ .../eevee_next/shaders/eevee_ao_lib.glsl | 45 +++++-------------- .../shaders/eevee_deferred_light_frag.glsl | 1 + .../shaders/eevee_nodetree_lib.glsl | 17 ++++++- .../shaders/eevee_surf_deferred_frag.glsl | 1 + .../shaders/eevee_surf_forward_frag.glsl | 1 + .../eevee_next/shaders/infos/eevee_ao_info.hh | 2 +- .../shaders/infos/eevee_deferred_info.hh | 1 + .../shaders/infos/eevee_material_info.hh | 7 ++- 12 files changed, 58 insertions(+), 40 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index 9c0aee07170..154a6f73e97 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -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()); + rt_data_.push_update(); } void AmbientOcclusion::sync() diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index a3b3abc454a..237bc644aec 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -47,6 +47,14 @@ class AmbientOcclusion { void sync(); void render(View &view); + + template void bind_resources(draw::detail::PassBase *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_); + } }; /** \} */ diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 2f277e8ac50..9625b830f97 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -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); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index 850ea6f451d..854cac6529c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -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. */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index 6e5227e0e79..12de9819bcf 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -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) */ + +#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 # 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 -} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl index 9653fe630bf..af9fb6ab75c 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl @@ -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() { diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index 957b2b01c1a..5414cc8ea48 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -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 diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl index b7fdca6374c..a02425c7e54 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl @@ -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) #pragma BLENDER_REQUIRE(eevee_surf_lib.glsl) #pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl) #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl index 49764e5219d..43b5fa675a3 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl @@ -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) diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index 23ba5a0dfa4..8e8de29eb2a 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -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) diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index ba4f149f0b7..8a15ff15950 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -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); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index 38bd4b89c68..1654e99bcc4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -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"); -- 2.30.2 From 397a00fa2f35a5b8e84bff502373727e046e7fe8 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Mon, 29 May 2023 19:10:42 +0200 Subject: [PATCH 04/25] Per sample randomization --- source/blender/draw/engines/eevee_next/eevee_ao.hh | 1 + .../draw/engines/eevee_next/shaders/eevee_ao_lib.glsl | 8 +++----- .../engines/eevee_next/shaders/infos/eevee_ao_info.hh | 2 +- .../eevee_next/shaders/infos/eevee_material_info.hh | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index 237bc644aec..e172bacc059 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -50,6 +50,7 @@ class AmbientOcclusion { template void bind_resources(draw::detail::PassBase *pass) { + inst_.sampling.bind_resources(pass); inst_.hiz_buffer.bind_resources(pass); pass->bind_ubo(AO_BUF_SLOT, &data_); pass->bind_ubo(RAYTRACE_BUF_SLOT, &rt_data_); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index 12de9819bcf..fbc819eb303 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -1,6 +1,7 @@ #pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) #pragma BLENDER_REQUIRE(eevee_raytrace_lib.glsl) /* TODO(Miguel Pozo): Move somewhere else. */ @@ -78,11 +79,8 @@ OcclusionData unpack_occlusion_data(vec4 v) vec2 get_ao_noise(void) { - vec2 noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy, UTIL_BLUE_NOISE_LAYER).xy; - - /* Decorrelate noise from AA. */ - /* TODO(@fclem): we should use a more general approach for more random number dimensions. */ - noise = fract(noise * 6.1803402007); + vec2 uv_offset = sampling_rng_2D_get(SAMPLING_SHADOW_X) * vec2(UTIL_TEX_SIZE); + vec2 noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy + uv_offset, UTIL_BLUE_NOISE_LAYER).xy; return noise; } diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index 8e8de29eb2a..dde759c155f 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -8,7 +8,7 @@ GPU_SHADER_CREATE_INFO(eevee_raytrace_lib) .uniform_buf(RAYTRACE_BUF_SLOT, "RayTracingData", "rt_buf"); GPU_SHADER_CREATE_INFO(eevee_ao_lib) - .additional_info("eevee_raytrace_lib", "eevee_utility_texture") + .additional_info("eevee_raytrace_lib", "eevee_sampling_data", "eevee_utility_texture") .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index 1654e99bcc4..69b7e80cb6c 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -17,7 +17,7 @@ GPU_SHADER_CREATE_INFO(eevee_shared) GPU_SHADER_CREATE_INFO(eevee_sampling_data) .define("EEVEE_SAMPLING_DATA") .additional_info("eevee_shared") - .storage_buf(6, Qualifier::READ, "SamplingData", "sampling_buf"); + .storage_buf(SAMPLING_BUF_SLOT, Qualifier::READ, "SamplingData", "sampling_buf"); GPU_SHADER_CREATE_INFO(eevee_utility_texture) .sampler(RBUFS_UTILITY_TEX_SLOT, ImageType::FLOAT_2D_ARRAY, "utility_tx"); -- 2.30.2 From 24a6622681d917351d86c265abbe82147b4898b0 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Mon, 29 May 2023 19:34:23 +0200 Subject: [PATCH 05/25] Cleanup --- source/blender/draw/engines/eevee_next/eevee_ao.cc | 3 --- source/blender/draw/engines/eevee_next/eevee_ao.hh | 13 +++++++++---- .../draw/engines/eevee_next/eevee_shader_shared.hh | 2 ++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index 154a6f73e97..9856eb15495 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -35,9 +35,6 @@ namespace blender::eevee { void AmbientOcclusion::init() { - dummy_horizons_tx_.ensure_2d( - GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ, float4(0)); - debug_ = G.debug_value == 6; const Scene *scene = inst_.scene; diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index e172bacc059..2a027176780 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -26,20 +26,25 @@ class AmbientOcclusion { bool debug_; /* TODO: Move somewhere else. */ - UniformBuffer rt_data_; + RayTracingDataBuf rt_data_; - UniformBuffer data_; + AODataBuf data_; Texture dummy_horizons_tx_; Texture horizons_tx_; - Texture horizons_debug_tx_; Framebuffer fb_ = {"GTAO"}; PassSimple horizons_search_ps_ = {"GTAO Horizons Search"}; public: - AmbientOcclusion(Instance &inst) : inst_(inst){}; + AmbientOcclusion(Instance &inst) : inst_(inst) + { + dummy_horizons_tx_.ensure_2d(GPU_RGBA8, + int2(1), + GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ, + float4(0)); + }; ~AmbientOcclusion(){}; void init(); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 75dcc834224..b3bdcad2916 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -1014,6 +1014,8 @@ using VelocityGeometryBuf = draw::StorageArrayBuffer; using VelocityIndexBuf = draw::StorageArrayBuffer; using VelocityObjectBuf = draw::StorageArrayBuffer; using CryptomatteObjectBuf = draw::StorageArrayBuffer; +using AODataBuf = draw::UniformBuffer; +using RayTracingDataBuf = draw::UniformBuffer; } // namespace blender::eevee #endif -- 2.30.2 From 89b7fb245ac540cee8c9d6380eaba739d6737ce7 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Tue, 30 May 2023 16:01:53 +0200 Subject: [PATCH 06/25] Cleanup: Shader info names --- .../engines/eevee_next/shaders/infos/eevee_ao_info.hh | 8 ++++---- .../eevee_next/shaders/infos/eevee_deferred_info.hh | 2 +- .../eevee_next/shaders/infos/eevee_material_info.hh | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index dde759c155f..f4e313b73f7 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -3,17 +3,17 @@ #include "eevee_defines.hh" #include "gpu_shader_create_info.hh" -GPU_SHADER_CREATE_INFO(eevee_raytrace_lib) +GPU_SHADER_CREATE_INFO(eevee_raytrace_data) .additional_info("draw_view", "eevee_shared", "eevee_hiz_data") .uniform_buf(RAYTRACE_BUF_SLOT, "RayTracingData", "rt_buf"); -GPU_SHADER_CREATE_INFO(eevee_ao_lib) - .additional_info("eevee_raytrace_lib", "eevee_sampling_data", "eevee_utility_texture") +GPU_SHADER_CREATE_INFO(eevee_ao_data) + .additional_info("eevee_raytrace_data", "eevee_sampling_data", "eevee_utility_texture") .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); GPU_SHADER_CREATE_INFO(eevee_ao) - .additional_info("eevee_ao_lib") + .additional_info("eevee_ao_data") .additional_info("draw_fullscreen") .fragment_source("eevee_ao_frag.glsl") .fragment_out(0, Type::VEC4, "out_horizons") diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index 8a15ff15950..9a2a536f6f9 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -41,7 +41,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light) "eevee_deferred_base", "eevee_hiz_data", "eevee_render_pass_out", - "eevee_ao_lib", + "eevee_ao_data", "draw_view", "draw_fullscreen") .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index 69b7e80cb6c..5cc538a57f6 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -109,7 +109,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred) "eevee_sampling_data", "eevee_render_pass_out", "eevee_cryptomatte_out", - "eevee_ao_lib"); + "eevee_ao_data"); GPU_SHADER_CREATE_INFO(eevee_surf_forward) .vertex_out(eevee_surf_iface) @@ -124,7 +124,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward) "eevee_utility_texture", "eevee_sampling_data", "eevee_shadow_data", - "eevee_ao_lib" + "eevee_ao_data" /* Optionally added depending on the material. */ // "eevee_render_pass_out", // "eevee_cryptomatte_out", -- 2.30.2 From 72e1917a3e5d762c3457fa6333ac53daf800766e Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 31 May 2023 17:27:35 +0200 Subject: [PATCH 07/25] AO Pass --- source/blender/draw/CMakeLists.txt | 3 +- .../draw/engines/eevee_next/eevee_ao.cc | 46 ++- .../draw/engines/eevee_next/eevee_ao.hh | 8 + .../draw/engines/eevee_next/eevee_defines.hh | 3 + .../draw/engines/eevee_next/eevee_instance.cc | 2 +- .../draw/engines/eevee_next/eevee_pipeline.cc | 1 - .../engines/eevee_next/eevee_renderbuffers.cc | 6 +- .../draw/engines/eevee_next/eevee_shader.cc | 8 +- .../draw/engines/eevee_next/eevee_shader.hh | 3 +- .../draw/engines/eevee_next/eevee_view.cc | 3 +- .../eevee_next/shaders/eevee_ao_frag.glsl | 108 ------- .../shaders/eevee_ao_horizons_frag.glsl | 26 ++ .../eevee_next/shaders/eevee_ao_lib.glsl | 79 ++---- .../shaders/eevee_ao_pass_comp.glsl | 42 +++ .../shaders/eevee_deferred_light_frag.glsl | 2 +- .../shaders/eevee_nodetree_lib.glsl | 5 +- .../shaders/eevee_surf_forward_frag.glsl | 2 +- .../shaders/eevee_surf_world_frag.glsl | 2 +- .../eevee_next/shaders/infos/eevee_ao_info.hh | 22 +- .../draw/intern/shaders/common_view_lib.glsl | 263 +++++++++++------- 20 files changed, 336 insertions(+), 298 deletions(-) delete mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 59f356da3a5..c16746eeec0 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -436,8 +436,9 @@ set(GLSL_SRC engines/eevee/shaders/infos/engine_eevee_legacy_shared.h engines/eevee/engine_eevee_shared_defines.h - engines/eevee_next/shaders/eevee_ao_frag.glsl + engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl engines/eevee_next/shaders/eevee_ao_lib.glsl + engines/eevee_next/shaders/eevee_ao_pass_comp.glsl engines/eevee_next/shaders/eevee_attributes_lib.glsl engines/eevee_next/shaders/eevee_camera_lib.glsl engines/eevee_next/shaders/eevee_colorspace_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index 9856eb15495..f6905600426 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -35,12 +35,13 @@ namespace blender::eevee { void AmbientOcclusion::init() { - debug_ = G.debug_value == 6; - const Scene *scene = inst_.scene; data_.enabled = (scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) || (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO); + debug_ = data_.enabled && G.debug_value == 6; + render_pass_enabled_ = data_.enabled && inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; + if (!data_.enabled) { /* Early return. */ data_.push_update(); @@ -72,13 +73,28 @@ void AmbientOcclusion::sync() horizons_search_ps_.init(); horizons_search_ps_.state_set(DRW_STATE_WRITE_COLOR); - horizons_search_ps_.shader_set(inst_.shaders.static_shader_get(AO)); + horizons_search_ps_.shader_set(inst_.shaders.static_shader_get(AO_HORIZONS)); horizons_search_ps_.bind_ubo(RAYTRACE_BUF_SLOT, &rt_data_); horizons_search_ps_.bind_ubo(AO_BUF_SLOT, &data_); horizons_search_ps_.bind_texture("utility_tx", &inst_.pipelines.utility_tx); inst_.hiz_buffer.bind_resources(&horizons_search_ps_); horizons_search_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3); + + if (render_pass_enabled_) { + render_pass_ps_.init(); + render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AO_PASS)); + bind_resources(&render_pass_ps_); + + render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); + render_pass_ps_.push_constant("rp_normal_index", &rp_normal_index); + render_pass_ps_.bind_image("out_ao_img", &rp_ao_tx_); + render_pass_ps_.push_constant("rp_ao_index", &rp_ao_index); + + render_pass_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS & GPU_BARRIER_TEXTURE_FETCH); + render_pass_ps_.dispatch( + math::divide_ceil(inst_.film.render_extent_get(), int2(AO_PASS_TILE_SIZE))); + } } void AmbientOcclusion::render(View &view) @@ -90,6 +106,7 @@ void AmbientOcclusion::render(View &view) inst_.hiz_buffer.update(); fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(horizons_tx_)); + fb_.bind(); inst_.manager->submit(horizons_search_ps_, view); if (GPU_mip_render_workaround() || @@ -100,4 +117,27 @@ void AmbientOcclusion::render(View &view) } } +void AmbientOcclusion::render_pass(View &view) +{ + if (!render_pass_enabled_) { + return; + } + + RenderBuffers &rb = inst_.render_buffers; + + rp_normal_tx_ = rb.rp_color_tx; + rp_normal_index = rb.data.normal_id; + rp_ao_tx_ = rb.rp_value_tx; + rp_ao_index = rb.data.ambient_occlusion_id; + + /* + rb.rp_color_tx.ensure_layer_views(); + rp_normal_tx_ = rb.rp_color_tx.layer_view(rb.data.normal_id); + rb.rp_value_tx.ensure_layer_views(); + rp_ao_tx_ = rb.rp_value_tx.layer_view(rb.data.ambient_occlusion_id); + */ + + inst_.manager->submit(render_pass_ps_, view); +} + } // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index 2a027176780..c9342e0dcc3 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -24,6 +24,7 @@ class AmbientOcclusion { class Instance &inst_; bool debug_; + bool render_pass_enabled_; /* TODO: Move somewhere else. */ RayTracingDataBuf rt_data_; @@ -36,6 +37,12 @@ class AmbientOcclusion { Framebuffer fb_ = {"GTAO"}; PassSimple horizons_search_ps_ = {"GTAO Horizons Search"}; + PassSimple render_pass_ps_ = {"GTAO Render Pass"}; + + GPUTexture *rp_normal_tx_ = nullptr; + int rp_normal_index = 0; + GPUTexture *rp_ao_tx_ = nullptr; + int rp_ao_index = 0; public: AmbientOcclusion(Instance &inst) : inst_(inst) @@ -52,6 +59,7 @@ class AmbientOcclusion { void sync(); void render(View &view); + void render_pass(View &view); template void bind_resources(draw::detail::PassBase *pass) { diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index a3b76e853ce..9b7e2054ba5 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -87,6 +87,9 @@ #define DOF_GATHER_GROUP_SIZE DOF_TILES_SIZE #define DOF_RESOLVE_GROUP_SIZE (DOF_TILES_SIZE * 2) +/* Ambient Occlusion. */ +#define AO_PASS_TILE_SIZE 16 + /* Resource bindings. */ /* Texture. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 27080a83837..c84154f293b 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -117,11 +117,11 @@ void Instance::begin_sync() depth_of_field.sync(); motion_blur.sync(); hiz_buffer.sync(); - ao.sync(); main_view.sync(); world.sync(); film.sync(); render_buffers.sync(); + ao.sync(); irradiance_cache.sync(); } diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 9625b830f97..c71a86b7f2c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -414,7 +414,6 @@ void DeferredLayer::render(View &view, inst_.hiz_buffer.set_dirty(); inst_.shadows.set_view(view); - inst_.ao.render(view); inst_.gbuffer.acquire(extent, closure_bits_); diff --git a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc index ee7a4df8739..03a93140ecf 100644 --- a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc +++ b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc @@ -32,15 +32,15 @@ void RenderBuffers::sync() data.color_len = 0; data.value_len = 0; - auto pass_index_get = [&](eViewLayerEEVEEPassType pass_type) { - if (enabled_passes & pass_type) { + auto pass_index_get = [&](eViewLayerEEVEEPassType pass_type, int dependent_passes = 0) { + if (enabled_passes & (pass_type | dependent_passes)) { return inst_.film.pass_storage_type(pass_type) == PASS_STORAGE_COLOR ? data.color_len++ : data.value_len++; } return -1; }; - data.normal_id = pass_index_get(EEVEE_RENDER_PASS_NORMAL); + data.normal_id = pass_index_get(EEVEE_RENDER_PASS_NORMAL, EEVEE_RENDER_PASS_AO); data.diffuse_light_id = pass_index_get(EEVEE_RENDER_PASS_DIFFUSE_LIGHT); data.diffuse_color_id = pass_index_get(EEVEE_RENDER_PASS_DIFFUSE_COLOR); data.specular_light_id = pass_index_get(EEVEE_RENDER_PASS_SPECULAR_LIGHT); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index 854cac6529c..548099dd1d7 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -81,11 +81,13 @@ ShaderModule::~ShaderModule() const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_type) { switch (shader_type) { - case AO: - return "eevee_ao"; + case AO_HORIZONS: + return "eevee_ao_horizons"; + case AO_PASS: + return "eevee_ao_pass"; case AO_DEBUG: /* TODO */ - return "eevee_ao"; + return "eevee_ao_pass"; case FILM_FRAG: return "eevee_film_frag"; case FILM_COMP: diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index fadc0444117..8537c8a137b 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -27,7 +27,8 @@ namespace blender::eevee { /* Keep alphabetical order and clean prefix. */ enum eShaderType { - AO = 0, + AO_HORIZONS = 0, + AO_PASS, AO_DEBUG, FILM_FRAG, diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index f19260c6066..f43bc6ce92e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -139,8 +139,9 @@ void ShadingView::render() inst_.irradiance_cache.debug_draw(render_view_new_, combined_fb_); - GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx); + inst_.ao.render_pass(render_view_new_); + GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx); inst_.film.accumulate(sub_view_, combined_final_tx); rbufs.release(); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl deleted file mode 100644 index bd1f071cb43..00000000000 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_frag.glsl +++ /dev/null @@ -1,108 +0,0 @@ - -#pragma BLENDER_REQUIRE(common_view_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) - -/** - * This shader only compute maximum horizon angles for each directions. - * The final integration is done at the resolve stage with the shading normal. - */ - -/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. - * This samples the depth buffer 4 time for each direction to get the most correct - * implicit normal reconstruction out of the depth buffer. */ -vec3 view_position_derivative_from_depth(vec2 uvs, vec2 ofs, vec3 vP, float depth_center) -{ - vec2 uv1 = uvs - ofs * 2.0; - vec2 uv2 = uvs - ofs; - vec2 uv3 = uvs + ofs; - vec2 uv4 = uvs + ofs * 2.0; - vec4 H; - H.x = textureLod(hiz_tx, uv1, 0.0).r; - H.y = textureLod(hiz_tx, uv2, 0.0).r; - H.z = textureLod(hiz_tx, uv3, 0.0).r; - H.w = textureLod(hiz_tx, uv4, 0.0).r; - /* Fix issue with depth precision. Take even larger diff. */ - vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); - if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { - return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); - } - /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ - vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); - if (deltas.x < deltas.y) { - return vP - get_view_space_from_depth(uv2, H.y); - } - else { - return get_view_space_from_depth(uv3, H.z) - vP; - } -} - -/* TODO(@fclem): port to a common place for other effects to use. */ -bool reconstruct_view_position_and_normal_from_depth(vec2 uvs, out vec3 vP, out vec3 vNg) -{ - vec2 texel_size = vec2(abs(dFdx(uvs.x)), abs(dFdy(uvs.y))); - float depth_center = textureLod(hiz_tx, uvs, 0.0).r; - - vP = get_view_space_from_depth(uvs, depth_center); - - vec3 dPdx = view_position_derivative_from_depth(uvs, texel_size * vec2(1, 0), vP, depth_center); - vec3 dPdy = view_position_derivative_from_depth(uvs, texel_size * vec2(0, 1), vP, depth_center); - - vNg = safe_normalize(cross(dPdx, dPdy)); - - /* Background case. */ - if (depth_center == 1.0) { - return false; - } - - return true; -} - -#ifdef DEBUG_AO - -void main() -{ - vec3 vP, vNg; - vec2 uvs = uvcoordsvar.xy; - - if (!reconstruct_view_position_and_normal_from_depth(uvs * hiz_buf.uv_scale, vP, vNg)) { - /* Handle Background case. Prevent artifact due to uncleared Horizon Render Target. */ - FragColor = vec4(0.0); - } - else { - vec3 P = transform_point(ViewMatrixInverse, vP); - vec3 V = cameraVec(P); - vec3 vV = viewCameraVec(vP); - vec3 vN = normal_decode(texture(normalBuffer, uvs).rg, vV); - vec3 N = transform_direction(ViewMatrixInverse, vN); - vec3 Ng = transform_direction(ViewMatrixInverse, vNg); - - OcclusionData data = occlusion_load(vP, 1.0); - - if (min_v4(abs(data.horizons)) != M_PI) { - FragColor = vec4(diffuse_occlusion(data, V, N, Ng)); - } - else { - FragColor = vec4(1.0); - } - } -} - -#else - -void main() -{ - vec2 uvs = uvcoordsvar.xy; - float depth = textureLod(hiz_tx, uvs * hiz_buf.uv_scale, 0.0).r; - vec3 vP = get_view_space_from_depth(uvs, depth); - - OcclusionData data = NO_OCCLUSION_DATA; - /* Do not trace for background */ - if (depth != 1.0) { - data = occlusion_search(vP, hiz_tx, ao_buf.distance, 0.0, 8.0); - } - - out_horizons = pack_occlusion_data(data); -} -#endif diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl new file mode 100644 index 00000000000..5cef47e4e79 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl @@ -0,0 +1,26 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) + +/** + * This shader only compute maximum horizon angles for each directions. + * The final integration is done at the resolve stage with the shading normal. + */ + +void main() +{ + vec2 uvs = uvcoordsvar.xy; + float depth = textureLod(hiz_tx, uvs * hiz_buf.uv_scale, 0.0).r; + vec3 vP = get_view_space_from_depth(uvs, depth); + + OcclusionData data = NO_OCCLUSION_DATA; + /* Do not trace for background */ + if (depth != 1.0) { + ivec2 texel = ivec2(gl_FragCoord.xy); + data = occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); + } + + out_horizons = pack_occlusion_data(data); +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index fbc819eb303..b0b2a8857e4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -25,30 +25,6 @@ float cone_cosine(float r) * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ -/* TODO(Miguel Pozo) */ - -#if defined(MAT_GEOM_MESH) -# if !defined(USE_ALPHA_HASH) -# if !defined(DEPTH_SHADER) -# if !defined(MAT_TRANSPARENT) -# if !defined(USE_REFRACTION) -# define ENABLE_DEFERRED_AO -# endif -# endif -# endif -# endif -#endif - -#ifndef ENABLE_DEFERRED_AO -# if defined(STEP_RESOLVE) -# define ENABLE_DEFERRED_AO -# endif -#endif - -#ifndef GPU_FRAGMENT_SHADER -# define gl_FragCoord vec4(0.0) -#endif - #define NO_OCCLUSION_DATA OcclusionData(vec4(M_PI, -M_PI, M_PI, -M_PI), 1.0) struct OcclusionData { @@ -77,10 +53,10 @@ OcclusionData unpack_occlusion_data(vec4 v) return OcclusionData((1.0 - v) * vec4(1, -1, 1, -1) * M_PI, 0.0); } -vec2 get_ao_noise(void) +vec2 get_ao_noise(ivec2 texel) { - vec2 uv_offset = sampling_rng_2D_get(SAMPLING_SHADOW_X) * vec2(UTIL_TEX_SIZE); - vec2 noise = utility_tx_fetch(utility_tx, gl_FragCoord.xy + uv_offset, UTIL_BLUE_NOISE_LAYER).xy; + texel += ivec2(sampling_rng_2D_get(SAMPLING_SHADOW_X) * UTIL_TEX_SIZE); + vec2 noise = utility_tx_fetch(utility_tx, texel, UTIL_BLUE_NOISE_LAYER).xy; return noise; } @@ -170,14 +146,18 @@ float search_horizon(vec3 vI, return fast_acos(h); } -OcclusionData occlusion_search( - vec3 vP, sampler2D depth_tx, float radius, const float inverted, const float dir_sample_count) +OcclusionData occlusion_search(vec3 vP, + sampler2D depth_tx, + ivec2 texel, + float radius, + const float inverted, + const float dir_sample_count) { if (!ao_buf.enabled) { return NO_OCCLUSION_DATA; } - vec2 noise = get_ao_noise(); + vec2 noise = get_ao_noise(texel); vec2 dir = get_ao_dir(noise.x); vec2 uv = get_uvs_from_view(vP); vec3 vI = ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)); @@ -228,6 +208,7 @@ vec2 clamp_horizons_to_hemisphere(vec2 horizons, float angle_N, const float inve } void occlusion_eval(OcclusionData data, + ivec2 texel, vec3 V, vec3 N, vec3 Ng, @@ -260,7 +241,7 @@ void occlusion_eval(OcclusionData data, return; } - vec2 noise = get_ao_noise(); + vec2 noise = get_ao_noise(texel); vec2 dir = get_ao_dir(noise.x); visibility_error = 0.0; @@ -346,23 +327,23 @@ float gtao_multibounce(float visibility, vec3 albedo) return max(x, ((x * a + b) * x + c) * x); } -float diffuse_occlusion(OcclusionData data, vec3 V, vec3 N, vec3 Ng) +float diffuse_occlusion(OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng) { vec3 unused; float unused_error; float visibility; - occlusion_eval(data, V, N, Ng, 0.0, visibility, unused_error, unused); + occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, unused); /* Scale by user factor */ visibility = occlusion_pow(saturate(visibility), ao_buf.factor); return visibility; } float diffuse_occlusion( - OcclusionData data, vec3 V, vec3 N, vec3 Ng, vec3 albedo, out vec3 bent_normal) + OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng, vec3 albedo, out vec3 bent_normal) { float visibility; float unused_error; - occlusion_eval(data, V, N, Ng, 0.0, visibility, unused_error, bent_normal); + occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, bent_normal); visibility = gtao_multibounce(visibility, albedo); /* Scale by user factor */ @@ -402,12 +383,12 @@ float spherical_cap_intersection(float radius1, float radius2, float dist) } float specular_occlusion( - OcclusionData data, vec3 V, vec3 N, float roughness, inout vec3 specular_dir) + OcclusionData data, ivec2 texel, vec3 V, vec3 N, float roughness, inout vec3 specular_dir) { vec3 visibility_dir; float visibility_error; float visibility; - occlusion_eval(data, V, N, N, 0.0, visibility, visibility_error, visibility_dir); + occlusion_eval(data, texel, V, N, N, 0.0, visibility, visibility_error, visibility_dir); /* Correct visibility error for very sharp surfaces. */ visibility *= mix(safe_rcp(visibility_error), 1.0, roughness); @@ -433,27 +414,3 @@ float specular_occlusion( visibility = occlusion_pow(saturate(visibility), ao_buf.factor); return visibility; } - -/* Use the right occlusion. */ -OcclusionData occlusion_load(vec3 vP, float custom_occlusion) -{ - /* Default to fully opened cone. */ - OcclusionData data = NO_OCCLUSION_DATA; - -#ifdef ENABLE_DEFERRED_AO - if (ao_buf.enabled) { - data = unpack_occlusion_data(texelFetch(horizons_tx, ivec2(gl_FragCoord.xy), 0)); - } -#else - /* For blended surfaces. */ - data = occlusion_search(vP, hiz_tx, ao_buf.distance, 0.0, 8.0); -#endif - - data.custom_occlusion = custom_occlusion; - - return data; -} - -#ifndef GPU_FRAGMENT_SHADER -# undef gl_FragCoord -#endif diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl new file mode 100644 index 00000000000..33235701fde --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl @@ -0,0 +1,42 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + // ivec2 extent = imageSize(in_normal_img); + ivec2 extent = imageSize(in_normal_img).xy; + if (any(greaterThanEqual(texel, extent))) { + return; + } + + vec2 uv = (vec2(texel) + vec2(0.5)) / vec2(extent); + vec3 vP, vNg; + if (!reconstruct_view_position_and_normal_from_depth(hiz_tx, extent, uv, vP, vNg)) { + /* Do not trace for background */ + imageStore(out_ao_img, ivec3(texel, ao_index), vec4(0.0)); + return; + } + + vec3 P = transform_point(ViewMatrixInverse, vP); + vec3 V = cameraVec(P); + vec3 Ng = transform_direction(ViewMatrixInverse, vNg); + // vec3 N = imageLoad(in_normal_img, texel).xyz; + vec3 N = imageLoad(in_normal_img, ivec3(texel, normal_index)).xyz; + + // OcclusionData data = unpack_occlusion_data(texelFetch(horizons_tx, texel, 0)); + OcclusionData data = occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); + + float visibility; + float visibility_error_out; + vec3 bent_normal_out; + occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, visibility_error_out, bent_normal_out); + /* Scale by user factor */ + visibility = occlusion_pow(saturate(visibility), ao_buf.factor); + + // imageStore(out_ao_img, texel, vec4(visibility)); + imageStore(out_ao_img, ivec3(texel, ao_index), vec4(visibility)); +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl index af9fb6ab75c..c66e24ebf1b 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl @@ -88,7 +88,7 @@ void main() if (rp_buf.shadow_id >= 0) { imageStore(rp_value_img, ivec3(texel, rp_buf.shadow_id), vec4(shadow)); } - /* TODO: AO. */ + /** NOTE: AO is done on its own pass. */ diffuse_light *= diffuse_data.color; reflection_light *= reflection_data.color; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index 5414cc8ea48..b1ce04b0923 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -205,7 +205,8 @@ float ambient_occlusion_eval(vec3 normal, { #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); + ivec2 texel = ivec2(gl_FragCoord.xy); + OcclusionData data = occlusion_search(vP, hiz_tx, texel, max_distance, inverted, sample_count); vec3 V = cameraVec(g_data.P); vec3 N = g_data.N; @@ -213,7 +214,7 @@ float ambient_occlusion_eval(vec3 normal, float unused_error, visibility; vec3 unused; - occlusion_eval(data, V, N, Ng, inverted, visibility, unused_error, unused); + occlusion_eval(data, texel, V, N, Ng, inverted, visibility, unused_error, unused); return visibility; #else return 1.0; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl index 43b5fa675a3..2122880f228 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl @@ -118,7 +118,7 @@ void main() output_renderpass_color(rp_buf.specular_light_id, vec4(specular_light, 1.0)); output_renderpass_color(rp_buf.emission_id, vec4(g_emission, 1.0)); output_renderpass_value(rp_buf.shadow_id, shadow); - /* TODO: AO. */ + /** NOTE: AO is done on its own pass. */ #endif out_radiance.rgb *= 1.0 - g_holdout; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl index 0c53451cda3..c10ddcdba00 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_world_frag.glsl @@ -49,6 +49,6 @@ void main() output_renderpass_color(rp_buf.specular_color_id, clear_color); output_renderpass_color(rp_buf.emission_id, clear_color); output_renderpass_value(rp_buf.shadow_id, 1.0); - output_renderpass_value(rp_buf.ambient_occlusion_id, 0.0); + /** NOTE: AO is done on its own pass. */ imageStore(rp_cryptomatte_img, texel, vec4(0.0)); } diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index f4e313b73f7..7c7a42e6364 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -12,10 +12,22 @@ GPU_SHADER_CREATE_INFO(eevee_ao_data) .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); -GPU_SHADER_CREATE_INFO(eevee_ao) - .additional_info("eevee_ao_data") - .additional_info("draw_fullscreen") - .fragment_source("eevee_ao_frag.glsl") +GPU_SHADER_CREATE_INFO(eevee_ao_horizons) + .additional_info("eevee_ao_data", "draw_fullscreen") + .fragment_source("eevee_ao_horizons_frag.glsl") .fragment_out(0, Type::VEC4, "out_horizons") - .sampler(0, ImageType::FLOAT_2D, "normal_tx") + .do_static_compilation(true); + +GPU_SHADER_CREATE_INFO(eevee_ao_pass) + .additional_info("eevee_ao_data") + .compute_source("eevee_ao_pass_comp.glsl") + .local_group_size(AO_PASS_TILE_SIZE, AO_PASS_TILE_SIZE) + /* + .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "in_normal_img") + .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_ao_img") + */ + .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "in_normal_img") + .push_constant(Type::INT, "normal_index") + .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_ao_img") + .push_constant(Type::INT, "ao_index") .do_static_compilation(true); diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index a7a81d155f2..a45119d3a6b 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -1,25 +1,27 @@ +#pragma BLENDER_REQUIRE(common_math_lib.glsl) /* WORKAROUND: to guard against double include in EEVEE. */ #ifndef COMMON_VIEW_LIB_GLSL -#define COMMON_VIEW_LIB_GLSL +# define COMMON_VIEW_LIB_GLSL -#ifndef DRW_RESOURCE_CHUNK_LEN -# error Missing draw_view additional create info on shader create info -#endif +# ifndef DRW_RESOURCE_CHUNK_LEN +# error Missing draw_view additional create info on shader create info +# endif /* Not supported anymore. TODO(fclem): Add back support. */ // #define IS_DEBUG_MOUSE_FRAGMENT (ivec2(gl_FragCoord) == drw_view.mouse_pixel) -#define IS_FIRST_INVOCATION (gl_GlobalInvocationID == uvec3(0)) +# define IS_FIRST_INVOCATION (gl_GlobalInvocationID == uvec3(0)) -#define cameraForward ViewMatrixInverse[2].xyz -#define cameraPos ViewMatrixInverse[3].xyz +# define cameraForward ViewMatrixInverse[2].xyz +# define cameraPos ViewMatrixInverse[3].xyz vec3 cameraVec(vec3 P) { return ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - P) : cameraForward); } -#define viewCameraVec(vP) ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)) +# define viewCameraVec(vP) \ + ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)) -#ifdef COMMON_GLOBALS_LIB +# ifdef COMMON_GLOBALS_LIB /* TODO move to overlay engine. */ float mul_project_m4_v3_zfac(vec3 co) { @@ -27,7 +29,7 @@ float mul_project_m4_v3_zfac(vec3 co) return pixelFac * ((ProjectionMatrix[0][3] * vP.x) + (ProjectionMatrix[1][3] * vP.y) + (ProjectionMatrix[2][3] * vP.z) + ProjectionMatrix[3][3]); } -#endif +# endif /* Not the right place but need to be common to all overlay's. * TODO: Split to an overlay lib. */ @@ -66,100 +68,100 @@ vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos) } /* Temporary until we fully make the switch. */ -#ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO uniform int drw_resourceChunk; -#endif /* USE_GPU_SHADER_CREATE_INFO */ +# endif /* USE_GPU_SHADER_CREATE_INFO */ -#ifdef GPU_VERTEX_SHADER +# ifdef GPU_VERTEX_SHADER /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO /* clang-format off */ # if defined(IN_PLACE_INSTANCES) || defined(INSTANCED_ATTR) || defined(DRW_LEGACY_MODEL_MATRIX) || defined(GPU_DEPRECATED_AMD_DRIVER) /* clang-format on */ /* When drawing instances of an object at the same position. */ -# define instanceId 0 -# else -# define instanceId gl_InstanceID -# endif +# define instanceId 0 +# else +# define instanceId gl_InstanceID +# endif -# if defined(UNIFORM_RESOURCE_ID) +# if defined(UNIFORM_RESOURCE_ID) /* This is in the case we want to do a special instance drawcall for one object but still want to * have the right resourceId and all the correct ubo datas. */ uniform int drw_ResourceID; -# define resource_id drw_ResourceID -# else -# define resource_id (gpu_BaseInstance + instanceId) -# endif +# define resource_id drw_ResourceID +# else +# define resource_id (gpu_BaseInstance + instanceId) +# endif /* Use this to declare and pass the value if * the fragment shader uses the resource_id. */ -# if defined(EEVEE_GENERATED_INTERFACE) -# define RESOURCE_ID_VARYING -# define PASS_RESOURCE_ID resourceIDFrag = resource_id; -# elif defined(USE_GEOMETRY_SHADER) -# define RESOURCE_ID_VARYING flat out int resourceIDGeom; -# define PASS_RESOURCE_ID resourceIDGeom = resource_id; -# else -# define RESOURCE_ID_VARYING flat out int resourceIDFrag; -# define PASS_RESOURCE_ID resourceIDFrag = resource_id; -# endif +# if defined(EEVEE_GENERATED_INTERFACE) +# define RESOURCE_ID_VARYING +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# elif defined(USE_GEOMETRY_SHADER) +# define RESOURCE_ID_VARYING flat out int resourceIDGeom; +# define PASS_RESOURCE_ID resourceIDGeom = resource_id; +# else +# define RESOURCE_ID_VARYING flat out int resourceIDFrag; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# endif -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# endif /* USE_GPU_SHADER_CREATE_INFO */ -#endif /* GPU_VERTEX_SHADER */ +# endif /* GPU_VERTEX_SHADER */ /* Temporary until we fully make the switch. */ -#ifdef USE_GPU_SHADER_CREATE_INFO +# ifdef USE_GPU_SHADER_CREATE_INFO /* TODO(fclem): Rename PASS_RESOURCE_ID to DRW_RESOURCE_ID_VARYING_SET */ -# if defined(UNIFORM_RESOURCE_ID) -# define resource_id drw_ResourceID -# define PASS_RESOURCE_ID +# if defined(UNIFORM_RESOURCE_ID) +# define resource_id drw_ResourceID +# define PASS_RESOURCE_ID -# elif defined(GPU_VERTEX_SHADER) -# if defined(UNIFORM_RESOURCE_ID_NEW) -# define resource_id (drw_ResourceID >> DRW_VIEW_SHIFT) -# else -# define resource_id gpu_InstanceIndex +# elif defined(GPU_VERTEX_SHADER) +# if defined(UNIFORM_RESOURCE_ID_NEW) +# define resource_id (drw_ResourceID >> DRW_VIEW_SHIFT) +# else +# define resource_id gpu_InstanceIndex +# endif +# define PASS_RESOURCE_ID drw_ResourceID_iface.resource_index = resource_id; + +# elif defined(GPU_GEOMETRY_SHADER) +# define resource_id drw_ResourceID_iface_in[0].resource_index +# define PASS_RESOURCE_ID drw_ResourceID_iface_out.resource_index = resource_id; + +# elif defined(GPU_FRAGMENT_SHADER) +# define resource_id drw_ResourceID_iface.resource_index # endif -# define PASS_RESOURCE_ID drw_ResourceID_iface.resource_index = resource_id; - -# elif defined(GPU_GEOMETRY_SHADER) -# define resource_id drw_ResourceID_iface_in[0].resource_index -# define PASS_RESOURCE_ID drw_ResourceID_iface_out.resource_index = resource_id; - -# elif defined(GPU_FRAGMENT_SHADER) -# define resource_id drw_ResourceID_iface.resource_index -# endif /* TODO(fclem): Remove. */ -# define RESOURCE_ID_VARYING +# define RESOURCE_ID_VARYING -#else +# else /* If used in a fragment / geometry shader, we pass * resource_id as varying. */ -# ifdef GPU_GEOMETRY_SHADER +# ifdef GPU_GEOMETRY_SHADER /* TODO(fclem): Remove. This is getting ridiculous. */ -# if !defined(EEVEE_GENERATED_INTERFACE) -# define RESOURCE_ID_VARYING \ - flat out int resourceIDFrag; \ - flat in int resourceIDGeom[]; -# else -# define RESOURCE_ID_VARYING +# if !defined(EEVEE_GENERATED_INTERFACE) +# define RESOURCE_ID_VARYING \ + flat out int resourceIDFrag; \ + flat in int resourceIDGeom[]; +# else +# define RESOURCE_ID_VARYING +# endif + +# define resource_id resourceIDGeom +# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0]; # endif -# define resource_id resourceIDGeom -# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0]; -# endif - -# if defined(GPU_FRAGMENT_SHADER) -# if !defined(EEVEE_GENERATED_INTERFACE) +# if defined(GPU_FRAGMENT_SHADER) +# if !defined(EEVEE_GENERATED_INTERFACE) flat in int resourceIDFrag; +# endif +# define resource_id resourceIDFrag # endif -# define resource_id resourceIDFrag # endif -#endif /* Breaking this across multiple lines causes issues for some older GLSL compilers. */ /* clang-format off */ @@ -167,42 +169,42 @@ flat in int resourceIDFrag; /* clang-format on */ /* Temporary until we fully make the switch. */ -# ifndef DRW_SHADER_SHARED_H +# ifndef DRW_SHADER_SHARED_H struct ObjectMatrices { mat4 model; mat4 model_inverse; }; -# endif /* DRW_SHADER_SHARED_H */ +# endif /* DRW_SHADER_SHARED_H */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO layout(std140) uniform modelBlock { ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN]; }; -# define ModelMatrix (drw_matrices[resource_id].model) -# define ModelMatrixInverse (drw_matrices[resource_id].model_inverse) -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# define ModelMatrix (drw_matrices[resource_id].model) +# define ModelMatrixInverse (drw_matrices[resource_id].model_inverse) +# endif /* USE_GPU_SHADER_CREATE_INFO */ -#else /* GPU_INTEL */ +# else /* GPU_INTEL */ /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO /* Intel GPU seems to suffer performance impact when the model matrix is in UBO storage. * So for now we just force using the legacy path. */ /* Note that this is also a workaround of a problem on OSX (AMD or NVIDIA) * and older amd driver on windows. */ uniform mat4 ModelMatrix; uniform mat4 ModelMatrixInverse; -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# endif /* USE_GPU_SHADER_CREATE_INFO */ -#endif +# endif /* Temporary until we fully make the switch. */ -#ifndef USE_GPU_SHADER_CREATE_INFO -# define resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) -#endif +# ifndef USE_GPU_SHADER_CREATE_INFO +# define resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) +# endif /** Transform shortcuts. */ /* Rule of thumb: Try to reuse world positions and normals because converting through viewspace @@ -221,21 +223,21 @@ uniform mat4 ModelMatrixInverse; * NOTE: This is only valid because we are only using the mat3 of the ViewMatrixInverse. * ViewMatrix * transpose(ModelMatrixInverse) */ -#define NormalMatrix transpose(mat3(ModelMatrixInverse)) -#define NormalMatrixInverse transpose(mat3(ModelMatrix)) +# define NormalMatrix transpose(mat3(ModelMatrixInverse)) +# define NormalMatrixInverse transpose(mat3(ModelMatrix)) -#define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n)) -#define normal_object_to_world(n) (NormalMatrix * n) -#define normal_world_to_object(n) (NormalMatrixInverse * n) -#define normal_world_to_view(n) (mat3(ViewMatrix) * n) -#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) +# define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n)) +# define normal_object_to_world(n) (NormalMatrix * n) +# define normal_world_to_object(n) (NormalMatrixInverse * n) +# define normal_world_to_view(n) (mat3(ViewMatrix) * n) +# define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) -#define point_object_to_ndc(p) \ - (ProjectionMatrix * (ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))) -#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) -#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) -#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) -#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) +# define point_object_to_ndc(p) \ + (ProjectionMatrix * (ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))) +# define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) +# define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) +# define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) +# define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) vec4 point_view_to_ndc(vec3 p) { @@ -276,16 +278,16 @@ float get_homogenous_z_offset(float vs_z, float hs_w, float vs_offset) /* Due to some shader compiler bug, we somewhat need to access gl_VertexID * to make vertex shaders work. even if it's actually dead code. */ -#if defined(GPU_INTEL) && defined(GPU_OPENGL) -# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); -#else -# define GPU_INTEL_VERTEX_SHADER_WORKAROUND -#endif +# if defined(GPU_INTEL) && defined(GPU_OPENGL) +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); +# else +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND +# endif -#define DRW_BASE_SELECTED (1 << 1) -#define DRW_BASE_FROM_DUPLI (1 << 2) -#define DRW_BASE_FROM_SET (1 << 3) -#define DRW_BASE_ACTIVE (1 << 4) +# define DRW_BASE_SELECTED (1 << 1) +# define DRW_BASE_FROM_DUPLI (1 << 2) +# define DRW_BASE_FROM_SET (1 << 3) +# define DRW_BASE_ACTIVE (1 << 4) /* ---- Opengl Depth conversion ---- */ @@ -365,4 +367,55 @@ vec3 get_view_vector_from_screen_uv(vec2 uvcoords) return vec3(0.0, 0.0, 1.0); } +/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. + * This samples the depth buffer 4 time for each direction to get the most correct + * implicit normal reconstruction out of the depth buffer. */ +vec3 view_position_derivative_from_depth( + sampler2D depth_tx, ivec2 extent, vec2 uv, ivec2 offset, vec3 vP, float depth_center) +{ + vec4 H; + H.x = texelFetch(depth_tx, ivec2(uv * extent) - offset * 2, 0).r; + H.y = texelFetch(depth_tx, ivec2(uv * extent) - offset, 0).r; + H.z = texelFetch(depth_tx, ivec2(uv * extent) + offset, 0).r; + H.w = texelFetch(depth_tx, ivec2(uv * extent) + offset * 2, 0).r; + + vec2 uv_offset = vec2(offset) / extent; + vec2 uv1 = uv - uv_offset * 2.0; + vec2 uv2 = uv - uv_offset; + vec2 uv3 = uv + uv_offset; + vec2 uv4 = uv + uv_offset * 2.0; + + /* Fix issue with depth precision. Take even larger diff. */ + vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); + if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { + return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); + } + /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ + vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); + if (deltas.x < deltas.y) { + return vP - get_view_space_from_depth(uv2, H.y); + } + else { + return get_view_space_from_depth(uv3, H.z) - vP; + } +} + +bool reconstruct_view_position_and_normal_from_depth( + sampler2D depth_tx, ivec2 extent, vec2 uv, out vec3 vP, out vec3 vNg) +{ + float depth_center = texelFetch(depth_tx, ivec2(uv * extent), 0).r; + + vP = get_view_space_from_depth(uv, depth_center); + + vec3 dPdx = view_position_derivative_from_depth( + depth_tx, extent, uv, ivec2(1, 0), vP, depth_center); + vec3 dPdy = view_position_derivative_from_depth( + depth_tx, extent, uv, ivec2(0, 1), vP, depth_center); + + vNg = safe_normalize(cross(dPdx, dPdy)); + + /* Background case. */ + return depth_center != 1.0; +} + #endif /* COMMON_VIEW_LIB_GLSL */ -- 2.30.2 From 1d60aced03a2f60f008c41c793648cd7b0ac1ee7 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 31 May 2023 17:52:15 +0200 Subject: [PATCH 08/25] Use layer views --- source/blender/draw/engines/eevee_next/eevee_ao.cc | 11 ++--------- .../eevee_next/shaders/eevee_ao_pass_comp.glsl | 11 ++++------- .../engines/eevee_next/shaders/infos/eevee_ao_info.hh | 6 ------ 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index f6905600426..bb0e1f0529c 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -87,9 +87,7 @@ void AmbientOcclusion::sync() bind_resources(&render_pass_ps_); render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); - render_pass_ps_.push_constant("rp_normal_index", &rp_normal_index); render_pass_ps_.bind_image("out_ao_img", &rp_ao_tx_); - render_pass_ps_.push_constant("rp_ao_index", &rp_ao_index); render_pass_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS & GPU_BARRIER_TEXTURE_FETCH); render_pass_ps_.dispatch( @@ -125,17 +123,12 @@ void AmbientOcclusion::render_pass(View &view) RenderBuffers &rb = inst_.render_buffers; - rp_normal_tx_ = rb.rp_color_tx; - rp_normal_index = rb.data.normal_id; - rp_ao_tx_ = rb.rp_value_tx; - rp_ao_index = rb.data.ambient_occlusion_id; - - /* rb.rp_color_tx.ensure_layer_views(); rp_normal_tx_ = rb.rp_color_tx.layer_view(rb.data.normal_id); rb.rp_value_tx.ensure_layer_views(); rp_ao_tx_ = rb.rp_value_tx.layer_view(rb.data.ambient_occlusion_id); - */ + + BLI_assert(rp_normal_tx_ && rp_ao_tx_); inst_.manager->submit(render_pass_ps_, view); } diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl index 33235701fde..af18eabd8c5 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl @@ -7,8 +7,7 @@ void main() { ivec2 texel = ivec2(gl_GlobalInvocationID.xy); - // ivec2 extent = imageSize(in_normal_img); - ivec2 extent = imageSize(in_normal_img).xy; + ivec2 extent = imageSize(in_normal_img); if (any(greaterThanEqual(texel, extent))) { return; } @@ -17,15 +16,14 @@ void main() vec3 vP, vNg; if (!reconstruct_view_position_and_normal_from_depth(hiz_tx, extent, uv, vP, vNg)) { /* Do not trace for background */ - imageStore(out_ao_img, ivec3(texel, ao_index), vec4(0.0)); + imageStore(out_ao_img, texel, vec4(0.0)); return; } vec3 P = transform_point(ViewMatrixInverse, vP); vec3 V = cameraVec(P); vec3 Ng = transform_direction(ViewMatrixInverse, vNg); - // vec3 N = imageLoad(in_normal_img, texel).xyz; - vec3 N = imageLoad(in_normal_img, ivec3(texel, normal_index)).xyz; + vec3 N = imageLoad(in_normal_img, texel).xyz; // OcclusionData data = unpack_occlusion_data(texelFetch(horizons_tx, texel, 0)); OcclusionData data = occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); @@ -37,6 +35,5 @@ void main() /* Scale by user factor */ visibility = occlusion_pow(saturate(visibility), ao_buf.factor); - // imageStore(out_ao_img, texel, vec4(visibility)); - imageStore(out_ao_img, ivec3(texel, ao_index), vec4(visibility)); + imageStore(out_ao_img, texel, vec4(visibility)); } diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index 7c7a42e6364..adf60eece0a 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -22,12 +22,6 @@ GPU_SHADER_CREATE_INFO(eevee_ao_pass) .additional_info("eevee_ao_data") .compute_source("eevee_ao_pass_comp.glsl") .local_group_size(AO_PASS_TILE_SIZE, AO_PASS_TILE_SIZE) - /* .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "in_normal_img") .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_ao_img") - */ - .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D_ARRAY, "in_normal_img") - .push_constant(Type::INT, "normal_index") - .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D_ARRAY, "out_ao_img") - .push_constant(Type::INT, "ao_index") .do_static_compilation(true); -- 2.30.2 From ab5deccdf06b8aa89ff457166da60a1d6692364b Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 31 May 2023 19:49:01 +0200 Subject: [PATCH 09/25] Add RayTracing module --- source/blender/draw/CMakeLists.txt | 2 + .../draw/engines/eevee_next/eevee_ao.cc | 13 ++---- .../draw/engines/eevee_next/eevee_ao.hh | 9 ++-- .../draw/engines/eevee_next/eevee_instance.cc | 1 + .../draw/engines/eevee_next/eevee_instance.hh | 5 ++- .../engines/eevee_next/eevee_raytracing.cc | 40 ++++++++++++++++++ .../engines/eevee_next/eevee_raytracing.hh | 42 +++++++++++++++++++ .../engines/eevee_next/eevee_shader_shared.hh | 17 ++++---- .../shaders/eevee_raytrace_lib.glsl | 2 +- 9 files changed, 107 insertions(+), 24 deletions(-) create mode 100644 source/blender/draw/engines/eevee_next/eevee_raytracing.cc create mode 100644 source/blender/draw/engines/eevee_next/eevee_raytracing.hh diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index c16746eeec0..5ac3f032b70 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -151,6 +151,7 @@ set(SRC engines/eevee_next/eevee_material.cc engines/eevee_next/eevee_motion_blur.cc engines/eevee_next/eevee_pipeline.cc + engines/eevee_next/eevee_raytracing.cc engines/eevee_next/eevee_renderbuffers.cc engines/eevee_next/eevee_sampling.cc engines/eevee_next/eevee_shader.cc @@ -292,6 +293,7 @@ set(SRC engines/eevee_next/eevee_material.hh engines/eevee_next/eevee_motion_blur.hh engines/eevee_next/eevee_pipeline.hh + engines/eevee_next/eevee_raytracing.hh engines/eevee_next/eevee_renderbuffers.hh engines/eevee_next/eevee_sampling.hh engines/eevee_next/eevee_shader.hh diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index bb0e1f0529c..7549277ce65 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -59,10 +59,6 @@ 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()); - rt_data_.push_update(); } void AmbientOcclusion::sync() @@ -74,10 +70,7 @@ void AmbientOcclusion::sync() horizons_search_ps_.init(); horizons_search_ps_.state_set(DRW_STATE_WRITE_COLOR); horizons_search_ps_.shader_set(inst_.shaders.static_shader_get(AO_HORIZONS)); - horizons_search_ps_.bind_ubo(RAYTRACE_BUF_SLOT, &rt_data_); - horizons_search_ps_.bind_ubo(AO_BUF_SLOT, &data_); - horizons_search_ps_.bind_texture("utility_tx", &inst_.pipelines.utility_tx); - inst_.hiz_buffer.bind_resources(&horizons_search_ps_); + bind_resources(&horizons_search_ps_, false); horizons_search_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3); @@ -121,6 +114,8 @@ void AmbientOcclusion::render_pass(View &view) return; } + inst_.hiz_buffer.update(); + RenderBuffers &rb = inst_.render_buffers; rb.rp_color_tx.ensure_layer_views(); @@ -128,8 +123,6 @@ void AmbientOcclusion::render_pass(View &view) rb.rp_value_tx.ensure_layer_views(); rp_ao_tx_ = rb.rp_value_tx.layer_view(rb.data.ambient_occlusion_id); - BLI_assert(rp_normal_tx_ && rp_ao_tx_); - inst_.manager->submit(render_pass_ps_, view); } diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index c9342e0dcc3..2094a6c686b 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -26,9 +26,6 @@ class AmbientOcclusion { bool debug_; bool render_pass_enabled_; - /* TODO: Move somewhere else. */ - RayTracingDataBuf rt_data_; - AODataBuf data_; Texture dummy_horizons_tx_; @@ -61,12 +58,14 @@ class AmbientOcclusion { void render(View &view); void render_pass(View &view); - template void bind_resources(draw::detail::PassBase *pass) + template + void bind_resources(draw::detail::PassBase *pass, bool bind_horizons = true) { inst_.sampling.bind_resources(pass); inst_.hiz_buffer.bind_resources(pass); + inst_.raytracing.bind_resources(pass); + pass->bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); 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_); } }; diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index c84154f293b..f96ffe1ad25 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -73,6 +73,7 @@ void Instance::init(const int2 &output_res, motion_blur.init(); main_view.init(); irradiance_cache.init(); + raytracing.init(); } void Instance::set_time(float time) diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 546585e1850..92f911c1a87 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -28,6 +28,7 @@ #include "eevee_material.hh" #include "eevee_motion_blur.hh" #include "eevee_pipeline.hh" +#include "eevee_raytracing.hh" #include "eevee_renderbuffers.hh" #include "eevee_sampling.hh" #include "eevee_shader.hh" @@ -67,6 +68,7 @@ class Instance { MainView main_view; World world; IrradianceCache irradiance_cache; + RayTracing raytracing; /** Input data. */ Depsgraph *depsgraph; @@ -112,7 +114,8 @@ class Instance { render_buffers(*this), main_view(*this), world(*this), - irradiance_cache(*this){}; + irradiance_cache(*this), + raytracing(*this){}; ~Instance(){}; void init(const int2 &output_res, diff --git a/source/blender/draw/engines/eevee_next/eevee_raytracing.cc b/source/blender/draw/engines/eevee_next/eevee_raytracing.cc new file mode 100644 index 00000000000..c1eb0dda21d --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_raytracing.cc @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eevee + * + * Screen Space Ray Tracing + * + */ + +#pragma once + +#include "eevee_raytracing.hh" +#include "eevee_instance.hh" + +namespace blender::eevee { + +class Instance; + +/* -------------------------------------------------------------------- */ +/** \name RayTracing + * \{ */ + +void RayTracing::init() +{ + /* Compute pixel size. Size is multiplied by 2 because it is applied in NDC [-1..1] range. */ + data_.pixel_size = float2(2.0f) / float2(inst_.film.render_extent_get()); + data_.border_fade = inst_.scene->eevee.ssr_border_fade; + + data_.ssr_quality = 1.0f - 0.95f * inst_.scene->eevee.ssr_quality; + data_.ssr_thickness = inst_.scene->eevee.ssr_thickness; + data_.ssr_firefly_factor = inst_.scene->eevee.ssr_firefly_fac; + data_.ssr_max_roughness = inst_.scene->eevee.ssr_max_roughness; + data_.ssr_brdf_bias = 0.1f + data_.ssr_quality * 0.6f; /* Range [0.1, 0.7]. */ + + data_.push_update(); +} + +/** \} */ + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_raytracing.hh b/source/blender/draw/engines/eevee_next/eevee_raytracing.hh new file mode 100644 index 00000000000..84a3310a0a5 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/eevee_raytracing.hh @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eevee + * + * Screen Space Ray Tracing + * + */ + +#pragma once + +#include "eevee_shader_shared.hh" + +namespace blender::eevee { + +class Instance; + +/* -------------------------------------------------------------------- */ +/** \name RayTracing + * \{ */ + +class RayTracing { + private: + class Instance &inst_; + + RayTracingDataBuf data_; + + public: + RayTracing(Instance &inst) : inst_(inst){}; + ~RayTracing(){}; + + void init(); + + template void bind_resources(draw::detail::PassBase *pass) + { + pass->bind_ubo(RAYTRACE_BUF_SLOT, &data_); + } +}; + +/** \} */ + +} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index b3bdcad2916..b94e5d378b9 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -886,13 +886,16 @@ enum eClosureBits : uint32_t { struct RayTracingData { float2 pixel_size; - float quality; - float thickness; - float border_factor; /* This is the only one used */ - float max_roughness; - float firefly_factor; - float brdf_bias; - bool1 toggle; + float border_fade; + + /* TODO(Miguel Pozo): Does this belong here? */ + float ssr_quality; + float ssr_thickness; + float ssr_max_roughness; + float ssr_firefly_factor; + float ssr_brdf_bias; + bool1 ssr_enabled; + int _pad0; int _pad1; int _pad2; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl index c4f93fd5f6c..64b179a8ea4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl @@ -245,7 +245,7 @@ bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out float screen_border_mask(vec2 hit_co) { const float margin = 0.003; - float atten = rt_buf.border_factor + margin; /* Screen percentage */ + float atten = rt_buf.border_fade + margin; /* Screen percentage */ hit_co = smoothstep(0.0, atten, hit_co) * (1.0 - smoothstep(1.0 - atten, 1.0, hit_co)); float screenfade = hit_co.x * hit_co.y; -- 2.30.2 From 79fc2ff3a0476c4b8951e7d6f0d46d62fd9300c2 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 31 May 2023 20:01:02 +0200 Subject: [PATCH 10/25] Cleanup --- .../draw/engines/eevee_next/eevee_ao.cc | 9 +- .../draw/engines/eevee_next/eevee_ao.hh | 3 +- .../draw/intern/shaders/common_view_lib.glsl | 218 +++++++++--------- 3 files changed, 115 insertions(+), 115 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index 7549277ce65..7eac97cddbd 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -5,10 +5,11 @@ * * Ground Truth Ambient Occlusion * - */ - -/** - * Occlusion Algorithm Overview: + * Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx + * + * Algorithm Overview: * * We separate the computation into 2 steps. * diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index 2094a6c686b..5e32d83a025 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -36,10 +36,9 @@ class AmbientOcclusion { PassSimple horizons_search_ps_ = {"GTAO Horizons Search"}; PassSimple render_pass_ps_ = {"GTAO Render Pass"}; + /* Used as pointers for texture views in the AO Render Pass. */ GPUTexture *rp_normal_tx_ = nullptr; - int rp_normal_index = 0; GPUTexture *rp_ao_tx_ = nullptr; - int rp_ao_index = 0; public: AmbientOcclusion(Instance &inst) : inst_(inst) diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index a45119d3a6b..18e14267836 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -1,27 +1,27 @@ -#pragma BLENDER_REQUIRE(common_math_lib.glsl) /* WORKAROUND: to guard against double include in EEVEE. */ #ifndef COMMON_VIEW_LIB_GLSL -# define COMMON_VIEW_LIB_GLSL +#define COMMON_VIEW_LIB_GLSL -# ifndef DRW_RESOURCE_CHUNK_LEN -# error Missing draw_view additional create info on shader create info -# endif +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +#ifndef DRW_RESOURCE_CHUNK_LEN +# error Missing draw_view additional create info on shader create info +#endif /* Not supported anymore. TODO(fclem): Add back support. */ // #define IS_DEBUG_MOUSE_FRAGMENT (ivec2(gl_FragCoord) == drw_view.mouse_pixel) -# define IS_FIRST_INVOCATION (gl_GlobalInvocationID == uvec3(0)) +#define IS_FIRST_INVOCATION (gl_GlobalInvocationID == uvec3(0)) -# define cameraForward ViewMatrixInverse[2].xyz -# define cameraPos ViewMatrixInverse[3].xyz +#define cameraForward ViewMatrixInverse[2].xyz +#define cameraPos ViewMatrixInverse[3].xyz vec3 cameraVec(vec3 P) { return ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - P) : cameraForward); } -# define viewCameraVec(vP) \ - ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)) +#define viewCameraVec(vP) ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)) -# ifdef COMMON_GLOBALS_LIB +#ifdef COMMON_GLOBALS_LIB /* TODO move to overlay engine. */ float mul_project_m4_v3_zfac(vec3 co) { @@ -29,7 +29,7 @@ float mul_project_m4_v3_zfac(vec3 co) return pixelFac * ((ProjectionMatrix[0][3] * vP.x) + (ProjectionMatrix[1][3] * vP.y) + (ProjectionMatrix[2][3] * vP.z) + ProjectionMatrix[3][3]); } -# endif +#endif /* Not the right place but need to be common to all overlay's. * TODO: Split to an overlay lib. */ @@ -68,143 +68,143 @@ vec4 pack_line_data(vec2 frag_co, vec2 edge_start, vec2 edge_pos) } /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO +#ifndef USE_GPU_SHADER_CREATE_INFO uniform int drw_resourceChunk; -# endif /* USE_GPU_SHADER_CREATE_INFO */ +#endif /* USE_GPU_SHADER_CREATE_INFO */ -# ifdef GPU_VERTEX_SHADER +#ifdef GPU_VERTEX_SHADER /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO /* clang-format off */ # if defined(IN_PLACE_INSTANCES) || defined(INSTANCED_ATTR) || defined(DRW_LEGACY_MODEL_MATRIX) || defined(GPU_DEPRECATED_AMD_DRIVER) /* clang-format on */ /* When drawing instances of an object at the same position. */ -# define instanceId 0 -# else -# define instanceId gl_InstanceID -# endif +# define instanceId 0 +# else +# define instanceId gl_InstanceID +# endif -# if defined(UNIFORM_RESOURCE_ID) +# if defined(UNIFORM_RESOURCE_ID) /* This is in the case we want to do a special instance drawcall for one object but still want to * have the right resourceId and all the correct ubo datas. */ uniform int drw_ResourceID; -# define resource_id drw_ResourceID -# else -# define resource_id (gpu_BaseInstance + instanceId) -# endif +# define resource_id drw_ResourceID +# else +# define resource_id (gpu_BaseInstance + instanceId) +# endif /* Use this to declare and pass the value if * the fragment shader uses the resource_id. */ -# if defined(EEVEE_GENERATED_INTERFACE) -# define RESOURCE_ID_VARYING -# define PASS_RESOURCE_ID resourceIDFrag = resource_id; -# elif defined(USE_GEOMETRY_SHADER) -# define RESOURCE_ID_VARYING flat out int resourceIDGeom; -# define PASS_RESOURCE_ID resourceIDGeom = resource_id; -# else -# define RESOURCE_ID_VARYING flat out int resourceIDFrag; -# define PASS_RESOURCE_ID resourceIDFrag = resource_id; -# endif +# if defined(EEVEE_GENERATED_INTERFACE) +# define RESOURCE_ID_VARYING +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# elif defined(USE_GEOMETRY_SHADER) +# define RESOURCE_ID_VARYING flat out int resourceIDGeom; +# define PASS_RESOURCE_ID resourceIDGeom = resource_id; +# else +# define RESOURCE_ID_VARYING flat out int resourceIDFrag; +# define PASS_RESOURCE_ID resourceIDFrag = resource_id; +# endif -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# endif /* USE_GPU_SHADER_CREATE_INFO */ -# endif /* GPU_VERTEX_SHADER */ +#endif /* GPU_VERTEX_SHADER */ /* Temporary until we fully make the switch. */ -# ifdef USE_GPU_SHADER_CREATE_INFO +#ifdef USE_GPU_SHADER_CREATE_INFO /* TODO(fclem): Rename PASS_RESOURCE_ID to DRW_RESOURCE_ID_VARYING_SET */ -# if defined(UNIFORM_RESOURCE_ID) -# define resource_id drw_ResourceID -# define PASS_RESOURCE_ID +# if defined(UNIFORM_RESOURCE_ID) +# define resource_id drw_ResourceID +# define PASS_RESOURCE_ID -# elif defined(GPU_VERTEX_SHADER) -# if defined(UNIFORM_RESOURCE_ID_NEW) -# define resource_id (drw_ResourceID >> DRW_VIEW_SHIFT) -# else -# define resource_id gpu_InstanceIndex -# endif -# define PASS_RESOURCE_ID drw_ResourceID_iface.resource_index = resource_id; - -# elif defined(GPU_GEOMETRY_SHADER) -# define resource_id drw_ResourceID_iface_in[0].resource_index -# define PASS_RESOURCE_ID drw_ResourceID_iface_out.resource_index = resource_id; - -# elif defined(GPU_FRAGMENT_SHADER) -# define resource_id drw_ResourceID_iface.resource_index +# elif defined(GPU_VERTEX_SHADER) +# if defined(UNIFORM_RESOURCE_ID_NEW) +# define resource_id (drw_ResourceID >> DRW_VIEW_SHIFT) +# else +# define resource_id gpu_InstanceIndex # endif +# define PASS_RESOURCE_ID drw_ResourceID_iface.resource_index = resource_id; + +# elif defined(GPU_GEOMETRY_SHADER) +# define resource_id drw_ResourceID_iface_in[0].resource_index +# define PASS_RESOURCE_ID drw_ResourceID_iface_out.resource_index = resource_id; + +# elif defined(GPU_FRAGMENT_SHADER) +# define resource_id drw_ResourceID_iface.resource_index +# endif /* TODO(fclem): Remove. */ -# define RESOURCE_ID_VARYING +# define RESOURCE_ID_VARYING -# else +#else /* If used in a fragment / geometry shader, we pass * resource_id as varying. */ -# ifdef GPU_GEOMETRY_SHADER +# ifdef GPU_GEOMETRY_SHADER /* TODO(fclem): Remove. This is getting ridiculous. */ -# if !defined(EEVEE_GENERATED_INTERFACE) -# define RESOURCE_ID_VARYING \ - flat out int resourceIDFrag; \ - flat in int resourceIDGeom[]; -# else -# define RESOURCE_ID_VARYING -# endif - -# define resource_id resourceIDGeom -# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0]; +# if !defined(EEVEE_GENERATED_INTERFACE) +# define RESOURCE_ID_VARYING \ + flat out int resourceIDFrag; \ + flat in int resourceIDGeom[]; +# else +# define RESOURCE_ID_VARYING # endif -# if defined(GPU_FRAGMENT_SHADER) -# if !defined(EEVEE_GENERATED_INTERFACE) -flat in int resourceIDFrag; -# endif -# define resource_id resourceIDFrag -# endif +# define resource_id resourceIDGeom +# define PASS_RESOURCE_ID resourceIDFrag = resource_id[0]; # endif +# if defined(GPU_FRAGMENT_SHADER) +# if !defined(EEVEE_GENERATED_INTERFACE) +flat in int resourceIDFrag; +# endif +# define resource_id resourceIDFrag +# endif +#endif + /* Breaking this across multiple lines causes issues for some older GLSL compilers. */ /* clang-format off */ #if !defined(GPU_INTEL) && !defined(GPU_DEPRECATED_AMD_DRIVER) && (!defined(OS_MAC) || defined(GPU_METAL)) && !defined(INSTANCED_ATTR) && !defined(DRW_LEGACY_MODEL_MATRIX) /* clang-format on */ /* Temporary until we fully make the switch. */ -# ifndef DRW_SHADER_SHARED_H +# ifndef DRW_SHADER_SHARED_H struct ObjectMatrices { mat4 model; mat4 model_inverse; }; -# endif /* DRW_SHADER_SHARED_H */ +# endif /* DRW_SHADER_SHARED_H */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO layout(std140) uniform modelBlock { ObjectMatrices drw_matrices[DRW_RESOURCE_CHUNK_LEN]; }; -# define ModelMatrix (drw_matrices[resource_id].model) -# define ModelMatrixInverse (drw_matrices[resource_id].model_inverse) -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# define ModelMatrix (drw_matrices[resource_id].model) +# define ModelMatrixInverse (drw_matrices[resource_id].model_inverse) +# endif /* USE_GPU_SHADER_CREATE_INFO */ -# else /* GPU_INTEL */ +#else /* GPU_INTEL */ /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO +# ifndef USE_GPU_SHADER_CREATE_INFO /* Intel GPU seems to suffer performance impact when the model matrix is in UBO storage. * So for now we just force using the legacy path. */ /* Note that this is also a workaround of a problem on OSX (AMD or NVIDIA) * and older amd driver on windows. */ uniform mat4 ModelMatrix; uniform mat4 ModelMatrixInverse; -# endif /* USE_GPU_SHADER_CREATE_INFO */ +# endif /* USE_GPU_SHADER_CREATE_INFO */ -# endif +#endif /* Temporary until we fully make the switch. */ -# ifndef USE_GPU_SHADER_CREATE_INFO -# define resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) -# endif +#ifndef USE_GPU_SHADER_CREATE_INFO +# define resource_handle (drw_resourceChunk * DRW_RESOURCE_CHUNK_LEN + resource_id) +#endif /** Transform shortcuts. */ /* Rule of thumb: Try to reuse world positions and normals because converting through viewspace @@ -223,21 +223,21 @@ uniform mat4 ModelMatrixInverse; * NOTE: This is only valid because we are only using the mat3 of the ViewMatrixInverse. * ViewMatrix * transpose(ModelMatrixInverse) */ -# define NormalMatrix transpose(mat3(ModelMatrixInverse)) -# define NormalMatrixInverse transpose(mat3(ModelMatrix)) +#define NormalMatrix transpose(mat3(ModelMatrixInverse)) +#define NormalMatrixInverse transpose(mat3(ModelMatrix)) -# define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n)) -# define normal_object_to_world(n) (NormalMatrix * n) -# define normal_world_to_object(n) (NormalMatrixInverse * n) -# define normal_world_to_view(n) (mat3(ViewMatrix) * n) -# define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) +#define normal_object_to_view(n) (mat3(ViewMatrix) * (NormalMatrix * n)) +#define normal_object_to_world(n) (NormalMatrix * n) +#define normal_world_to_object(n) (NormalMatrixInverse * n) +#define normal_world_to_view(n) (mat3(ViewMatrix) * n) +#define normal_view_to_world(n) (mat3(ViewMatrixInverse) * n) -# define point_object_to_ndc(p) \ - (ProjectionMatrix * (ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))) -# define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) -# define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) -# define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) -# define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) +#define point_object_to_ndc(p) \ + (ProjectionMatrix * (ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0))) +#define point_object_to_view(p) ((ViewMatrix * vec4((ModelMatrix * vec4(p, 1.0)).xyz, 1.0)).xyz) +#define point_object_to_world(p) ((ModelMatrix * vec4(p, 1.0)).xyz) +#define point_view_to_object(p) ((ModelMatrixInverse * (ViewMatrixInverse * vec4(p, 1.0))).xyz) +#define point_world_to_object(p) ((ModelMatrixInverse * vec4(p, 1.0)).xyz) vec4 point_view_to_ndc(vec3 p) { @@ -278,16 +278,16 @@ float get_homogenous_z_offset(float vs_z, float hs_w, float vs_offset) /* Due to some shader compiler bug, we somewhat need to access gl_VertexID * to make vertex shaders work. even if it's actually dead code. */ -# if defined(GPU_INTEL) && defined(GPU_OPENGL) -# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); -# else -# define GPU_INTEL_VERTEX_SHADER_WORKAROUND -# endif +#if defined(GPU_INTEL) && defined(GPU_OPENGL) +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND gl_Position.x = float(gl_VertexID); +#else +# define GPU_INTEL_VERTEX_SHADER_WORKAROUND +#endif -# define DRW_BASE_SELECTED (1 << 1) -# define DRW_BASE_FROM_DUPLI (1 << 2) -# define DRW_BASE_FROM_SET (1 << 3) -# define DRW_BASE_ACTIVE (1 << 4) +#define DRW_BASE_SELECTED (1 << 1) +#define DRW_BASE_FROM_DUPLI (1 << 2) +#define DRW_BASE_FROM_SET (1 << 3) +#define DRW_BASE_ACTIVE (1 << 4) /* ---- Opengl Depth conversion ---- */ -- 2.30.2 From 469d46e16e5da51e01d320103eb8eb2748595f86 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 2 Jun 2023 17:34:32 +0200 Subject: [PATCH 11/25] Fix bind resources --- source/blender/draw/engines/eevee_next/eevee_ao.hh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index 5e32d83a025..8a1dd0a4bb1 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -65,7 +65,10 @@ class AmbientOcclusion { inst_.raytracing.bind_resources(pass); pass->bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); pass->bind_ubo(AO_BUF_SLOT, &data_); - pass->bind_texture(AO_HORIZONS_TEX_SLOT, data_.enabled ? &horizons_tx_ : &dummy_horizons_tx_); + if (bind_horizons) { + pass->bind_texture(AO_HORIZONS_TEX_SLOT, + data_.enabled ? &horizons_tx_ : &dummy_horizons_tx_); + } } }; -- 2.30.2 From 8b254636d1ec801c8d0f10c51ede724cf4040ea8 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 2 Jun 2023 17:34:46 +0200 Subject: [PATCH 12/25] Fix get_ao_noise --- source/blender/draw/engines/eevee_next/eevee_sampling.cc | 3 +++ .../blender/draw/engines/eevee_next/eevee_shader_shared.hh | 6 ++++-- .../draw/engines/eevee_next/shaders/eevee_ao_lib.glsl | 3 +-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_sampling.cc b/source/blender/draw/engines/eevee_next/eevee_sampling.cc index 6f79ffa2513..6ca006c40a2 100644 --- a/source/blender/draw/engines/eevee_next/eevee_sampling.cc +++ b/source/blender/draw/engines/eevee_next/eevee_sampling.cc @@ -112,6 +112,9 @@ void Sampling::step() /* TODO de-correlate. */ data_.dimensions[SAMPLING_LIGHTPROBE] = r[0]; data_.dimensions[SAMPLING_TRANSPARENCY] = r[1]; + /* TODO de-correlate. */ + data_.dimensions[SAMPLING_AO_U] = r[0]; + data_.dimensions[SAMPLING_AO_V] = r[1]; } { /* Using leaped Halton sequence so we can reused the same primes as lens. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index b94e5d378b9..1396e5c6b7e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -97,14 +97,16 @@ enum eSamplingDimension : uint32_t { SAMPLING_RAYTRACE_U = 15u, SAMPLING_RAYTRACE_V = 16u, SAMPLING_RAYTRACE_W = 17u, - SAMPLING_RAYTRACE_X = 18u + SAMPLING_RAYTRACE_X = 18u, + SAMPLING_AO_U = 19u, + SAMPLING_AO_V = 20u, }; /** * IMPORTANT: Make sure the array can contain all sampling dimensions. * Also note that it needs to be multiple of 4. */ -#define SAMPLING_DIMENSION_COUNT 20 +#define SAMPLING_DIMENSION_COUNT 24 /* NOTE(@fclem): Needs to be used in #StorageBuffer because of arrays of scalar. */ struct SamplingData { diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index b0b2a8857e4..f59f861c15a 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -55,9 +55,8 @@ OcclusionData unpack_occlusion_data(vec4 v) vec2 get_ao_noise(ivec2 texel) { - texel += ivec2(sampling_rng_2D_get(SAMPLING_SHADOW_X) * UTIL_TEX_SIZE); vec2 noise = utility_tx_fetch(utility_tx, texel, UTIL_BLUE_NOISE_LAYER).xy; - return noise; + return fract(noise + sampling_rng_2D_get(SAMPLING_AO_U)); } vec2 get_ao_dir(float jitter) -- 2.30.2 From edb9b9ccc25572bc816a9a72d515d64cb1ff8fed Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 2 Jun 2023 17:40:36 +0200 Subject: [PATCH 13/25] Cleanup --- source/blender/draw/engines/eevee_next/eevee_ao.cc | 2 -- source/blender/draw/engines/eevee_next/eevee_ao.hh | 1 - source/blender/draw/engines/eevee_next/eevee_shader.cc | 3 --- source/blender/draw/engines/eevee_next/eevee_shader.hh | 1 - 4 files changed, 7 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index 7eac97cddbd..a66e60c654a 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -39,8 +39,6 @@ void AmbientOcclusion::init() const Scene *scene = inst_.scene; data_.enabled = (scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) || (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO); - - debug_ = data_.enabled && G.debug_value == 6; render_pass_enabled_ = data_.enabled && inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; if (!data_.enabled) { diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index 8a1dd0a4bb1..b8a27197c7d 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -23,7 +23,6 @@ class AmbientOcclusion { private: class Instance &inst_; - bool debug_; bool render_pass_enabled_; AODataBuf data_; diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index 548099dd1d7..c9b41e1c7ab 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -85,9 +85,6 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ return "eevee_ao_horizons"; case AO_PASS: return "eevee_ao_pass"; - case AO_DEBUG: - /* TODO */ - return "eevee_ao_pass"; case FILM_FRAG: return "eevee_film_frag"; case FILM_COMP: diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index 8537c8a137b..93ecc0820e9 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -29,7 +29,6 @@ namespace blender::eevee { enum eShaderType { AO_HORIZONS = 0, AO_PASS, - AO_DEBUG, FILM_FRAG, FILM_COMP, -- 2.30.2 From abaea6659a389e4a0e071288bb9a13080eaea5f2 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Mon, 5 Jun 2023 12:32:20 +0200 Subject: [PATCH 14/25] Cleanup --- source/blender/draw/engines/eevee_next/eevee_ao.hh | 10 +++++++--- .../draw/engines/eevee_next/shaders/eevee_ao_lib.glsl | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ao.hh index b8a27197c7d..f7337a7b789 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ao.hh @@ -5,6 +5,10 @@ * * Ground Truth Ambient Occlusion * + * Based on Practical Realtime Strategies for Accurate Indirect Occlusion + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf + * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx + * */ #pragma once @@ -30,10 +34,10 @@ class AmbientOcclusion { Texture dummy_horizons_tx_; Texture horizons_tx_; - Framebuffer fb_ = {"GTAO"}; + Framebuffer fb_ = {"AO"}; - PassSimple horizons_search_ps_ = {"GTAO Horizons Search"}; - PassSimple render_pass_ps_ = {"GTAO Render Pass"}; + PassSimple horizons_search_ps_ = {"AO Horizons Search"}; + PassSimple render_pass_ps_ = {"AO Render Pass"}; /* Used as pointers for texture views in the AO Render Pass. */ GPUTexture *rp_normal_tx_ = nullptr; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index f59f861c15a..67c031830e1 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -352,8 +352,8 @@ float diffuse_occlusion( /** * Approximate the area of intersection of two spherical caps - * radius1 : First cap’s radius (arc length in radians) - * radius2 : Second caps’ radius (in radians) + * radius1 : First cap radius (arc length in radians) + * radius2 : Second cap radius (in radians) * dist : Distance between caps (radians between centers of caps) * NOTE: Result is divided by pi to save one multiply. */ -- 2.30.2 From f69e0f221397bce050944a90e2cd4e1d9998e1ba Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 15 Jun 2023 16:02:05 +0200 Subject: [PATCH 15/25] Split eevee_ao_data/eevee_ao_horizons_data --- .../draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh | 7 +++++-- .../eevee_next/shaders/infos/eevee_deferred_info.hh | 2 +- .../eevee_next/shaders/infos/eevee_material_info.hh | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh index adf60eece0a..69de7e8dbe4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh @@ -9,9 +9,12 @@ GPU_SHADER_CREATE_INFO(eevee_raytrace_data) GPU_SHADER_CREATE_INFO(eevee_ao_data) .additional_info("eevee_raytrace_data", "eevee_sampling_data", "eevee_utility_texture") - .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); +GPU_SHADER_CREATE_INFO(eevee_ao_horizons_data) + .additional_info("eevee_ao_data") + .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx"); + GPU_SHADER_CREATE_INFO(eevee_ao_horizons) .additional_info("eevee_ao_data", "draw_fullscreen") .fragment_source("eevee_ao_horizons_frag.glsl") @@ -19,7 +22,7 @@ GPU_SHADER_CREATE_INFO(eevee_ao_horizons) .do_static_compilation(true); GPU_SHADER_CREATE_INFO(eevee_ao_pass) - .additional_info("eevee_ao_data") + .additional_info("eevee_ao_horizons_data") .compute_source("eevee_ao_pass_comp.glsl") .local_group_size(AO_PASS_TILE_SIZE, AO_PASS_TILE_SIZE) .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "in_normal_img") diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index 9a2a536f6f9..2c37e14c1ac 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -41,7 +41,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light) "eevee_deferred_base", "eevee_hiz_data", "eevee_render_pass_out", - "eevee_ao_data", + "eevee_ao_horizons_data", "draw_view", "draw_fullscreen") .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index 6ff8d879b8f..f553b028a03 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -125,7 +125,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward) "eevee_utility_texture", "eevee_sampling_data", "eevee_shadow_data", - "eevee_ao_horizons_data", + "eevee_ao_horizons_data" /* Optionally added depending on the material. */ // "eevee_render_pass_out", // "eevee_cryptomatte_out", -- 2.30.2 From 5f7a76ced131c6daadca67904f4fd1a125adab80 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 15 Jun 2023 17:13:09 +0200 Subject: [PATCH 16/25] Remove outdated parameters --- scripts/startup/bl_ui/properties_render.py | 3 -- .../draw/engines/eevee_next/eevee_ao.cc | 3 -- .../engines/eevee_next/eevee_shader_shared.hh | 4 --- .../eevee_next/shaders/eevee_ao_lib.glsl | 32 +++++++++---------- 4 files changed, 15 insertions(+), 27 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 785123a4c34..4104887232b 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -168,10 +168,7 @@ class RENDER_PT_eevee_next_ambient_occlusion(RenderButtonsPanel, Panel): layout.active = props.use_gtao col = layout.column() col.prop(props, "gtao_distance") - col.prop(props, "gtao_factor") col.prop(props, "gtao_quality") - col.prop(props, "use_gtao_bent_normals") - col.prop(props, "use_gtao_bounce") class RENDER_PT_eevee_motion_blur(RenderButtonsPanel, Panel): diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ao.cc index a66e60c654a..330725afa27 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ao.cc @@ -49,10 +49,7 @@ void AmbientOcclusion::init() } data_.distance = scene->eevee.gtao_distance; - data_.factor = std::max(1e-4f, scene->eevee.gtao_factor); data_.quality = scene->eevee.gtao_quality; - data_.use_bent_normals = scene->eevee.flag & SCE_EEVEE_GTAO_BENT_NORMALS; - data_.bounce_factor = (scene->eevee.flag & SCE_EEVEE_GTAO_BOUNCE) ? 1.0f : 0.0f; data_.push_update(); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 1396e5c6b7e..c7efe207d28 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -914,13 +914,9 @@ BLI_STATIC_ASSERT_ALIGN(RayTracingData, 16) struct AOData { bool1 enabled; - bool1 use_bent_normals; float distance; - float factor; - float bounce_factor; float quality; int _pad0; - int _pad1; }; BLI_STATIC_ASSERT_ALIGN(AOData, 16) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index 67c031830e1..80044275f2b 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -26,6 +26,8 @@ float cone_cosine(float r) */ #define NO_OCCLUSION_DATA OcclusionData(vec4(M_PI, -M_PI, M_PI, -M_PI), 1.0) +#define AO_BENT_NORMALS true +#define AO_MULTI_BOUNCE true struct OcclusionData { /* 4 horizons angles, one in each direction around the view vector to form a cross pattern. */ @@ -231,11 +233,11 @@ void occlusion_eval(OcclusionData data, visibility = saturate(dot(N, Ng) * 0.5 + 0.5); visibility = min(visibility, data.custom_occlusion); - if (!ao_buf.use_bent_normals) { - bent_normal = N; + if (AO_BENT_NORMALS) { + bent_normal = safe_normalize(N + Ng); } else { - bent_normal = safe_normalize(N + Ng); + bent_normal = N; } return; } @@ -297,21 +299,21 @@ void occlusion_eval(OcclusionData data, visibility = min(visibility, data.custom_occlusion); - if (!ao_buf.use_bent_normals) { - bent_normal = N; - } - else { + if (AO_BENT_NORMALS) { /* NOTE: using pow(visibility, 6.0) produces NaN (see #87369). */ float tmp = saturate(pow6(visibility)); bent_normal = normalize(mix(bent_normal, N, tmp)); } + else { + bent_normal = N; + } } /* Multibounce approximation base on surface albedo. * Page 78 in the .pdf version. */ float gtao_multibounce(float visibility, vec3 albedo) { - if (ao_buf.bounce_factor == 0.0) { + if (!AO_MULTI_BOUNCE) { return visibility; } @@ -332,9 +334,8 @@ float diffuse_occlusion(OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng float unused_error; float visibility; occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, unused); - /* Scale by user factor */ - visibility = occlusion_pow(saturate(visibility), ao_buf.factor); - return visibility; + + return saturate(visibility); } float diffuse_occlusion( @@ -345,9 +346,8 @@ float diffuse_occlusion( occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, bent_normal); visibility = gtao_multibounce(visibility, albedo); - /* Scale by user factor */ - visibility = occlusion_pow(saturate(visibility), ao_buf.factor); - return visibility; + + return saturate(visibility); } /** @@ -409,7 +409,5 @@ float specular_occlusion( float tmp = saturate(pow8(visibility)); visibility = mix(specular_occlusion, 1.0, tmp); - /* Scale by user factor */ - visibility = occlusion_pow(saturate(visibility), ao_buf.factor); - return visibility; + return saturate(visibility); } -- 2.30.2 From cf95e7ec7f2b7b967b9794fc4e341d17c918fbd1 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 15 Jun 2023 17:14:11 +0200 Subject: [PATCH 17/25] Workaround shader compilation errors --- .../draw/engines/eevee_next/eevee_defines.hh | 5 +- .../shaders/eevee_ao_pass_comp.glsl | 55 ++++++++++++++++++- .../draw/intern/shaders/common_view_lib.glsl | 53 ------------------ 3 files changed, 57 insertions(+), 56 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index d7e4941c340..a61f763b579 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -119,8 +119,9 @@ #define HIZ_BUF_SLOT 5 #define CAMERA_BUF_SLOT 6 #define RBUFS_BUF_SLOT 7 -#define RAYTRACE_BUF_SLOT 8 -#define AO_BUF_SLOT 9 +/* Skip 8 to avoid overlap with draw_modelmat in hair and gpencil */ +#define RAYTRACE_BUF_SLOT 9 +#define AO_BUF_SLOT 10 /* Storage Buffers. */ #define LIGHT_CULL_BUF_SLOT 0 diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl index af18eabd8c5..2729d1e924d 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl @@ -4,6 +4,59 @@ #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) #pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) +/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. + * This samples the depth buffer 4 time for each direction to get the most correct + * implicit normal reconstruction out of the depth buffer. */ +vec3 view_position_derivative_from_depth( + sampler2D depth_tx, ivec2 extent, vec2 uv, ivec2 offset, vec3 vP, float depth_center) +{ + vec4 H; + H.x = texelFetch(depth_tx, ivec2(uv * extent) - offset * 2, 0).r; + H.y = texelFetch(depth_tx, ivec2(uv * extent) - offset, 0).r; + H.z = texelFetch(depth_tx, ivec2(uv * extent) + offset, 0).r; + H.w = texelFetch(depth_tx, ivec2(uv * extent) + offset * 2, 0).r; + + vec2 uv_offset = vec2(offset) / extent; + vec2 uv1 = uv - uv_offset * 2.0; + vec2 uv2 = uv - uv_offset; + vec2 uv3 = uv + uv_offset; + vec2 uv4 = uv + uv_offset * 2.0; + + /* Fix issue with depth precision. Take even larger diff. */ + vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); + if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { + return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); + } + /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ + vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); + if (deltas.x < deltas.y) { + return vP - get_view_space_from_depth(uv2, H.y); + } + else { + return get_view_space_from_depth(uv3, H.z) - vP; + } +} + +/* TODO(Miguel Pozo): This should be in common_view_lib, + * but moving it there results in dependency hell. */ +bool reconstruct_view_position_and_normal_from_depth( + sampler2D depth_tx, ivec2 extent, vec2 uv, out vec3 vP, out vec3 vNg) +{ + float depth_center = texelFetch(depth_tx, ivec2(uv * extent), 0).r; + + vP = get_view_space_from_depth(uv, depth_center); + + vec3 dPdx = view_position_derivative_from_depth( + depth_tx, extent, uv, ivec2(1, 0), vP, depth_center); + vec3 dPdy = view_position_derivative_from_depth( + depth_tx, extent, uv, ivec2(0, 1), vP, depth_center); + + vNg = safe_normalize(cross(dPdx, dPdy)); + + /* Background case. */ + return depth_center != 1.0; +} + void main() { ivec2 texel = ivec2(gl_GlobalInvocationID.xy); @@ -33,7 +86,7 @@ void main() vec3 bent_normal_out; occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, visibility_error_out, bent_normal_out); /* Scale by user factor */ - visibility = occlusion_pow(saturate(visibility), ao_buf.factor); + visibility = saturate(visibility); imageStore(out_ao_img, texel, vec4(visibility)); } diff --git a/source/blender/draw/intern/shaders/common_view_lib.glsl b/source/blender/draw/intern/shaders/common_view_lib.glsl index 18e14267836..a7a81d155f2 100644 --- a/source/blender/draw/intern/shaders/common_view_lib.glsl +++ b/source/blender/draw/intern/shaders/common_view_lib.glsl @@ -3,8 +3,6 @@ #ifndef COMMON_VIEW_LIB_GLSL #define COMMON_VIEW_LIB_GLSL -#pragma BLENDER_REQUIRE(common_math_lib.glsl) - #ifndef DRW_RESOURCE_CHUNK_LEN # error Missing draw_view additional create info on shader create info #endif @@ -367,55 +365,4 @@ vec3 get_view_vector_from_screen_uv(vec2 uvcoords) return vec3(0.0, 0.0, 1.0); } -/* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. - * This samples the depth buffer 4 time for each direction to get the most correct - * implicit normal reconstruction out of the depth buffer. */ -vec3 view_position_derivative_from_depth( - sampler2D depth_tx, ivec2 extent, vec2 uv, ivec2 offset, vec3 vP, float depth_center) -{ - vec4 H; - H.x = texelFetch(depth_tx, ivec2(uv * extent) - offset * 2, 0).r; - H.y = texelFetch(depth_tx, ivec2(uv * extent) - offset, 0).r; - H.z = texelFetch(depth_tx, ivec2(uv * extent) + offset, 0).r; - H.w = texelFetch(depth_tx, ivec2(uv * extent) + offset * 2, 0).r; - - vec2 uv_offset = vec2(offset) / extent; - vec2 uv1 = uv - uv_offset * 2.0; - vec2 uv2 = uv - uv_offset; - vec2 uv3 = uv + uv_offset; - vec2 uv4 = uv + uv_offset * 2.0; - - /* Fix issue with depth precision. Take even larger diff. */ - vec4 diff = abs(vec4(depth_center, H.yzw) - H.x); - if (max_v4(diff) < 2.4e-7 && all(lessThan(diff.xyz, diff.www))) { - return 0.25 * (get_view_space_from_depth(uv3, H.w) - get_view_space_from_depth(uv1, H.x)); - } - /* Simplified (H.xw + 2.0 * (H.yz - H.xw)) - depth_center */ - vec2 deltas = abs((2.0 * H.yz - H.xw) - depth_center); - if (deltas.x < deltas.y) { - return vP - get_view_space_from_depth(uv2, H.y); - } - else { - return get_view_space_from_depth(uv3, H.z) - vP; - } -} - -bool reconstruct_view_position_and_normal_from_depth( - sampler2D depth_tx, ivec2 extent, vec2 uv, out vec3 vP, out vec3 vNg) -{ - float depth_center = texelFetch(depth_tx, ivec2(uv * extent), 0).r; - - vP = get_view_space_from_depth(uv, depth_center); - - vec3 dPdx = view_position_derivative_from_depth( - depth_tx, extent, uv, ivec2(1, 0), vP, depth_center); - vec3 dPdy = view_position_derivative_from_depth( - depth_tx, extent, uv, ivec2(0, 1), vP, depth_center); - - vNg = safe_normalize(cross(dPdx, dPdy)); - - /* Background case. */ - return depth_center != 1.0; -} - #endif /* COMMON_VIEW_LIB_GLSL */ -- 2.30.2 From 4f34ce7cfa12c78b1e14f2f93e1daefe86edb8c5 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 16 Jun 2023 19:46:25 +0200 Subject: [PATCH 18/25] Cleanup tmp --- .../shaders/eevee_ao_horizons_frag.glsl | 6 +- .../eevee_next/shaders/eevee_ao_lib.glsl | 155 +++++++++--------- .../shaders/eevee_ao_pass_comp.glsl | 6 +- .../shaders/eevee_deferred_light_frag.glsl | 1 - .../shaders/eevee_nodetree_lib.glsl | 13 +- 5 files changed, 87 insertions(+), 94 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl index 5cef47e4e79..df535c079b8 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl @@ -15,12 +15,12 @@ void main() float depth = textureLod(hiz_tx, uvs * hiz_buf.uv_scale, 0.0).r; vec3 vP = get_view_space_from_depth(uvs, depth); - OcclusionData data = NO_OCCLUSION_DATA; + OcclusionData data = ambient_occlusion_disabled_data(); /* Do not trace for background */ if (depth != 1.0) { ivec2 texel = ivec2(gl_FragCoord.xy); - data = occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); + data = ambient_occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); } - out_horizons = pack_occlusion_data(data); + out_horizons = ambient_occlusion_pack_data(data); } diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl index 80044275f2b..e686f7262c8 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl @@ -4,10 +4,9 @@ #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) #pragma BLENDER_REQUIRE(eevee_raytrace_lib.glsl) -/* TODO(Miguel Pozo): Move somewhere else. */ - +/* TODO(Miguel Pozo): Move this function somewhere else. */ /* Return a fitted cone angle given the input roughness */ -float cone_cosine(float r) +float ambient_occlusion_cone_cosine(float r) { /* Using phong gloss * roughness = sqrt(2/(gloss+2)) */ @@ -25,43 +24,47 @@ float cone_cosine(float r) * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */ -#define NO_OCCLUSION_DATA OcclusionData(vec4(M_PI, -M_PI, M_PI, -M_PI), 1.0) #define AO_BENT_NORMALS true #define AO_MULTI_BOUNCE true struct OcclusionData { - /* 4 horizons angles, one in each direction around the view vector to form a cross pattern. */ + /* 4 horizon angles, one in each direction around the view vector to form a cross pattern. */ vec4 horizons; /* Custom large scale occlusion. */ float custom_occlusion; - -#ifdef GPU_METAL - /* Constructors required for OcclusionData(..) syntax. */ - inline OcclusionData() = default; - inline OcclusionData(vec4 in_horizons, float in_custom_occlusion) - : horizons(in_horizons), custom_occlusion(in_custom_occlusion) - { - } -#endif }; -vec4 pack_occlusion_data(OcclusionData data) +OcclusionData ambient_occlusion_data(vec4 horizons, float custom_occlusion) +{ + OcclusionData data; + data.horizons = horizons; + data.custom_occlusion = custom_occlusion; + return data; +} + +/* No Occlusion Data. */ +OcclusionData ambient_occlusion_disabled_data() +{ + return ambient_occlusion_data(vec4(M_PI, -M_PI, M_PI, -M_PI), 1.0); +} + +vec4 ambient_occlusion_pack_data(OcclusionData data) { return vec4(1.0 - data.horizons * vec4(1, -1, 1, -1) * M_1_PI); } -OcclusionData unpack_occlusion_data(vec4 v) +OcclusionData ambient_occlusion_unpack_data(vec4 v) { - return OcclusionData((1.0 - v) * vec4(1, -1, 1, -1) * M_PI, 0.0); + return ambient_occlusion_data((1.0 - v) * vec4(1, -1, 1, -1) * M_PI, 0.0); } -vec2 get_ao_noise(ivec2 texel) +vec2 ambient_occlusion_get_noise(ivec2 texel) { vec2 noise = utility_tx_fetch(utility_tx, texel, UTIL_BLUE_NOISE_LAYER).xy; return fract(noise + sampling_rng_2D_get(SAMPLING_AO_U)); } -vec2 get_ao_dir(float jitter) +vec2 ambient_occlusion_get_dir(float jitter) { /* Only a quarter of a turn because we integrate using 2 slices. * We use this instead of using utiltex circle noise to improve cache hits @@ -70,30 +73,15 @@ vec2 get_ao_dir(float jitter) return vec2(cos(jitter), sin(jitter)); } -/* Certain intel drivers on macOS lose precision, resulting in rendering artifacts, - * when using standard pow(A, B) function. - * Using logarithmic identity provides higher precision results. */ -#if defined(GPU_INTEL) && defined(OS_MAC) -float occlusion_pow(float a, float b) -{ - return exp(b * log(a)); -} -#else -float occlusion_pow(float a, float b) -{ - return pow(a, b); -} -#endif - /* Return horizon angle cosine. */ -float search_horizon(vec3 vI, - vec3 vP, - float noise, - ScreenSpaceRay ssray, - sampler2D depth_tx, - const float inverted, - float radius, - const float sample_count) +float ambient_ambient_occlusion_search_horizon(vec3 vI, + vec3 vP, + float noise, + ScreenSpaceRay ssray, + sampler2D depth_tx, + const float inverted, + float radius, + const float sample_count) { /* Init at cos(M_PI). */ float h = (inverted != 0.0) ? 1.0 : -1.0; @@ -147,26 +135,26 @@ float search_horizon(vec3 vI, return fast_acos(h); } -OcclusionData occlusion_search(vec3 vP, - sampler2D depth_tx, - ivec2 texel, - float radius, - const float inverted, - const float dir_sample_count) +OcclusionData ambient_occlusion_search(vec3 vP, + sampler2D depth_tx, + ivec2 texel, + float radius, + const float inverted, + const float dir_sample_count) { if (!ao_buf.enabled) { - return NO_OCCLUSION_DATA; + return ambient_occlusion_disabled_data(); } - vec2 noise = get_ao_noise(texel); - vec2 dir = get_ao_dir(noise.x); + vec2 noise = ambient_occlusion_get_noise(texel); + vec2 dir = ambient_occlusion_get_dir(noise.x); vec2 uv = get_uvs_from_view(vP); vec3 vI = ((ProjectionMatrix[3][3] == 0.0) ? normalize(-vP) : vec3(0.0, 0.0, 1.0)); vec3 avg_dir = vec3(0.0); float avg_apperture = 0.0; - OcclusionData data = (inverted != 0.0) ? OcclusionData(vec4(0, 0, 0, 0), 1.0) : - NO_OCCLUSION_DATA; + OcclusionData data = (inverted != 0.0) ? ambient_occlusion_data(vec4(0, 0, 0, 0), 1.0) : + ambient_occlusion_disabled_data(); for (int i = 0; i < 2; i++) { Ray ray; @@ -176,13 +164,13 @@ OcclusionData occlusion_search(vec3 vP, ScreenSpaceRay ssray; ssray = raytrace_screenspace_ray_create(ray); - data.horizons[0 + i * 2] = search_horizon( + data.horizons[0 + i * 2] = ambient_ambient_occlusion_search_horizon( vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); ray.direction = -ray.direction; ssray = raytrace_screenspace_ray_create(ray); - data.horizons[1 + i * 2] = -search_horizon( + data.horizons[1 + i * 2] = -ambient_ambient_occlusion_search_horizon( vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); /* Rotate 90 degrees. */ @@ -192,7 +180,9 @@ OcclusionData occlusion_search(vec3 vP, return data; } -vec2 clamp_horizons_to_hemisphere(vec2 horizons, float angle_N, const float inverted) +vec2 ambient_occlusion_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; @@ -208,15 +198,15 @@ vec2 clamp_horizons_to_hemisphere(vec2 horizons, float angle_N, const float inve return horizons; } -void occlusion_eval(OcclusionData data, - ivec2 texel, - vec3 V, - vec3 N, - vec3 Ng, - const float inverted, - out float visibility, - out float visibility_error, - out vec3 bent_normal) +void ambient_occlusion_eval(OcclusionData data, + ivec2 texel, + vec3 V, + vec3 N, + vec3 Ng, + const float inverted, + out float visibility, + out float visibility_error, + out vec3 bent_normal) { /* No error by default. */ visibility_error = 1.0; @@ -242,8 +232,8 @@ void occlusion_eval(OcclusionData data, return; } - vec2 noise = get_ao_noise(texel); - vec2 dir = get_ao_dir(noise.x); + vec2 noise = ambient_occlusion_get_noise(texel); + vec2 dir = ambient_occlusion_get_dir(noise.x); visibility_error = 0.0; visibility = 0.0; @@ -269,7 +259,7 @@ void occlusion_eval(OcclusionData data, float angle_Ng = sign(Ng_sin) * fast_acos(Ng_cos); float angle_N = sign(N_sin) * fast_acos(N_cos); /* Clamp horizons to hemisphere around shading normal. */ - h = clamp_horizons_to_hemisphere(h, angle_N, inverted); + h = ambient_occlusion_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. @@ -279,7 +269,7 @@ void occlusion_eval(OcclusionData data, /* 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_horizons_to_hemisphere(h, angle_Ng, inverted); + h = ambient_occlusion_clamp_horizons_to_hemisphere(h, angle_Ng, inverted); /* Inner integral (Eq. 7). */ float a = dot(-cos(2.0 * h - angle_N) + N_cos + 2.0 * h * N_sin, vec2(0.25)); @@ -311,7 +301,7 @@ void occlusion_eval(OcclusionData data, /* Multibounce approximation base on surface albedo. * Page 78 in the .pdf version. */ -float gtao_multibounce(float visibility, vec3 albedo) +float ambient_occlusion_multibounce(float visibility, vec3 albedo) { if (!AO_MULTI_BOUNCE) { return visibility; @@ -328,24 +318,24 @@ float gtao_multibounce(float visibility, vec3 albedo) return max(x, ((x * a + b) * x + c) * x); } -float diffuse_occlusion(OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng) +float ambient_occlusion_diffuse(OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng) { vec3 unused; float unused_error; float visibility; - occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, unused); + ambient_occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, unused); return saturate(visibility); } -float diffuse_occlusion( +float ambient_occlusion_diffuse( OcclusionData data, ivec2 texel, vec3 V, vec3 N, vec3 Ng, vec3 albedo, out vec3 bent_normal) { float visibility; float unused_error; - occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, bent_normal); + ambient_occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, unused_error, bent_normal); - visibility = gtao_multibounce(visibility, albedo); + visibility = ambient_occlusion_multibounce(visibility, albedo); return saturate(visibility); } @@ -357,7 +347,7 @@ float diffuse_occlusion( * dist : Distance between caps (radians between centers of caps) * NOTE: Result is divided by pi to save one multiply. */ -float spherical_cap_intersection(float radius1, float radius2, float dist) +float ambient_occlusion_spherical_cap_intersection(float radius1, float radius2, float dist) { /* From "Ambient Aperture Lighting" by Chris Oat * Slide 15. */ @@ -381,13 +371,13 @@ float spherical_cap_intersection(float radius1, float radius2, float dist) return area; } -float specular_occlusion( +float ambient_occlusion_specular( OcclusionData data, ivec2 texel, vec3 V, vec3 N, float roughness, inout vec3 specular_dir) { vec3 visibility_dir; float visibility_error; float visibility; - occlusion_eval(data, texel, V, N, N, 0.0, visibility, visibility_error, visibility_dir); + ambient_occlusion_eval(data, texel, V, N, N, 0.0, visibility, visibility_error, visibility_dir); /* Correct visibility error for very sharp surfaces. */ visibility *= mix(safe_rcp(visibility_error), 1.0, roughness); @@ -397,13 +387,16 @@ float specular_occlusion( /* Visibility to cone angle (eq. 18). */ float vis_angle = fast_acos(sqrt(1 - visibility)); /* Roughness to cone angle (eq. 26). */ - float spec_angle = max(0.00990998744964599609375, fast_acos(cone_cosine(roughness))); + float spec_angle = max(0.00990998744964599609375, + fast_acos(ambient_occlusion_cone_cosine(roughness))); /* Angle between cone axes. */ float cone_cone_dist = fast_acos(saturate(dot(visibility_dir, specular_dir))); float cone_nor_dist = fast_acos(saturate(dot(N, specular_dir))); - float isect_solid_angle = spherical_cap_intersection(vis_angle, spec_angle, cone_cone_dist); - float specular_solid_angle = spherical_cap_intersection(M_PI_2, spec_angle, cone_nor_dist); + float isect_solid_angle = ambient_occlusion_spherical_cap_intersection( + vis_angle, spec_angle, cone_cone_dist); + float specular_solid_angle = ambient_occlusion_spherical_cap_intersection( + M_PI_2, spec_angle, cone_nor_dist); float specular_occlusion = isect_solid_angle / specular_solid_angle; /* Mix because it is unstable in unoccluded areas. */ float tmp = saturate(pow8(visibility)); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl index 2729d1e924d..d6c4db09a3c 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl @@ -78,13 +78,13 @@ void main() vec3 Ng = transform_direction(ViewMatrixInverse, vNg); vec3 N = imageLoad(in_normal_img, texel).xyz; - // OcclusionData data = unpack_occlusion_data(texelFetch(horizons_tx, texel, 0)); - OcclusionData data = occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); + OcclusionData data = ambient_occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); float visibility; float visibility_error_out; vec3 bent_normal_out; - occlusion_eval(data, texel, V, N, Ng, 0.0, visibility, visibility_error_out, bent_normal_out); + ambient_occlusion_eval( + data, texel, V, N, Ng, 0.0, visibility, visibility_error_out, bent_normal_out); /* Scale by user factor */ visibility = saturate(visibility); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl index c66e24ebf1b..aab6f08d269 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_deferred_light_frag.glsl @@ -9,7 +9,6 @@ #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() { diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index a80494709c6..e907f80abe4 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -198,15 +198,16 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) return Closure(0); } -float ambient_occlusion_eval(vec3 normal, - float max_distance, - const float inverted, - const float sample_count) +float ambient_ambient_occlusion_eval(vec3 normal, + float max_distance, + const float inverted, + const float sample_count) { #if defined(GPU_FRAGMENT_SHADER) && defined(MAT_AO) && !defined(MAT_DEPTH) && !defined(MAT_SHADOW) vec3 vP = transform_point(ViewMatrix, g_data.P); ivec2 texel = ivec2(gl_FragCoord.xy); - OcclusionData data = occlusion_search(vP, hiz_tx, texel, max_distance, inverted, sample_count); + OcclusionData data = ambient_occlusion_search( + vP, hiz_tx, texel, max_distance, inverted, sample_count); vec3 V = cameraVec(g_data.P); vec3 N = g_data.N; @@ -214,7 +215,7 @@ float ambient_occlusion_eval(vec3 normal, float unused_error, visibility; vec3 unused; - occlusion_eval(data, texel, V, N, Ng, inverted, visibility, unused_error, unused); + ambient_occlusion_eval(data, texel, V, N, Ng, inverted, visibility, unused_error, unused); return visibility; #else return 1.0; -- 2.30.2 From aa9f73b535f4466ee95ea1fd3a295ddfdc9331a6 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 16 Jun 2023 20:10:18 +0200 Subject: [PATCH 19/25] Rename AO to Ambient Occlusion --- source/blender/draw/CMakeLists.txt | 10 +++++----- ...eevee_ao.cc => eevee_ambient_occlusion.cc} | 6 +++--- ...eevee_ao.hh => eevee_ambient_occlusion.hh} | 0 .../draw/engines/eevee_next/eevee_defines.hh | 2 +- .../draw/engines/eevee_next/eevee_instance.cc | 4 ++-- .../draw/engines/eevee_next/eevee_instance.hh | 6 +++--- .../draw/engines/eevee_next/eevee_pipeline.cc | 8 ++++---- .../draw/engines/eevee_next/eevee_shader.cc | 8 ++++---- .../draw/engines/eevee_next/eevee_shader.hh | 2 +- .../draw/engines/eevee_next/eevee_view.cc | 2 +- ...evee_ambient_occlusion_horizons_frag.glsl} | 2 +- ....glsl => eevee_ambient_occlusion_lib.glsl} | 0 ...=> eevee_ambient_occlusion_pass_comp.glsl} | 2 +- .../shaders/eevee_nodetree_lib.glsl | 14 ++++++++----- .../shaders/eevee_surf_deferred_frag.glsl | 2 +- .../shaders/eevee_surf_forward_frag.glsl | 2 +- ...nfo.hh => eevee_ambient_occlusion_info.hh} | 20 +++++++++---------- .../shaders/infos/eevee_deferred_info.hh | 2 +- .../shaders/infos/eevee_material_info.hh | 4 ++-- source/blender/gpu/CMakeLists.txt | 2 +- 20 files changed, 51 insertions(+), 47 deletions(-) rename source/blender/draw/engines/eevee_next/{eevee_ao.cc => eevee_ambient_occlusion.cc} (97%) rename source/blender/draw/engines/eevee_next/{eevee_ao.hh => eevee_ambient_occlusion.hh} (100%) rename source/blender/draw/engines/eevee_next/shaders/{eevee_ao_horizons_frag.glsl => eevee_ambient_occlusion_horizons_frag.glsl} (92%) rename source/blender/draw/engines/eevee_next/shaders/{eevee_ao_lib.glsl => eevee_ambient_occlusion_lib.glsl} (100%) rename source/blender/draw/engines/eevee_next/shaders/{eevee_ao_pass_comp.glsl => eevee_ambient_occlusion_pass_comp.glsl} (98%) rename source/blender/draw/engines/eevee_next/shaders/infos/{eevee_ao_info.hh => eevee_ambient_occlusion_info.hh} (55%) diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 92584ae9e15..29dcd7e8b5f 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -138,7 +138,7 @@ set(SRC engines/eevee/eevee_subsurface.c engines/eevee/eevee_temporal_sampling.c engines/eevee/eevee_volumes.c - engines/eevee_next/eevee_ao.cc + engines/eevee_next/eevee_ambient_occlusion.cc engines/eevee_next/eevee_camera.cc engines/eevee_next/eevee_cryptomatte.cc engines/eevee_next/eevee_depth_of_field.cc @@ -280,7 +280,7 @@ set(SRC engines/eevee/eevee_lut.h engines/eevee/eevee_private.h engines/eevee/engine_eevee_shared_defines.h - engines/eevee_next/eevee_ao.hh + engines/eevee_next/eevee_ambient_occlusion.hh engines/eevee_next/eevee_camera.hh engines/eevee_next/eevee_cryptomatte.hh engines/eevee_next/eevee_depth_of_field.hh @@ -439,9 +439,9 @@ set(GLSL_SRC engines/eevee/shaders/infos/engine_eevee_legacy_shared.h engines/eevee/engine_eevee_shared_defines.h - engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl - engines/eevee_next/shaders/eevee_ao_lib.glsl - engines/eevee_next/shaders/eevee_ao_pass_comp.glsl + engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl + engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl + engines/eevee_next/shaders/eevee_ambient_occlusion_pass_comp.glsl engines/eevee_next/shaders/eevee_attributes_lib.glsl engines/eevee_next/shaders/eevee_camera_lib.glsl engines/eevee_next/shaders/eevee_colorspace_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.cc b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc similarity index 97% rename from source/blender/draw/engines/eevee_next/eevee_ao.cc rename to source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc index 330725afa27..1c9c516d1e1 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ao.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc @@ -23,7 +23,7 @@ #pragma once -#include "eevee_ao.hh" +#include "eevee_ambient_occlusion.hh" #include "eevee_instance.hh" #include "GPU_capabilities.h" @@ -72,7 +72,7 @@ void AmbientOcclusion::sync() if (render_pass_enabled_) { render_pass_ps_.init(); - render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AO_PASS)); + render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AMBIENT_OCCLUSION_PASS)); bind_resources(&render_pass_ps_); render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); @@ -80,7 +80,7 @@ void AmbientOcclusion::sync() render_pass_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS & GPU_BARRIER_TEXTURE_FETCH); render_pass_ps_.dispatch( - math::divide_ceil(inst_.film.render_extent_get(), int2(AO_PASS_TILE_SIZE))); + math::divide_ceil(inst_.film.render_extent_get(), int2(AMBIENT_OCCLUSION_PASS_TILE_SIZE))); } } diff --git a/source/blender/draw/engines/eevee_next/eevee_ao.hh b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh similarity index 100% rename from source/blender/draw/engines/eevee_next/eevee_ao.hh rename to source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index a61f763b579..7e9b10a7b50 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -88,7 +88,7 @@ #define DOF_RESOLVE_GROUP_SIZE (DOF_TILES_SIZE * 2) /* Ambient Occlusion. */ -#define AO_PASS_TILE_SIZE 16 +#define AMBIENT_OCCLUSION_PASS_TILE_SIZE 16 /* Resource bindings. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 03183e84519..6d7f503cbb7 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -66,7 +66,7 @@ void Instance::init(const int2 &output_res, sampling.init(scene); camera.init(); film.init(output_res, output_rect); - ao.init(); + ambient_occlusion.init(); velocity.init(); depth_of_field.init(); shadows.init(); @@ -122,7 +122,7 @@ void Instance::begin_sync() world.sync(); film.sync(); render_buffers.sync(); - ao.sync(); + ambient_occlusion.sync(); irradiance_cache.sync(); } diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index ed3c59adf19..a9332eefad4 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -16,7 +16,7 @@ #include "DNA_lightprobe_types.h" #include "DRW_render.h" -#include "eevee_ao.hh" +#include "eevee_ambient_occlusion.hh" #include "eevee_camera.hh" #include "eevee_cryptomatte.hh" #include "eevee_depth_of_field.hh" @@ -54,7 +54,7 @@ class Instance { PipelineModule pipelines; ShadowModule shadows; LightModule lights; - AmbientOcclusion ao; + AmbientOcclusion ambient_occlusion; VelocityModule velocity; MotionBlurModule motion_blur; DepthOfField depth_of_field; @@ -102,7 +102,7 @@ class Instance { pipelines(*this), shadows(*this), lights(*this), - ao(*this), + ambient_occlusion(*this), velocity(*this), motion_blur(*this), depth_of_field(*this), diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index b7ad18bdf03..d0845da47ba 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -150,7 +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_); + inst_.ambient_occlusion.bind_resources(&opaque_ps_); } opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided"); @@ -176,7 +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); + inst_.ambient_occlusion.bind_resources(&sub); } } @@ -330,7 +330,7 @@ void DeferredLayer::begin_sync() inst_.sampling.bind_resources(&gbuffer_ps_); inst_.cryptomatte.bind_resources(&gbuffer_ps_); - inst_.ao.bind_resources(&gbuffer_ps_); + inst_.ambient_occlusion.bind_resources(&gbuffer_ps_); } DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_EQUAL | @@ -373,7 +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_); + inst_.ambient_occlusion.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); diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index 2ca6f682dcd..c0ef2c40ae4 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -82,9 +82,9 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_ { switch (shader_type) { case AO_HORIZONS: - return "eevee_ao_horizons"; - case AO_PASS: - return "eevee_ao_pass"; + return "eevee_ambient_occlusion_horizons"; + case AMBIENT_OCCLUSION_PASS: + return "eevee_ambient_occlusion_pass"; case FILM_FRAG: return "eevee_film_frag"; case FILM_COMP: @@ -248,7 +248,7 @@ void ShaderModule::material_create_info_ammend(GPUMaterial *gpumat, GPUCodegenOu ELEM(pipeline_type, MAT_PIPE_FORWARD, MAT_PIPE_DEFERRED) && ELEM(geometry_type, MAT_GEOM_MESH, MAT_GEOM_CURVES)) { - info.define("MAT_AO"); + info.define("MAT_AMBIENT_OCCLUSION"); } if (GPU_material_flag_get(gpumat, GPU_MATFLAG_TRANSPARENT)) { diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index 050bd440d16..d022d52f07a 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -28,7 +28,7 @@ namespace blender::eevee { /* Keep alphabetical order and clean prefix. */ enum eShaderType { AO_HORIZONS = 0, - AO_PASS, + AMBIENT_OCCLUSION_PASS = 0, FILM_FRAG, FILM_COMP, diff --git a/source/blender/draw/engines/eevee_next/eevee_view.cc b/source/blender/draw/engines/eevee_next/eevee_view.cc index 365c459eb32..5b06a654718 100644 --- a/source/blender/draw/engines/eevee_next/eevee_view.cc +++ b/source/blender/draw/engines/eevee_next/eevee_view.cc @@ -139,7 +139,7 @@ void ShadingView::render() inst_.irradiance_cache.debug_draw(render_view_new_, combined_fb_); - inst_.ao.render_pass(render_view_new_); + inst_.ambient_occlusion.render_pass(render_view_new_); GPUTexture *combined_final_tx = render_postfx(rbufs.combined_tx); inst_.film.accumulate(sub_view_, combined_final_tx); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl similarity index 92% rename from source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl rename to source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl index df535c079b8..8ebce89bbb3 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_horizons_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl @@ -2,7 +2,7 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) #pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl) /** * This shader only compute maximum horizon angles for each directions. diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl similarity index 100% rename from source/blender/draw/engines/eevee_next/shaders/eevee_ao_lib.glsl rename to source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_pass_comp.glsl similarity index 98% rename from source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl rename to source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_pass_comp.glsl index d6c4db09a3c..d7fb7ab22e0 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ao_pass_comp.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_pass_comp.glsl @@ -2,7 +2,7 @@ #pragma BLENDER_REQUIRE(common_view_lib.glsl) #pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_ao_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl) /* Similar to https://atyuwen.github.io/posts/normal-reconstruction/. * This samples the depth buffer 4 time for each direction to get the most correct diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl index e907f80abe4..6ec88f48b76 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_nodetree_lib.glsl @@ -198,12 +198,16 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) return Closure(0); } -float ambient_ambient_occlusion_eval(vec3 normal, - float max_distance, - const float inverted, - const float sample_count) +float ambient_occlusion_eval(vec3 normal, + float max_distance, + const float inverted, + const float sample_count) { -#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_AO) && !defined(MAT_DEPTH) && !defined(MAT_SHADOW) + /* Avoid multiline preprocesor conditionals. + * Some drivers don't handle them correctly. */ + // clang-format off +#if defined(GPU_FRAGMENT_SHADER) && defined(MAT_AMBIENT_OCCLUSION) && !defined(MAT_DEPTH) && !defined(MAT_SHADOW) + // clang-format on vec3 vP = transform_point(ViewMatrix, g_data.P); ivec2 texel = ivec2(gl_FragCoord.xy); OcclusionData data = ambient_occlusion_search( diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl index a02425c7e54..e3f214ccbb1 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_deferred_frag.glsl @@ -10,7 +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) +#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl) #pragma BLENDER_REQUIRE(eevee_surf_lib.glsl) #pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl) #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl index 2122880f228..fb4fc6361af 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_surf_forward_frag.glsl @@ -8,7 +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_ambient_occlusion_lib.glsl) #pragma BLENDER_REQUIRE(eevee_light_eval_lib.glsl) #pragma BLENDER_REQUIRE(eevee_nodetree_lib.glsl) #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh similarity index 55% rename from source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh rename to source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh index 69de7e8dbe4..6d6e3400fd6 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh @@ -7,24 +7,24 @@ GPU_SHADER_CREATE_INFO(eevee_raytrace_data) .additional_info("draw_view", "eevee_shared", "eevee_hiz_data") .uniform_buf(RAYTRACE_BUF_SLOT, "RayTracingData", "rt_buf"); -GPU_SHADER_CREATE_INFO(eevee_ao_data) +GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_data) .additional_info("eevee_raytrace_data", "eevee_sampling_data", "eevee_utility_texture") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); -GPU_SHADER_CREATE_INFO(eevee_ao_horizons_data) - .additional_info("eevee_ao_data") +GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_horizons_data) + .additional_info("eevee_ambient_occlusion_data") .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx"); -GPU_SHADER_CREATE_INFO(eevee_ao_horizons) - .additional_info("eevee_ao_data", "draw_fullscreen") - .fragment_source("eevee_ao_horizons_frag.glsl") +GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_horizons) + .additional_info("eevee_ambient_occlusion_data", "draw_fullscreen") + .fragment_source("eevee_ambient_occlusion_horizons_frag.glsl") .fragment_out(0, Type::VEC4, "out_horizons") .do_static_compilation(true); -GPU_SHADER_CREATE_INFO(eevee_ao_pass) - .additional_info("eevee_ao_horizons_data") - .compute_source("eevee_ao_pass_comp.glsl") - .local_group_size(AO_PASS_TILE_SIZE, AO_PASS_TILE_SIZE) +GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_pass) + .additional_info("eevee_ambient_occlusion_horizons_data") + .compute_source("eevee_ambient_occlusion_pass_comp.glsl") + .local_group_size(AMBIENT_OCCLUSION_PASS_TILE_SIZE, AMBIENT_OCCLUSION_PASS_TILE_SIZE) .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "in_normal_img") .image(1, GPU_RG16F, Qualifier::WRITE, ImageType::FLOAT_2D, "out_ao_img") .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index 2c37e14c1ac..b408b8cf10e 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -41,7 +41,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light) "eevee_deferred_base", "eevee_hiz_data", "eevee_render_pass_out", - "eevee_ao_horizons_data", + "eevee_ambient_occlusion_horizons_data", "draw_view", "draw_fullscreen") .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index f553b028a03..b4b4a104618 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -110,7 +110,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_deferred) /* Added at runtime because of test shaders not having `node_tree`. */ // "eevee_render_pass_out", "eevee_cryptomatte_out", - "eevee_ao_data"); + "eevee_ambient_occlusion_data"); GPU_SHADER_CREATE_INFO(eevee_surf_forward) .vertex_out(eevee_surf_iface) @@ -125,7 +125,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward) "eevee_utility_texture", "eevee_sampling_data", "eevee_shadow_data", - "eevee_ao_horizons_data" + "eevee_ambient_occlusion_horizons_data" /* Optionally added depending on the material. */ // "eevee_render_pass_out", // "eevee_cryptomatte_out", diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 958de82aed8..cab1d63c08f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -643,7 +643,7 @@ list(APPEND INC ${CMAKE_CURRENT_BINARY_DIR}) set(SRC_SHADER_CREATE_INFOS ../draw/engines/basic/shaders/infos/basic_depth_info.hh - ../draw/engines/eevee_next/shaders/infos/eevee_ao_info.hh + ../draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_depth_of_field_info.hh ../draw/engines/eevee_next/shaders/infos/eevee_film_info.hh -- 2.30.2 From dda8772851a330ae48f356557a1038e461adda53 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Fri, 16 Jun 2023 20:30:29 +0200 Subject: [PATCH 20/25] Remove horizons pass --- source/blender/draw/CMakeLists.txt | 1 - .../eevee_next/eevee_ambient_occlusion.cc | 57 +++---------------- .../eevee_next/eevee_ambient_occlusion.hh | 22 +------ .../draw/engines/eevee_next/eevee_defines.hh | 1 - .../draw/engines/eevee_next/eevee_shader.cc | 2 - .../draw/engines/eevee_next/eevee_shader.hh | 1 - ...eevee_ambient_occlusion_horizons_frag.glsl | 26 --------- .../infos/eevee_ambient_occlusion_info.hh | 12 +--- .../shaders/infos/eevee_deferred_info.hh | 1 - .../shaders/infos/eevee_material_info.hh | 2 +- 10 files changed, 13 insertions(+), 112 deletions(-) delete mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 29dcd7e8b5f..d563fac85ef 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -439,7 +439,6 @@ set(GLSL_SRC engines/eevee/shaders/infos/engine_eevee_legacy_shared.h engines/eevee/engine_eevee_shared_defines.h - engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl engines/eevee_next/shaders/eevee_ambient_occlusion_pass_comp.glsl engines/eevee_next/shaders/eevee_attributes_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc index 1c9c516d1e1..1cfbb6cddf0 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc @@ -41,67 +41,28 @@ void AmbientOcclusion::init() (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO); render_pass_enabled_ = data_.enabled && inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; - if (!data_.enabled) { - /* Early return. */ - data_.push_update(); - horizons_tx_.free(); - return; - } - data_.distance = scene->eevee.gtao_distance; data_.quality = scene->eevee.gtao_quality; data_.push_update(); - - eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ; - horizons_tx_.ensure_2d(GPU_RGBA8, inst_.film.render_extent_get(), usage); } void AmbientOcclusion::sync() { - if (!data_.enabled) { + if (!render_pass_enabled_) { return; } - horizons_search_ps_.init(); - horizons_search_ps_.state_set(DRW_STATE_WRITE_COLOR); - horizons_search_ps_.shader_set(inst_.shaders.static_shader_get(AO_HORIZONS)); - bind_resources(&horizons_search_ps_, false); + render_pass_ps_.init(); + render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AMBIENT_OCCLUSION_PASS)); + bind_resources(&render_pass_ps_); - horizons_search_ps_.draw_procedural(GPU_PRIM_TRIS, 1, 3); + render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); + render_pass_ps_.bind_image("out_ao_img", &rp_ao_tx_); - if (render_pass_enabled_) { - render_pass_ps_.init(); - render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AMBIENT_OCCLUSION_PASS)); - bind_resources(&render_pass_ps_); - - render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); - render_pass_ps_.bind_image("out_ao_img", &rp_ao_tx_); - - render_pass_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS & GPU_BARRIER_TEXTURE_FETCH); - render_pass_ps_.dispatch( - math::divide_ceil(inst_.film.render_extent_get(), int2(AMBIENT_OCCLUSION_PASS_TILE_SIZE))); - } -} - -void AmbientOcclusion::render(View &view) -{ - if (!data_.enabled) { - return; - } - - inst_.hiz_buffer.update(); - - fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(horizons_tx_)); - fb_.bind(); - inst_.manager->submit(horizons_search_ps_, view); - - if (GPU_mip_render_workaround() || - GPU_type_matches_ex(GPU_DEVICE_INTEL_UHD, GPU_OS_WIN, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL)) - { - /* Fix dot corruption on intel HD5XX/HD6XX series. */ - GPU_flush(); - } + render_pass_ps_.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS & GPU_BARRIER_TEXTURE_FETCH); + render_pass_ps_.dispatch( + math::divide_ceil(inst_.film.render_extent_get(), int2(AMBIENT_OCCLUSION_PASS_TILE_SIZE))); } void AmbientOcclusion::render_pass(View &view) diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh index f7337a7b789..6c4352dd4a2 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh @@ -30,13 +30,6 @@ class AmbientOcclusion { bool render_pass_enabled_; AODataBuf data_; - - Texture dummy_horizons_tx_; - Texture horizons_tx_; - - Framebuffer fb_ = {"AO"}; - - PassSimple horizons_search_ps_ = {"AO Horizons Search"}; PassSimple render_pass_ps_ = {"AO Render Pass"}; /* Used as pointers for texture views in the AO Render Pass. */ @@ -44,13 +37,7 @@ class AmbientOcclusion { GPUTexture *rp_ao_tx_ = nullptr; public: - AmbientOcclusion(Instance &inst) : inst_(inst) - { - dummy_horizons_tx_.ensure_2d(GPU_RGBA8, - int2(1), - GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_SHADER_READ, - float4(0)); - }; + AmbientOcclusion(Instance &inst) : inst_(inst){}; ~AmbientOcclusion(){}; void init(); @@ -60,18 +47,13 @@ class AmbientOcclusion { void render(View &view); void render_pass(View &view); - template - void bind_resources(draw::detail::PassBase *pass, bool bind_horizons = true) + template void bind_resources(draw::detail::PassBase *pass) { inst_.sampling.bind_resources(pass); inst_.hiz_buffer.bind_resources(pass); inst_.raytracing.bind_resources(pass); pass->bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); pass->bind_ubo(AO_BUF_SLOT, &data_); - if (bind_horizons) { - pass->bind_texture(AO_HORIZONS_TEX_SLOT, - data_.enabled ? &horizons_tx_ : &dummy_horizons_tx_); - } } }; diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index 7e9b10a7b50..66d9ec92c70 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -99,7 +99,6 @@ /* Only during surface shading (forward and deferred eval). */ #define SHADOW_TILEMAPS_TEX_SLOT 4 #define SHADOW_ATLAS_TEX_SLOT 5 -#define AO_HORIZONS_TEX_SLOT 6 /* Only during shadow rendering. */ #define SHADOW_RENDER_MAP_SLOT 4 diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.cc b/source/blender/draw/engines/eevee_next/eevee_shader.cc index c0ef2c40ae4..781161caf11 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.cc +++ b/source/blender/draw/engines/eevee_next/eevee_shader.cc @@ -81,8 +81,6 @@ ShaderModule::~ShaderModule() const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_type) { switch (shader_type) { - case AO_HORIZONS: - return "eevee_ambient_occlusion_horizons"; case AMBIENT_OCCLUSION_PASS: return "eevee_ambient_occlusion_pass"; case FILM_FRAG: diff --git a/source/blender/draw/engines/eevee_next/eevee_shader.hh b/source/blender/draw/engines/eevee_next/eevee_shader.hh index d022d52f07a..535f3711d24 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader.hh @@ -27,7 +27,6 @@ namespace blender::eevee { /* Keep alphabetical order and clean prefix. */ enum eShaderType { - AO_HORIZONS = 0, AMBIENT_OCCLUSION_PASS = 0, FILM_FRAG, diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl deleted file mode 100644 index 8ebce89bbb3..00000000000 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_horizons_frag.glsl +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma BLENDER_REQUIRE(common_view_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_ambient_occlusion_lib.glsl) - -/** - * This shader only compute maximum horizon angles for each directions. - * The final integration is done at the resolve stage with the shading normal. - */ - -void main() -{ - vec2 uvs = uvcoordsvar.xy; - float depth = textureLod(hiz_tx, uvs * hiz_buf.uv_scale, 0.0).r; - vec3 vP = get_view_space_from_depth(uvs, depth); - - OcclusionData data = ambient_occlusion_disabled_data(); - /* Do not trace for background */ - if (depth != 1.0) { - ivec2 texel = ivec2(gl_FragCoord.xy); - data = ambient_occlusion_search(vP, hiz_tx, texel, ao_buf.distance, 0.0, 8.0); - } - - out_horizons = ambient_occlusion_pack_data(data); -} diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh index 6d6e3400fd6..14c4db9e343 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh @@ -11,18 +11,8 @@ GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_data) .additional_info("eevee_raytrace_data", "eevee_sampling_data", "eevee_utility_texture") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); -GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_horizons_data) - .additional_info("eevee_ambient_occlusion_data") - .sampler(AO_HORIZONS_TEX_SLOT, ImageType::FLOAT_2D, "horizons_tx"); - -GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_horizons) - .additional_info("eevee_ambient_occlusion_data", "draw_fullscreen") - .fragment_source("eevee_ambient_occlusion_horizons_frag.glsl") - .fragment_out(0, Type::VEC4, "out_horizons") - .do_static_compilation(true); - GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_pass) - .additional_info("eevee_ambient_occlusion_horizons_data") + .additional_info("eevee_ambient_occlusion_data") .compute_source("eevee_ambient_occlusion_pass_comp.glsl") .local_group_size(AMBIENT_OCCLUSION_PASS_TILE_SIZE, AMBIENT_OCCLUSION_PASS_TILE_SIZE) .image(0, GPU_RGBA16F, Qualifier::READ, ImageType::FLOAT_2D, "in_normal_img") diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh index b408b8cf10e..ba4f149f0b7 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_deferred_info.hh @@ -41,7 +41,6 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light) "eevee_deferred_base", "eevee_hiz_data", "eevee_render_pass_out", - "eevee_ambient_occlusion_horizons_data", "draw_view", "draw_fullscreen") .do_static_compilation(true); diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh index b4b4a104618..20527ab439f 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_material_info.hh @@ -125,7 +125,7 @@ GPU_SHADER_CREATE_INFO(eevee_surf_forward) "eevee_utility_texture", "eevee_sampling_data", "eevee_shadow_data", - "eevee_ambient_occlusion_horizons_data" + "eevee_ambient_occlusion_data" /* Optionally added depending on the material. */ // "eevee_render_pass_out", // "eevee_cryptomatte_out", -- 2.30.2 From 746dc746c183ca253c2fc44b1d55264dbc7ca625 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Wed, 28 Jun 2023 21:03:27 +0200 Subject: [PATCH 21/25] Fix AO and Shadow Final Render --- .../draw/engines/eevee_next/eevee_film.hh | 18 +++--------------- .../draw/engines/eevee_next/eevee_instance.cc | 5 ++--- .../engines/eevee_next/eevee_renderbuffers.cc | 4 ++-- .../engines/eevee_next/eevee_renderbuffers.hh | 18 ++++++++++++++++++ .../eevee_next/shaders/eevee_film_lib.glsl | 4 ++-- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_film.hh b/source/blender/draw/engines/eevee_next/eevee_film.hh index a13d25c3d80..2d5751aa803 100644 --- a/source/blender/draw/engines/eevee_next/eevee_film.hh +++ b/source/blender/draw/engines/eevee_next/eevee_film.hh @@ -105,13 +105,12 @@ class Film { int cryptomatte_layer_max_get() const; int cryptomatte_layer_len_get() const; + /** WARNING: Film and RenderBuffers use different storage types for AO and Shadow. */ static ePassStorageType pass_storage_type(eViewLayerEEVEEPassType pass_type) { switch (pass_type) { case EEVEE_RENDER_PASS_Z: case EEVEE_RENDER_PASS_MIST: - case EEVEE_RENDER_PASS_SHADOW: - case EEVEE_RENDER_PASS_AO: return PASS_STORAGE_VALUE; case EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT: case EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET: @@ -124,19 +123,8 @@ class Film { static bool pass_is_float3(eViewLayerEEVEEPassType pass_type) { - switch (pass_type) { - case EEVEE_RENDER_PASS_NORMAL: - case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: - case EEVEE_RENDER_PASS_DIFFUSE_COLOR: - case EEVEE_RENDER_PASS_SPECULAR_LIGHT: - case EEVEE_RENDER_PASS_SPECULAR_COLOR: - case EEVEE_RENDER_PASS_VOLUME_LIGHT: - case EEVEE_RENDER_PASS_EMIT: - case EEVEE_RENDER_PASS_ENVIRONMENT: - return true; - default: - return false; - } + return pass_storage_type(pass_type) == PASS_STORAGE_COLOR && + pass_type != EEVEE_RENDER_PASS_COMBINED; } /* Returns layer offset in the accumulation texture. -1 if the pass is not enabled. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index 7f7cccaef54..c240b8fe8bd 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -448,9 +448,8 @@ void Instance::update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB"); CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB"); CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB"); - /* TODO: CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB"); - * CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB"); - * When available they should be converted from Value textures to RGB. */ + CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB"); + CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB"); LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) { if ((aov->flag & AOV_CONFLICT) != 0) { diff --git a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc index f4a36c5556e..913ee1160e2 100644 --- a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc +++ b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.cc @@ -33,8 +33,8 @@ void RenderBuffers::sync() auto pass_index_get = [&](eViewLayerEEVEEPassType pass_type, int dependent_passes = 0) { if (enabled_passes & (pass_type | dependent_passes)) { - return inst_.film.pass_storage_type(pass_type) == PASS_STORAGE_COLOR ? data.color_len++ : - data.value_len++; + return pass_storage_type(pass_type) == PASS_STORAGE_COLOR ? data.color_len++ : + data.value_len++; } return -1; }; diff --git a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh index a6dd626b2e1..36d176c6a91 100644 --- a/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh +++ b/source/blender/draw/engines/eevee_next/eevee_renderbuffers.hh @@ -40,6 +40,24 @@ class RenderBuffers { public: RenderBuffers(Instance &inst) : inst_(inst){}; + /** WARNING: RenderBuffers and Film use different storage types for AO and Shadow. */ + static ePassStorageType pass_storage_type(eViewLayerEEVEEPassType pass_type) + { + switch (pass_type) { + case EEVEE_RENDER_PASS_Z: + case EEVEE_RENDER_PASS_MIST: + case EEVEE_RENDER_PASS_SHADOW: + case EEVEE_RENDER_PASS_AO: + return PASS_STORAGE_VALUE; + case EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT: + case EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET: + case EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL: + return PASS_STORAGE_CRYPTOMATTE; + default: + return PASS_STORAGE_COLOR; + } + } + void sync(); /* Acquires (also ensures) the render buffer before rendering to them. */ diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl index cb3285f7266..4a01d72bcae 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_film_lib.glsl @@ -717,8 +717,8 @@ void film_process_data(ivec2 texel_film, out vec4 out_color, out float out_depth film_store_color(dst, film_buf.diffuse_color_id, diffuse_color_accum, out_color); film_store_color(dst, film_buf.specular_color_id, specular_color_accum, out_color); film_store_color(dst, film_buf.environment_id, environment_accum, out_color); - film_store_value(dst, film_buf.shadow_id, shadow_accum, out_color); - film_store_value(dst, film_buf.ambient_occlusion_id, ao_accum, out_color); + film_store_color(dst, film_buf.shadow_id, vec4(vec3(shadow_accum), 1.0), out_color); + film_store_color(dst, film_buf.ambient_occlusion_id, vec4(vec3(ao_accum), 1.0), out_color); film_store_value(dst, film_buf.mist_id, mist_accum, out_color); } -- 2.30.2 From 87e9895f911675b1aafa03462f28212e1bec0500 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 29 Jun 2023 17:12:04 +0200 Subject: [PATCH 22/25] Remove AOData.enabled --- scripts/startup/bl_ui/properties_render.py | 8 +------- .../draw/engines/eevee_next/eevee_ambient_occlusion.cc | 5 +---- .../draw/engines/eevee_next/eevee_shader_shared.hh | 1 - .../shaders/eevee_ambient_occlusion_lib.glsl | 10 ---------- 4 files changed, 2 insertions(+), 22 deletions(-) diff --git a/scripts/startup/bl_ui/properties_render.py b/scripts/startup/bl_ui/properties_render.py index 813f5a8cf62..372675b3e9f 100644 --- a/scripts/startup/bl_ui/properties_render.py +++ b/scripts/startup/bl_ui/properties_render.py @@ -154,18 +154,12 @@ class RENDER_PT_eevee_next_ambient_occlusion(RenderButtonsPanel, Panel): def poll(cls, context): return (context.engine in cls.COMPAT_ENGINES) - def draw_header(self, context): - scene = context.scene - props = scene.eevee - self.layout.prop(props, "use_gtao", text="") - def draw(self, context): layout = self.layout layout.use_property_split = True scene = context.scene props = scene.eevee - - layout.active = props.use_gtao + col = layout.column() col.prop(props, "gtao_distance") col.prop(props, "gtao_quality") diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc index 1cfbb6cddf0..039877801c6 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc @@ -36,10 +36,7 @@ namespace blender::eevee { void AmbientOcclusion::init() { - const Scene *scene = inst_.scene; - data_.enabled = (scene->eevee.flag & SCE_EEVEE_GTAO_ENABLED) || - (inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO); - render_pass_enabled_ = data_.enabled && inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; + render_pass_enabled_ = inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; data_.distance = scene->eevee.gtao_distance; data_.quality = scene->eevee.gtao_quality; diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 0fd54468390..3214be05acf 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -1006,7 +1006,6 @@ BLI_STATIC_ASSERT_ALIGN(RayTracingData, 16) * \{ */ struct AOData { - bool1 enabled; float distance; float quality; int _pad0; diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl index e686f7262c8..981a01482ff 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl @@ -142,10 +142,6 @@ OcclusionData ambient_occlusion_search(vec3 vP, const float inverted, const float dir_sample_count) { - if (!ao_buf.enabled) { - return ambient_occlusion_disabled_data(); - } - vec2 noise = ambient_occlusion_get_noise(texel); vec2 dir = ambient_occlusion_get_dir(noise.x); vec2 uv = get_uvs_from_view(vP); @@ -211,12 +207,6 @@ void ambient_occlusion_eval(OcclusionData data, /* No error by default. */ visibility_error = 1.0; - if (!ao_buf.enabled) { - visibility = data.custom_occlusion; - bent_normal = N; - return; - } - bool early_out = (inverted != 0.0) ? (max_v4(abs(data.horizons)) == 0.0) : (min_v4(abs(data.horizons)) == M_PI); if (early_out) { -- 2.30.2 From 34740b8c715478694f590f3fa5b29059a911bf99 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 29 Jun 2023 17:12:57 +0200 Subject: [PATCH 23/25] Clarify min_angle value --- .../eevee_next/shaders/eevee_ambient_occlusion_lib.glsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl index 981a01482ff..961a3d8e428 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl @@ -377,8 +377,9 @@ float ambient_occlusion_specular( /* Visibility to cone angle (eq. 18). */ float vis_angle = fast_acos(sqrt(1 - visibility)); /* Roughness to cone angle (eq. 26). */ - float spec_angle = max(0.00990998744964599609375, - fast_acos(ambient_occlusion_cone_cosine(roughness))); + /* A 0.001 min_angle can generate NaNs on Intel GPUs. See D12508. */ + const float min_angle = 0.00990998744964599609375; + float spec_angle = max(min_angle, fast_acos(ambient_occlusion_cone_cosine(roughness))); /* Angle between cone axes. */ float cone_cone_dist = fast_acos(saturate(dot(visibility_dir, specular_dir))); float cone_nor_dist = fast_acos(saturate(dot(N, specular_dir))); -- 2.30.2 From b69f1e74a2900dcb466d4cbdcf01f8273e52bc18 Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 29 Jun 2023 17:15:45 +0200 Subject: [PATCH 24/25] Remove Raytracing module --- source/blender/draw/CMakeLists.txt | 4 +- .../eevee_next/eevee_ambient_occlusion.cc | 6 +- .../eevee_next/eevee_ambient_occlusion.hh | 1 - .../draw/engines/eevee_next/eevee_defines.hh | 3 +- .../draw/engines/eevee_next/eevee_instance.cc | 1 - .../draw/engines/eevee_next/eevee_instance.hh | 5 +- .../engines/eevee_next/eevee_raytracing.cc | 40 --- .../engines/eevee_next/eevee_raytracing.hh | 42 --- .../engines/eevee_next/eevee_shader_shared.hh | 25 +- .../shaders/eevee_ambient_occlusion_lib.glsl | 6 +- .../shaders/eevee_ray_types_lib.glsl | 63 +++++ .../shaders/eevee_raytrace_lib.glsl | 254 ------------------ .../infos/eevee_ambient_occlusion_info.hh | 10 +- 13 files changed, 81 insertions(+), 379 deletions(-) delete mode 100644 source/blender/draw/engines/eevee_next/eevee_raytracing.cc delete mode 100644 source/blender/draw/engines/eevee_next/eevee_raytracing.hh create mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_ray_types_lib.glsl delete mode 100644 source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 437fb071d53..998e38899fa 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -156,7 +156,6 @@ set(SRC engines/eevee_next/eevee_material.cc engines/eevee_next/eevee_motion_blur.cc engines/eevee_next/eevee_pipeline.cc - engines/eevee_next/eevee_raytracing.cc engines/eevee_next/eevee_renderbuffers.cc engines/eevee_next/eevee_sampling.cc engines/eevee_next/eevee_shader.cc @@ -300,7 +299,6 @@ set(SRC engines/eevee_next/eevee_material.hh engines/eevee_next/eevee_motion_blur.hh engines/eevee_next/eevee_pipeline.hh - engines/eevee_next/eevee_raytracing.hh engines/eevee_next/eevee_renderbuffers.hh engines/eevee_next/eevee_sampling.hh engines/eevee_next/eevee_shader.hh @@ -517,7 +515,7 @@ set(GLSL_SRC engines/eevee_next/shaders/eevee_motion_blur_gather_comp.glsl engines/eevee_next/shaders/eevee_motion_blur_lib.glsl engines/eevee_next/shaders/eevee_nodetree_lib.glsl - engines/eevee_next/shaders/eevee_raytrace_lib.glsl + engines/eevee_next/shaders/eevee_ray_types_lib.glsl engines/eevee_next/shaders/eevee_sampling_lib.glsl engines/eevee_next/shaders/eevee_shadow_debug_frag.glsl engines/eevee_next/shaders/eevee_shadow_lib.glsl diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc index 039877801c6..085319d3ada 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc @@ -38,8 +38,10 @@ void AmbientOcclusion::init() { render_pass_enabled_ = inst_.film.enabled_passes_get() & EEVEE_RENDER_PASS_AO; - data_.distance = scene->eevee.gtao_distance; - data_.quality = scene->eevee.gtao_quality; + data_.distance = inst_.scene->eevee.gtao_distance; + data_.quality = inst_.scene->eevee.gtao_quality; + /* Size is multiplied by 2 because it is applied in NDC [-1..1] range. */ + data_.pixel_size = float2(2.0f) / float2(inst_.film.render_extent_get()); data_.push_update(); } diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh index 6c4352dd4a2..6f3d7507a0e 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh @@ -51,7 +51,6 @@ class AmbientOcclusion { { inst_.sampling.bind_resources(pass); inst_.hiz_buffer.bind_resources(pass); - inst_.raytracing.bind_resources(pass); pass->bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); pass->bind_ubo(AO_BUF_SLOT, &data_); } diff --git a/source/blender/draw/engines/eevee_next/eevee_defines.hh b/source/blender/draw/engines/eevee_next/eevee_defines.hh index 519cfc6fb5b..cb40e554b5f 100644 --- a/source/blender/draw/engines/eevee_next/eevee_defines.hh +++ b/source/blender/draw/engines/eevee_next/eevee_defines.hh @@ -133,8 +133,7 @@ #define CAMERA_BUF_SLOT 6 #define RBUFS_BUF_SLOT 7 /* Skip 8 to avoid overlap with draw_modelmat in hair and gpencil */ -#define RAYTRACE_BUF_SLOT 9 -#define AO_BUF_SLOT 10 +#define AO_BUF_SLOT 9 /* Storage Buffers. */ #define LIGHT_CULL_BUF_SLOT 0 diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.cc b/source/blender/draw/engines/eevee_next/eevee_instance.cc index c240b8fe8bd..56f2cd0f155 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.cc +++ b/source/blender/draw/engines/eevee_next/eevee_instance.cc @@ -71,7 +71,6 @@ void Instance::init(const int2 &output_res, motion_blur.init(); main_view.init(); irradiance_cache.init(); - raytracing.init(); } void Instance::init_light_bake(Depsgraph *depsgraph, draw::Manager *manager) diff --git a/source/blender/draw/engines/eevee_next/eevee_instance.hh b/source/blender/draw/engines/eevee_next/eevee_instance.hh index 380138152bf..0b762a7aedc 100644 --- a/source/blender/draw/engines/eevee_next/eevee_instance.hh +++ b/source/blender/draw/engines/eevee_next/eevee_instance.hh @@ -28,7 +28,6 @@ #include "eevee_material.hh" #include "eevee_motion_blur.hh" #include "eevee_pipeline.hh" -#include "eevee_raytracing.hh" #include "eevee_renderbuffers.hh" #include "eevee_sampling.hh" #include "eevee_shader.hh" @@ -71,7 +70,6 @@ class Instance { World world; LightProbeModule light_probes; IrradianceCache irradiance_cache; - RayTracing raytracing; /** Input data. */ Depsgraph *depsgraph; @@ -122,8 +120,7 @@ class Instance { main_view(*this), world(*this), light_probes(*this), - irradiance_cache(*this), - raytracing(*this){}; + irradiance_cache(*this){}; ~Instance(){}; /* Render & Viewport. */ diff --git a/source/blender/draw/engines/eevee_next/eevee_raytracing.cc b/source/blender/draw/engines/eevee_next/eevee_raytracing.cc deleted file mode 100644 index c1eb0dda21d..00000000000 --- a/source/blender/draw/engines/eevee_next/eevee_raytracing.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup eevee - * - * Screen Space Ray Tracing - * - */ - -#pragma once - -#include "eevee_raytracing.hh" -#include "eevee_instance.hh" - -namespace blender::eevee { - -class Instance; - -/* -------------------------------------------------------------------- */ -/** \name RayTracing - * \{ */ - -void RayTracing::init() -{ - /* Compute pixel size. Size is multiplied by 2 because it is applied in NDC [-1..1] range. */ - data_.pixel_size = float2(2.0f) / float2(inst_.film.render_extent_get()); - data_.border_fade = inst_.scene->eevee.ssr_border_fade; - - data_.ssr_quality = 1.0f - 0.95f * inst_.scene->eevee.ssr_quality; - data_.ssr_thickness = inst_.scene->eevee.ssr_thickness; - data_.ssr_firefly_factor = inst_.scene->eevee.ssr_firefly_fac; - data_.ssr_max_roughness = inst_.scene->eevee.ssr_max_roughness; - data_.ssr_brdf_bias = 0.1f + data_.ssr_quality * 0.6f; /* Range [0.1, 0.7]. */ - - data_.push_update(); -} - -/** \} */ - -} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_raytracing.hh b/source/blender/draw/engines/eevee_next/eevee_raytracing.hh deleted file mode 100644 index 84a3310a0a5..00000000000 --- a/source/blender/draw/engines/eevee_next/eevee_raytracing.hh +++ /dev/null @@ -1,42 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -/** \file - * \ingroup eevee - * - * Screen Space Ray Tracing - * - */ - -#pragma once - -#include "eevee_shader_shared.hh" - -namespace blender::eevee { - -class Instance; - -/* -------------------------------------------------------------------- */ -/** \name RayTracing - * \{ */ - -class RayTracing { - private: - class Instance &inst_; - - RayTracingDataBuf data_; - - public: - RayTracing(Instance &inst) : inst_(inst){}; - ~RayTracing(){}; - - void init(); - - template void bind_resources(draw::detail::PassBase *pass) - { - pass->bind_ubo(RAYTRACE_BUF_SLOT, &data_); - } -}; - -/** \} */ - -} // namespace blender::eevee diff --git a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh index 3214be05acf..84c6fed0d0a 100644 --- a/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh +++ b/source/blender/draw/engines/eevee_next/eevee_shader_shared.hh @@ -979,26 +979,6 @@ enum eClosureBits : uint32_t { CLOSURE_AMBIENT_OCCLUSION = (1u << 12u), }; -struct RayTracingData { - float2 pixel_size; - float border_fade; - - /* TODO(Miguel Pozo): Does this belong here? */ - float ssr_quality; - float ssr_thickness; - float ssr_max_roughness; - float ssr_firefly_factor; - float ssr_brdf_bias; - bool1 ssr_enabled; - - int _pad0; - int _pad1; - int _pad2; -}; -BLI_STATIC_ASSERT_ALIGN(RayTracingData, 16) - -/** \} */ - /** \} */ /* -------------------------------------------------------------------- */ @@ -1008,10 +988,12 @@ BLI_STATIC_ASSERT_ALIGN(RayTracingData, 16) struct AOData { float distance; float quality; - int _pad0; + float2 pixel_size; }; BLI_STATIC_ASSERT_ALIGN(AOData, 16) +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Subsurface * \{ */ @@ -1114,7 +1096,6 @@ using VelocityIndexBuf = draw::StorageArrayBuffer; using VelocityObjectBuf = draw::StorageArrayBuffer; using CryptomatteObjectBuf = draw::StorageArrayBuffer; using AODataBuf = draw::UniformBuffer; -using RayTracingDataBuf = draw::UniformBuffer; } // namespace blender::eevee #endif diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl index 961a3d8e428..d2d9bece29e 100644 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ambient_occlusion_lib.glsl @@ -2,7 +2,7 @@ #pragma BLENDER_REQUIRE(common_math_lib.glsl) #pragma BLENDER_REQUIRE(common_math_geom_lib.glsl) #pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl) -#pragma BLENDER_REQUIRE(eevee_raytrace_lib.glsl) +#pragma BLENDER_REQUIRE(eevee_ray_types_lib.glsl) /* TODO(Miguel Pozo): Move this function somewhere else. */ /* Return a fitted cone angle given the input roughness */ @@ -159,13 +159,13 @@ OcclusionData ambient_occlusion_search(vec3 vP, ScreenSpaceRay ssray; - ssray = raytrace_screenspace_ray_create(ray); + ssray = raytrace_screenspace_ray_create(ray, ao_buf.pixel_size); data.horizons[0 + i * 2] = ambient_ambient_occlusion_search_horizon( vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); ray.direction = -ray.direction; - ssray = raytrace_screenspace_ray_create(ray); + ssray = raytrace_screenspace_ray_create(ray, ao_buf.pixel_size); data.horizons[1 + i * 2] = -ambient_ambient_occlusion_search_horizon( vI, vP, noise.y, ssray, depth_tx, inverted, radius, dir_sample_count); diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_ray_types_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_ray_types_lib.glsl new file mode 100644 index 00000000000..55be0a45d15 --- /dev/null +++ b/source/blender/draw/engines/eevee_next/shaders/eevee_ray_types_lib.glsl @@ -0,0 +1,63 @@ + +#pragma BLENDER_REQUIRE(common_view_lib.glsl) +#pragma BLENDER_REQUIRE(common_math_lib.glsl) + +/** + * Screen-Space Raytracing functions. + */ + +struct Ray { + vec3 origin; + /* Ray direction premultiplied by its maximum length. */ + vec3 direction; +}; + +/* Screenspace ray ([0..1] "uv" range) where direction is normalize to be as small as one + * full-resolution pixel. The ray is also clipped to all frustum sides. + */ +struct ScreenSpaceRay { + vec4 origin; + vec4 direction; + float max_time; +}; + +void raytrace_screenspace_ray_finalize(inout ScreenSpaceRay ray, vec2 pixel_size) +{ + /* Constant bias (due to depth buffer precision). Helps with self intersection. */ + /* Magic numbers for 24bits of precision. + * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */ + const float bias = -2.4e-7 * 2.0; + ray.origin.zw += bias; + ray.direction.zw += bias; + + ray.direction -= ray.origin; + /* If the line is degenerate, make it cover at least one pixel + * to not have to handle zero-pixel extent as a special case later */ + if (len_squared(ray.direction.xy) < 0.00001) { + ray.direction.xy = vec2(0.0, 0.00001); + } + float ray_len_sqr = len_squared(ray.direction.xyz); + /* Make ray.direction cover one pixel. */ + bool is_more_vertical = abs(ray.direction.x / pixel_size.x) < + abs(ray.direction.y / pixel_size.y); + ray.direction /= (is_more_vertical) ? abs(ray.direction.y) : abs(ray.direction.x); + ray.direction *= (is_more_vertical) ? pixel_size.y : pixel_size.x; + /* Clip to segment's end. */ + ray.max_time = sqrt(ray_len_sqr * safe_rcp(len_squared(ray.direction.xyz))); + /* Clipping to frustum sides. */ + float clip_dist = line_unit_box_intersect_dist_safe(ray.origin.xyz, ray.direction.xyz); + ray.max_time = min(ray.max_time, clip_dist); + /* Convert to texture coords [0..1] range. */ + ray.origin = ray.origin * 0.5 + 0.5; + ray.direction *= 0.5; +} + +ScreenSpaceRay raytrace_screenspace_ray_create(Ray ray, vec2 pixel_size) +{ + ScreenSpaceRay ssray; + ssray.origin.xyz = project_point(ProjectionMatrix, ray.origin); + ssray.direction.xyz = project_point(ProjectionMatrix, ray.origin + ray.direction); + + raytrace_screenspace_ray_finalize(ssray, pixel_size); + return ssray; +} diff --git a/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl b/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl deleted file mode 100644 index 64b179a8ea4..00000000000 --- a/source/blender/draw/engines/eevee_next/shaders/eevee_raytrace_lib.glsl +++ /dev/null @@ -1,254 +0,0 @@ - -#pragma BLENDER_REQUIRE(common_view_lib.glsl) -#pragma BLENDER_REQUIRE(common_math_lib.glsl) - -/* Fix for #104266 wherein AMD GPUs running Metal erroneously discard a successful hit. */ -#if defined(GPU_METAL) && defined(GPU_ATI) -# define METAL_AMD_RAYTRACE_WORKAROUND 1 -#endif - -/** - * Screen-Space Raytracing functions. - */ - -struct Ray { - vec3 origin; - /* Ray direction premultiplied by its maximum length. */ - vec3 direction; -}; - -/* Inputs expected to be in viewspace. */ -void raytrace_clip_ray_to_near_plane(inout Ray ray) -{ - float near_dist = get_view_z_from_depth(0.0); - if ((ray.origin.z + ray.direction.z) > near_dist) { - ray.direction *= abs((near_dist - ray.origin.z) / ray.direction.z); - } -} - -/* Screenspace ray ([0..1] "uv" range) where direction is normalize to be as small as one - * full-resolution pixel. The ray is also clipped to all frustum sides. - */ -struct ScreenSpaceRay { - vec4 origin; - vec4 direction; - float max_time; -}; - -void raytrace_screenspace_ray_finalize(inout ScreenSpaceRay ray) -{ - /* Constant bias (due to depth buffer precision). Helps with self intersection. */ - /* Magic numbers for 24bits of precision. - * From http://terathon.com/gdc07_lengyel.pdf (slide 26) */ - const float bias = -2.4e-7 * 2.0; - ray.origin.zw += bias; - ray.direction.zw += bias; - - ray.direction -= ray.origin; - /* If the line is degenerate, make it cover at least one pixel - * to not have to handle zero-pixel extent as a special case later */ - if (len_squared(ray.direction.xy) < 0.00001) { - ray.direction.xy = vec2(0.0, 0.00001); - } - float ray_len_sqr = len_squared(ray.direction.xyz); - /* Make ray.direction cover one pixel. */ - bool is_more_vertical = abs(ray.direction.x / rt_buf.pixel_size.x) < - abs(ray.direction.y / rt_buf.pixel_size.y); - ray.direction /= (is_more_vertical) ? abs(ray.direction.y) : abs(ray.direction.x); - ray.direction *= (is_more_vertical) ? rt_buf.pixel_size.y : rt_buf.pixel_size.x; - /* Clip to segment's end. */ - ray.max_time = sqrt(ray_len_sqr * safe_rcp(len_squared(ray.direction.xyz))); - /* Clipping to frustum sides. */ - float clip_dist = line_unit_box_intersect_dist_safe(ray.origin.xyz, ray.direction.xyz); - ray.max_time = min(ray.max_time, clip_dist); - /* Convert to texture coords [0..1] range. */ - ray.origin = ray.origin * 0.5 + 0.5; - ray.direction *= 0.5; -} - -ScreenSpaceRay raytrace_screenspace_ray_create(Ray ray) -{ - ScreenSpaceRay ssray; - ssray.origin.xyz = project_point(ProjectionMatrix, ray.origin); - ssray.direction.xyz = project_point(ProjectionMatrix, ray.origin + ray.direction); - - raytrace_screenspace_ray_finalize(ssray); - return ssray; -} - -ScreenSpaceRay raytrace_screenspace_ray_create(Ray ray, float thickness) -{ - ScreenSpaceRay ssray; - ssray.origin.xyz = project_point(ProjectionMatrix, ray.origin); - ssray.direction.xyz = project_point(ProjectionMatrix, ray.origin + ray.direction); - /* Interpolate thickness in screen space. - * Calculate thickness further away to avoid near plane clipping issues. */ - ssray.origin.w = get_depth_from_view_z(ray.origin.z - thickness) * 2.0 - 1.0; - ssray.direction.w = get_depth_from_view_z(ray.origin.z + ray.direction.z - thickness) * 2.0 - - 1.0; - - raytrace_screenspace_ray_finalize(ssray); - return ssray; -} - -struct RayTraceParameters { - /** ViewSpace thickness the objects. */ - float thickness; - /** Jitter along the ray to avoid banding artifact when steps are too large. */ - float jitter; - /** Determine how fast the sample steps are getting bigger. */ - float trace_quality; - /** Determine how we can use lower depth mipmaps to make the tracing faster. */ - float roughness; -}; - -/* Returns true on hit. */ -/* TODO(fclem): remove the back-face check and do it the SSR resolve code. */ -bool raytrace(Ray ray, - RayTraceParameters params, - const bool discard_backface, - const bool allow_self_intersection, - out vec3 hit_position) -{ - /* Clip to near plane for perspective view where there is a singularity at the camera origin. */ - if (ProjectionMatrix[3][3] == 0.0) { - raytrace_clip_ray_to_near_plane(ray); - } - - ScreenSpaceRay ssray = raytrace_screenspace_ray_create(ray, params.thickness); - /* Avoid no iteration. */ - if (!allow_self_intersection && ssray.max_time < 1.1) { - hit_position = ssray.origin.xyz + ssray.direction.xyz; - return false; - } - - ssray.max_time = max(1.1, ssray.max_time); - - float prev_delta = 0.0, prev_time = 0.0; - float depth_sample = get_depth_from_view_z(ray.origin.z); - float delta = depth_sample - ssray.origin.z; - - float lod_fac = saturate(fast_sqrt(params.roughness) * 2.0 - 0.4); - - /* Cross at least one pixel. */ - float t = 1.001, time = 1.001; - bool hit = false; -#ifdef METAL_AMD_RAYTRACE_WORKAROUND - bool hit_failsafe = true; -#endif - const float max_steps = 255.0; - for (float iter = 1.0; !hit && (time < ssray.max_time) && (iter < max_steps); iter++) { - float stride = 1.0 + iter * params.trace_quality; - float lod = log2(stride) * lod_fac; - - prev_time = time; - prev_delta = delta; - - time = min(t + stride * params.jitter, ssray.max_time); - t += stride; - - vec4 ss_p = ssray.origin + ssray.direction * time; - depth_sample = textureLod(hiz_tx, ss_p.xy * hiz_buf.uv_scale, floor(lod)).r; - - delta = depth_sample - ss_p.z; - /* Check if the ray is below the surface ... */ - hit = (delta < 0.0); - /* ... and above it with the added thickness. */ - hit = hit && (delta > ss_p.z - ss_p.w || abs(delta) < abs(ssray.direction.z * stride * 2.0)); - -#ifdef METAL_AMD_RAYTRACE_WORKAROUND - /* For workaround, perform discard backface and background check only within - * the iteration where the first successful ray intersection is registered. - * We flag failures to discard ray hits later. */ - bool hit_valid = !(discard_backface && prev_delta < 0.0) && (depth_sample != 1.0); - if (hit && !hit_valid) { - hit_failsafe = false; - } -#endif - } - -#ifndef METAL_AMD_RAYTRACE_WORKAROUND - /* Discard back-face hits. */ - hit = hit && !(discard_backface && prev_delta < 0.0); - /* Reject hit if background. */ - hit = hit && (depth_sample != 1.0); -#endif - /* Refine hit using intersection between the sampled heightfield and the ray. - * This simplifies nicely to this single line. */ - time = mix(prev_time, time, saturate(prev_delta / (prev_delta - delta))); - - hit_position = ssray.origin.xyz + ssray.direction.xyz * time; - -#ifdef METAL_AMD_RAYTRACE_WORKAROUND - /* Check failed ray flag to discard bad hits. */ - if (!hit_failsafe) { - return false; - } -#endif - return hit; -} - -#if 0 -bool raytrace_planar(Ray ray, RayTraceParameters params, int planar_ref_id, out vec3 hit_position) -{ - /* Clip to near plane for perspective view where there is a singularity at the camera origin. */ - if (ProjectionMatrix[3][3] == 0.0) { - raytrace_clip_ray_to_near_plane(ray); - } - - ScreenSpaceRay ssray = raytrace_screenspace_ray_create(ray); - - /* Planar Reflections have X mirrored. */ - ssray.origin.x = 1.0 - ssray.origin.x; - ssray.direction.x = -ssray.direction.x; - - float prev_delta = 0.0, prev_time = 0.0; - float depth_sample = texture(planarDepth, vec3(ssray.origin.xy, planar_ref_id)).r; - float delta = depth_sample - ssray.origin.z; - - float t = 0.0, time = 0.0; - /* On very sharp reflections, the ray can be perfectly aligned with the view direction - * making the tracing useless. Bypass tracing in this case. */ - bool hit = false; - const float max_steps = 255.0; - for (float iter = 1.0; !hit && (time < ssray.max_time) && (iter < max_steps); iter++) { - float stride = 1.0 + iter * params.trace_quality; - - prev_time = time; - prev_delta = delta; - - time = min(t + stride * params.jitter, ssray.max_time); - t += stride; - - vec4 ss_ray = ssray.origin + ssray.direction * time; - - depth_sample = texture(planarDepth, vec3(ss_ray.xy, planar_ref_id)).r; - - delta = depth_sample - ss_ray.z; - /* Check if the ray is below the surface. */ - hit = (delta < 0.0); - } - /* Reject hit if background. */ - hit = hit && (depth_sample != 1.0); - /* Refine hit using intersection between the sampled heightfield and the ray. - * This simplifies nicely to this single line. */ - time = mix(prev_time, time, saturate(prev_delta / (prev_delta - delta))); - - hit_position = ssray.origin.xyz + ssray.direction.xyz * time; - /* Planar Reflections have X mirrored. */ - hit_position.x = 1.0 - hit_position.x; - - return hit; -} -#endif - -float screen_border_mask(vec2 hit_co) -{ - const float margin = 0.003; - float atten = rt_buf.border_fade + margin; /* Screen percentage */ - hit_co = smoothstep(0.0, atten, hit_co) * (1.0 - smoothstep(1.0 - atten, 1.0, hit_co)); - - float screenfade = hit_co.x * hit_co.y; - - return screenfade; -} diff --git a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh index 14c4db9e343..6f829271942 100644 --- a/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh +++ b/source/blender/draw/engines/eevee_next/shaders/infos/eevee_ambient_occlusion_info.hh @@ -3,12 +3,12 @@ #include "eevee_defines.hh" #include "gpu_shader_create_info.hh" -GPU_SHADER_CREATE_INFO(eevee_raytrace_data) - .additional_info("draw_view", "eevee_shared", "eevee_hiz_data") - .uniform_buf(RAYTRACE_BUF_SLOT, "RayTracingData", "rt_buf"); - GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_data) - .additional_info("eevee_raytrace_data", "eevee_sampling_data", "eevee_utility_texture") + .additional_info("draw_view", + "eevee_shared", + "eevee_hiz_data", + "eevee_sampling_data", + "eevee_utility_texture") .uniform_buf(AO_BUF_SLOT, "AOData", "ao_buf"); GPU_SHADER_CREATE_INFO(eevee_ambient_occlusion_pass) -- 2.30.2 From b7d67932e64bde356bc71315b7a99819feb3a22b Mon Sep 17 00:00:00 2001 From: Miguel Pozo Date: Thu, 29 Jun 2023 17:16:12 +0200 Subject: [PATCH 25/25] Remove dependencies from bind_resources --- .../draw/engines/eevee_next/eevee_ambient_occlusion.cc | 4 ++++ .../draw/engines/eevee_next/eevee_ambient_occlusion.hh | 3 --- source/blender/draw/engines/eevee_next/eevee_pipeline.cc | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc index 085319d3ada..192ae756303 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.cc @@ -54,6 +54,10 @@ void AmbientOcclusion::sync() render_pass_ps_.init(); render_pass_ps_.shader_set(inst_.shaders.static_shader_get(AMBIENT_OCCLUSION_PASS)); + + render_pass_ps_.bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); + inst_.sampling.bind_resources(&render_pass_ps_); + inst_.hiz_buffer.bind_resources(&render_pass_ps_); bind_resources(&render_pass_ps_); render_pass_ps_.bind_image("in_normal_img", &rp_normal_tx_); diff --git a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh index 6f3d7507a0e..28c0e17e790 100644 --- a/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh +++ b/source/blender/draw/engines/eevee_next/eevee_ambient_occlusion.hh @@ -49,9 +49,6 @@ class AmbientOcclusion { template void bind_resources(draw::detail::PassBase *pass) { - inst_.sampling.bind_resources(pass); - inst_.hiz_buffer.bind_resources(pass); - pass->bind_texture(RBUFS_UTILITY_TEX_SLOT, &inst_.pipelines.utility_tx); pass->bind_ubo(AO_BUF_SLOT, &data_); } }; diff --git a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc index 13d3dec4a94..71cad781160 100644 --- a/source/blender/draw/engines/eevee_next/eevee_pipeline.cc +++ b/source/blender/draw/engines/eevee_next/eevee_pipeline.cc @@ -150,8 +150,9 @@ void ForwardPipeline::sync() inst_.lights.bind_resources(&opaque_ps_); inst_.shadows.bind_resources(&opaque_ps_); inst_.sampling.bind_resources(&opaque_ps_); - inst_.cryptomatte.bind_resources(&opaque_ps_); + inst_.hiz_buffer.bind_resources(&opaque_ps_); inst_.ambient_occlusion.bind_resources(&opaque_ps_); + inst_.cryptomatte.bind_resources(&opaque_ps_); } opaque_single_sided_ps_ = &opaque_ps_.sub("SingleSided"); @@ -178,6 +179,7 @@ void ForwardPipeline::sync() inst_.lights.bind_resources(&sub); inst_.shadows.bind_resources(&sub); inst_.sampling.bind_resources(&sub); + inst_.hiz_buffer.bind_resources(&sub); inst_.ambient_occlusion.bind_resources(&sub); } } @@ -332,8 +334,9 @@ void DeferredLayer::begin_sync() gbuffer_ps_.bind_ubo(RBUFS_BUF_SLOT, &inst_.render_buffers.data); inst_.sampling.bind_resources(&gbuffer_ps_); - inst_.cryptomatte.bind_resources(&gbuffer_ps_); + inst_.hiz_buffer.bind_resources(&gbuffer_ps_); inst_.ambient_occlusion.bind_resources(&gbuffer_ps_); + inst_.cryptomatte.bind_resources(&gbuffer_ps_); } DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM | DRW_STATE_DEPTH_EQUAL | -- 2.30.2