Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2021-10-19 18:40:10 +0300
committerClément Foucault <foucault.clem@gmail.com>2021-10-24 17:13:04 +0300
commit3db3006d4c22917cf25c12ca137d33594e323344 (patch)
treebfda4c4e37ffcd9040d2ba307bc56b2d65537056 /source/blender
parent008fb3eed9b8c318a8b50dc5a7e84e9cfb030656 (diff)
EEVEE: Port back HiZbuffer
Pretty much identical. Texture format is now always `GPU_R32F` to remove some workarounds.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/eevee/eevee_hizbuffer.cc101
-rw-r--r--source/blender/draw/engines/eevee/eevee_hizbuffer.hh103
-rw-r--r--source/blender/draw/engines/eevee/eevee_instance.cc1
-rw-r--r--source/blender/draw/engines/eevee/eevee_instance.hh3
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader.cc4
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader.hh3
-rw-r--r--source/blender/draw/engines/eevee/eevee_shader_shared.hh15
-rw-r--r--source/blender/draw/engines/eevee/eevee_shading.cc94
-rw-r--r--source/blender/draw/engines/eevee/eevee_shading.hh38
-rw-r--r--source/blender/draw/engines/eevee/eevee_view.cc4
-rw-r--r--source/blender/draw/engines/eevee/eevee_view.hh13
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl17
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl40
-rw-r--r--source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl12
16 files changed, 395 insertions, 60 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index f102141e7d2..e0343cffb01 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -120,6 +120,7 @@ set(SRC
engines/eevee/eevee_film.cc
engines/eevee/eevee_gpencil.cc
engines/eevee/eevee_hair.cc
+ engines/eevee/eevee_hizbuffer.cc
engines/eevee/eevee_id_map.cc
engines/eevee/eevee_instance.cc
engines/eevee/eevee_light.cc
@@ -253,6 +254,8 @@ data_to_c_simple(engines/eevee/shaders/eevee_deferred_holdout_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_deferred_transparent_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_deferred_volume_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_depth_clear_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/eevee_hiz_copy_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/eevee_hiz_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_depth_of_field_accumulator_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_depth_of_field_bokeh_lut_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/eevee_depth_of_field_filter_frag.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee_hizbuffer.cc b/source/blender/draw/engines/eevee/eevee_hizbuffer.cc
new file mode 100644
index 00000000000..24f0c8261e8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_hizbuffer.cc
@@ -0,0 +1,101 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup eevee
+ *
+ * The Hierarchical-Z buffer is texture containing a copy of the depth buffer with mipmaps.
+ * Each mip contains the maximum depth of each 4 pixels on the upper level.
+ * The size of the texture is padded to avoid messing with the mipmap pixels alignments.
+ */
+
+#include "eevee_instance.hh"
+
+#include "eevee_hizbuffer.hh"
+
+namespace blender::eevee {
+
+/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z buffer
+ *
+ * \{ */
+
+void HiZBufferModule::sync(void)
+{
+ {
+ hiz_copy_ps_ = DRW_pass_create("HizCopy", DRW_STATE_WRITE_COLOR);
+ GPUShader *sh = inst_.shaders.static_shader_get(HIZ_COPY);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, hiz_copy_ps_);
+ DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
+ }
+ {
+ hiz_downsample_ps_ = DRW_pass_create("HizDownsample", DRW_STATE_WRITE_COLOR);
+ GPUShader *sh = inst_.shaders.static_shader_get(HIZ_DOWNSAMPLE);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, hiz_downsample_ps_);
+ DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_uniform_vec2(grp, "texel_size", texel_size_, 1);
+ DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
+ }
+}
+
+void HiZBuffer::prepare(GPUTexture *depth_src_tx)
+{
+ int div = 1 << mip_count_;
+ vec2 extent_src(GPU_texture_width(depth_src_tx), GPU_texture_height(depth_src_tx));
+ vec2 extent_hiz(divide_ceil_u(extent_src.x, div) * div, divide_ceil_u(extent_src.y, div) * div);
+
+ inst_.hiz.texel_size_ = 1.0f / extent_hiz;
+ inst_.hiz.data_.uv_scale = extent_src / extent_hiz;
+
+ inst_.hiz.data_.push_update();
+
+ /* TODO/OPTI(fclem): Share it between similar views.
+ * Not possible right now because request_tmp does not support mipmaps. */
+ hiz_tx_.ensure("HiZ", UNPACK2(extent_hiz), mip_count_, GPU_R32F);
+ hiz_fb_.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(hiz_tx_));
+
+ GPU_texture_mipmap_mode(hiz_tx_, true, false);
+}
+
+void HiZBuffer::recursive_downsample(void *thunk, int UNUSED(lvl))
+{
+ HiZBufferModule &hiz = *reinterpret_cast<HiZBufferModule *>(thunk);
+ hiz.texel_size_ *= 2.0f;
+ DRW_draw_pass(hiz.hiz_downsample_ps_);
+}
+
+void HiZBuffer::update(GPUTexture *depth_src_tx)
+{
+ DRW_stats_group_start("Hiz");
+
+ inst_.hiz.texel_size_ = 1.0f / vec2(GPU_texture_width(hiz_tx_), GPU_texture_height(hiz_tx_));
+
+ inst_.hiz.input_depth_tx_ = depth_src_tx;
+ GPU_framebuffer_bind(hiz_fb_);
+ DRW_draw_pass(inst_.hiz.hiz_copy_ps_);
+
+ inst_.hiz.input_depth_tx_ = hiz_tx_;
+ GPU_framebuffer_recursive_downsample(hiz_fb_, mip_count_, &recursive_downsample, &inst_.hiz);
+
+ DRW_stats_group_end();
+}
+
+/** \} */
+
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee/eevee_hizbuffer.hh b/source/blender/draw/engines/eevee/eevee_hizbuffer.hh
new file mode 100644
index 00000000000..80bd7be912c
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_hizbuffer.hh
@@ -0,0 +1,103 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2021, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup eevee
+ *
+ * The Hierarchical-Z buffer is texture containing a copy of the depth buffer with mipmaps.
+ * Each mip contains the maximum depth of each 4 pixels on the upper level.
+ * The size of the texture is padded to avoid messing with the mipmap pixels alignments.
+ */
+
+#pragma once
+
+#include "DRW_render.h"
+
+#include "eevee_shader_shared.hh"
+
+namespace blender::eevee {
+
+class Instance;
+
+/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z buffer
+ * \{ */
+
+class HiZBuffer {
+ private:
+ Instance &inst_;
+ /** Framebuffer use for recursive downsampling. */
+ /* TODO(fclem) Remove this and use a compute shader instead. */
+ Framebuffer hiz_fb_ = Framebuffer("DepthHiz");
+ /** Max mip to downsample to. We ensure the hiz has enough padding to never
+ * have to compensate the mipmap alignments. */
+ constexpr static int mip_count_ = 6;
+ /** TODO/OPTI(fclem): Share it between similar views. */
+ Texture hiz_tx_;
+
+ public:
+ HiZBuffer(Instance &inst) : inst_(inst){};
+
+ void prepare(GPUTexture *depth_src);
+ void update(GPUTexture *depth_src);
+
+ GPUTexture *texture_get(void) const
+ {
+ return hiz_tx_;
+ }
+
+ private:
+ static void recursive_downsample(void *thunk, int lvl);
+};
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z buffer Module
+ * \{ */
+
+class HiZBufferModule {
+ friend HiZBuffer;
+
+ private:
+ Instance &inst_;
+
+ HiZDataBuf data_;
+ /** Copy input depth to hiz-buffer with border padding. */
+ DRWPass *hiz_copy_ps_;
+ /** Downsample one mipmap level. */
+ DRWPass *hiz_downsample_ps_;
+ /** References only. */
+ GPUTexture *input_depth_tx_ = nullptr;
+ /** Pixel size of the render target during hiz downsampling. */
+ vec2 texel_size_;
+
+ public:
+ HiZBufferModule(Instance &inst) : inst_(inst){};
+
+ void sync(void);
+
+ const GPUUniformBuf *ubo_get(void) const
+ {
+ return data_.ubo_get();
+ }
+};
+
+/** \} */
+
+} // namespace blender::eevee
diff --git a/source/blender/draw/engines/eevee/eevee_instance.cc b/source/blender/draw/engines/eevee/eevee_instance.cc
index 9aea6e301af..8c042ae062b 100644
--- a/source/blender/draw/engines/eevee/eevee_instance.cc
+++ b/source/blender/draw/engines/eevee/eevee_instance.cc
@@ -125,6 +125,7 @@ void Instance::begin_sync()
shading_passes.sync();
main_view.sync();
world.sync();
+ hiz.sync();
lookdev.sync_background();
lookdev.sync_overlay();
diff --git a/source/blender/draw/engines/eevee/eevee_instance.hh b/source/blender/draw/engines/eevee/eevee_instance.hh
index 22a5ad1f57a..24c1fae5515 100644
--- a/source/blender/draw/engines/eevee/eevee_instance.hh
+++ b/source/blender/draw/engines/eevee/eevee_instance.hh
@@ -29,6 +29,7 @@
#include "DRW_render.h"
#include "eevee_film.hh"
+#include "eevee_hizbuffer.hh"
#include "eevee_id_map.hh"
#include "eevee_light.hh"
#include "eevee_lightprobe.hh"
@@ -69,6 +70,7 @@ class Instance {
MotionBlurModule motion_blur;
LightModule lights;
LightProbeModule lightprobes;
+ HiZBufferModule hiz;
/* TODO(fclem) Move it to scene layer data. */
ShadowModule shadows;
SubsurfaceModule subsurface;
@@ -110,6 +112,7 @@ class Instance {
motion_blur(*this),
lights(*this),
lightprobes(*this),
+ hiz(*this),
shadows(*this),
subsurface(*this),
sync(*this),
diff --git a/source/blender/draw/engines/eevee/eevee_shader.cc b/source/blender/draw/engines/eevee/eevee_shader.cc
index 654a01cac80..8c8262f5893 100644
--- a/source/blender/draw/engines/eevee/eevee_shader.cc
+++ b/source/blender/draw/engines/eevee/eevee_shader.cc
@@ -54,6 +54,8 @@ extern char datatoc_eevee_deferred_holdout_frag_glsl[];
extern char datatoc_eevee_deferred_transparent_frag_glsl[];
extern char datatoc_eevee_deferred_volume_frag_glsl[];
extern char datatoc_eevee_depth_clear_frag_glsl[];
+extern char datatoc_eevee_hiz_copy_frag_glsl[];
+extern char datatoc_eevee_hiz_downsample_frag_glsl[];
extern char datatoc_eevee_depth_of_field_accumulator_lib_glsl[];
extern char datatoc_eevee_depth_of_field_bokeh_lut_frag_glsl[];
extern char datatoc_eevee_depth_of_field_downsample_frag_glsl[];
@@ -214,6 +216,8 @@ ShaderModule::ShaderModule()
SHADER_FULLSCREEN(DEFERRED_EVAL_VOLUME, eevee_deferred_volume_frag);
SHADER(DEFERRED_MESH, eevee_surface_mesh_vert, nullptr, eevee_surface_deferred_frag, nullptr);
SHADER(DEFERRED_VOLUME, eevee_volume_vert, nullptr, eevee_volume_deferred_frag, nullptr);
+ SHADER_FULLSCREEN(HIZ_COPY, eevee_hiz_copy_frag);
+ SHADER_FULLSCREEN(HIZ_DOWNSAMPLE, eevee_hiz_downsample_frag);
SHADER_FULLSCREEN(DOF_BOKEH_LUT, eevee_depth_of_field_bokeh_lut_frag);
SHADER_FULLSCREEN(DOF_FILTER, eevee_depth_of_field_filter_frag);
SHADER_FULLSCREEN_DEFINES(DOF_GATHER_BACKGROUND_LUT,
diff --git a/source/blender/draw/engines/eevee/eevee_shader.hh b/source/blender/draw/engines/eevee/eevee_shader.hh
index 792248540f7..4d0dc93d616 100644
--- a/source/blender/draw/engines/eevee/eevee_shader.hh
+++ b/source/blender/draw/engines/eevee/eevee_shader.hh
@@ -77,6 +77,9 @@ enum eShaderType {
FILM_RESOLVE,
FILM_RESOLVE_DEPTH,
+ HIZ_COPY,
+ HIZ_DOWNSAMPLE,
+
LIGHTPROBE_DISPLAY_CUBEMAP,
LIGHTPROBE_DISPLAY_IRRADIANCE,
diff --git a/source/blender/draw/engines/eevee/eevee_shader_shared.hh b/source/blender/draw/engines/eevee/eevee_shader_shared.hh
index d566212c49b..05e4ded136e 100644
--- a/source/blender/draw/engines/eevee/eevee_shader_shared.hh
+++ b/source/blender/draw/engines/eevee/eevee_shader_shared.hh
@@ -613,6 +613,20 @@ BLI_STATIC_ASSERT_ALIGN(LightProbeInfoData, 16)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Hierarchical-Z Buffer
+ * \{ */
+
+struct HiZData {
+ /** Scale factor to remove HiZBuffer padding. */
+ vec2 uv_scale;
+ int _pad0;
+ int _pad1;
+};
+BLI_STATIC_ASSERT_ALIGN(HiZData, 16)
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Subsurface
* \{ */
@@ -699,6 +713,7 @@ using CubemapDataBuf = StructArrayBuffer<CubemapData, CULLING_ITEM_BATCH>;
using CullingDataBuf = StructBuffer<CullingData>;
using DepthOfFieldDataBuf = StructBuffer<DepthOfFieldData>;
using GridDataBuf = StructArrayBuffer<GridData, GRID_MAX>;
+using HiZDataBuf = StructBuffer<HiZData>;
using LightDataBuf = StructArrayBuffer<LightData, CULLING_ITEM_BATCH>;
using LightProbeFilterDataBuf = StructBuffer<LightProbeFilterData>;
using LightProbeInfoDataBuf = StructBuffer<LightProbeInfoData>;
diff --git a/source/blender/draw/engines/eevee/eevee_shading.cc b/source/blender/draw/engines/eevee/eevee_shading.cc
index 948ff9ba524..16c03731dee 100644
--- a/source/blender/draw/engines/eevee/eevee_shading.cc
+++ b/source/blender/draw/engines/eevee/eevee_shading.cc
@@ -273,40 +273,57 @@ void DeferredLayer::volume_add(Object *ob)
DRW_shgroup_call(grp, DRW_cache_cube_get(), ob);
}
-void DeferredLayer::render(GBuffer &gbuffer, GPUFrameBuffer *view_fb)
+void DeferredLayer::render(GBuffer &gbuffer, HiZBuffer &hiz, GPUFrameBuffer *view_fb)
{
+ DeferredPass &deferred_pass = inst_.shading_passes.deferred;
+
const bool no_surfaces = DRW_pass_is_empty(gbuffer_ps_);
const bool no_volumes = DRW_pass_is_empty(volume_ps_);
if (no_surfaces && no_volumes) {
return;
}
+ /* TODO(fclem): detect these cases. */
+ const bool use_refraction = true;
+ const bool use_glossy = true;
+ const bool use_ao = false;
+
+ gbuffer.prepare((eClosureBits)0xFFFFFFFFu);
+ hiz.prepare(gbuffer.depth_tx);
- gbuffer.bind((eClosureBits)0xFFFFFFFFu);
+ update_pass_inputs(gbuffer, hiz);
+
+ if (use_refraction) {
+ /* TODO(fclem) Only update if needed.
+ * i.e: No need when SSR from previous layer has already updated hiz. */
+ hiz.update(gbuffer.depth_tx);
+ }
+
+ gbuffer.bind();
if (!no_surfaces) {
DRW_draw_pass(prepass_ps_);
+
+ /* TODO(fclem): Ambient Occlusion texture node. */
+ /* NOTE(fclem): Needs a separate hiz if used at the same time as refraction. */
+ if (use_ao) {
+ hiz.update(gbuffer.depth_tx);
+ gbuffer.bind();
+ }
+
DRW_draw_pass(gbuffer_ps_);
}
- DeferredPass &deferred_pass = inst_.shading_passes.deferred;
- deferred_pass.input_combined_tx = gbuffer.combined_tx;
- deferred_pass.input_emission_data_tx_ = gbuffer.emission_tx;
- deferred_pass.input_transmit_color_tx_ = gbuffer.transmit_color_tx;
- deferred_pass.input_transmit_normal_tx_ = gbuffer.transmit_normal_tx;
- deferred_pass.input_transmit_data_tx_ = gbuffer.transmit_data_tx;
- deferred_pass.input_reflect_color_tx_ = gbuffer.reflect_color_tx;
- deferred_pass.input_reflect_normal_tx_ = gbuffer.reflect_normal_tx;
- deferred_pass.input_diffuse_tx_ = gbuffer.diffuse_tx;
- deferred_pass.input_transparency_data_tx_ = gbuffer.transparency_tx;
- deferred_pass.input_volume_data_tx_ = gbuffer.volume_tx;
- deferred_pass.input_depth_tx_ = gbuffer.depth_copy_tx;
-
- if (!no_volumes) {
- gbuffer.copy_depth_behind();
- deferred_pass.input_depth_behind_tx_ = gbuffer.depth_behind_tx;
+ if (use_refraction) {
+ // if (inst_.raytracing.enabled()) {
+ // DRW_draw_pass(deferred_pass.trace_refraction_ps_);
+ // }
+ // DRW_draw_pass(deferred_pass.eval_refraction_ps_);
}
if (!no_volumes) {
+ // gbuffer.copy_depth_behind();
+ // deferred_pass.input_depth_behind_tx_ = gbuffer.depth_behind_tx;
+
for (auto index : inst_.lights.index_range()) {
inst_.lights.bind_batch(index);
@@ -315,7 +332,7 @@ void DeferredLayer::render(GBuffer &gbuffer, GPUFrameBuffer *view_fb)
}
}
- gbuffer.copy_depth();
+ hiz.update(gbuffer.depth_tx);
if (true) {
gbuffer.bind_holdout();
@@ -348,6 +365,26 @@ void DeferredLayer::render(GBuffer &gbuffer, GPUFrameBuffer *view_fb)
GPU_framebuffer_bind(view_fb);
DRW_draw_pass(deferred_pass.eval_subsurface_ps_);
}
+
+ // if (use_glossy && inst_.raytracing.enabled()) {
+ // inst_.raytracing.trace_reflection(gbuffer);
+ // }
+}
+
+void DeferredLayer::update_pass_inputs(GBuffer &gbuffer, HiZBuffer &hiz)
+{
+ DeferredPass &deferred_pass = inst_.shading_passes.deferred;
+ deferred_pass.input_combined_tx_ = gbuffer.combined_tx;
+ deferred_pass.input_emission_data_tx_ = gbuffer.emission_tx;
+ deferred_pass.input_transmit_color_tx_ = gbuffer.transmit_color_tx;
+ deferred_pass.input_transmit_normal_tx_ = gbuffer.transmit_normal_tx;
+ deferred_pass.input_transmit_data_tx_ = gbuffer.transmit_data_tx;
+ deferred_pass.input_reflect_color_tx_ = gbuffer.reflect_color_tx;
+ deferred_pass.input_reflect_normal_tx_ = gbuffer.reflect_normal_tx;
+ deferred_pass.input_diffuse_tx_ = gbuffer.diffuse_tx;
+ deferred_pass.input_transparency_data_tx_ = gbuffer.transparency_tx;
+ deferred_pass.input_volume_data_tx_ = gbuffer.volume_tx;
+ deferred_pass.input_hiz_tx_ = hiz.texture_get();
}
/** \} */
@@ -399,7 +436,7 @@ void DeferredPass::sync(void)
grp, "reflect_color_tx", &input_reflect_color_tx_, no_interp);
DRW_shgroup_uniform_texture_ref_ex(
grp, "reflect_normal_tx", &input_reflect_normal_tx_, no_interp);
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_);
DRW_shgroup_uniform_texture_ref(
grp, "sss_transmittance_tx", inst_.subsurface.transmittance_ref_get());
DRW_shgroup_stencil_set(
@@ -413,7 +450,8 @@ void DeferredPass::sync(void)
DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_subsurface_ps_);
DRW_shgroup_uniform_block(grp, "subsurface_block", inst_.subsurface.ubo_get());
DRW_shgroup_uniform_block(grp, "sampling_block", inst_.sampling.ubo_get());
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_uniform_block(grp, "hiz_block", inst_.hiz.ubo_get());
+ DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_);
DRW_shgroup_uniform_texture_ref_ex(grp, "radiance_tx", &input_diffuse_tx_, no_interp);
DRW_shgroup_uniform_texture_ref_ex(
grp, "transmit_color_tx", &input_transmit_color_tx_, no_interp);
@@ -438,7 +476,7 @@ void DeferredPass::sync(void)
DRW_shgroup_uniform_texture_ref_ex(
grp, "transparency_data_tx", &input_transparency_data_tx_, no_interp);
DRW_shgroup_uniform_texture_ref_ex(grp, "volume_data_tx", &input_volume_data_tx_, no_interp);
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_);
DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_VOLUME);
DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
}
@@ -449,7 +487,7 @@ void DeferredPass::sync(void)
DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_transparency_ps_);
DRW_shgroup_uniform_texture_ref(grp, "transparency_data_tx", &input_transparency_data_tx_);
DRW_shgroup_uniform_texture_ref_ex(grp, "volume_data_tx", &input_volume_data_tx_, no_interp);
- DRW_shgroup_uniform_texture_ref(grp, "depth_tx", &input_depth_tx_);
+ DRW_shgroup_uniform_texture_ref(grp, "hiz_tx", &input_hiz_tx_);
DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_TRANSPARENCY);
DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
}
@@ -458,7 +496,7 @@ void DeferredPass::sync(void)
eval_holdout_ps_ = DRW_pass_create("DeferredHoldout", state);
GPUShader *sh = inst_.shaders.static_shader_get(DEFERRED_EVAL_HOLDOUT);
DRWShadingGroup *grp = DRW_shgroup_create(sh, eval_volume_homogeneous_ps_);
- DRW_shgroup_uniform_texture_ref(grp, "combined_tx", &input_combined_tx);
+ DRW_shgroup_uniform_texture_ref(grp, "combined_tx", &input_combined_tx_);
DRW_shgroup_uniform_texture_ref(grp, "transparency_data_tx", &input_transparency_data_tx_);
DRW_shgroup_stencil_set(grp, 0x0, 0x0, CLOSURE_TRANSPARENCY);
DRW_shgroup_call_procedural_triangles(grp, nullptr, 1);
@@ -490,11 +528,11 @@ void DeferredPass::volume_add(Object *ob)
volumetric_layer_.volume_add(ob);
}
-void DeferredPass::render(GBuffer &gbuffer, GPUFrameBuffer *view_fb)
+void DeferredPass::render(GBuffer &gbuffer, HiZBuffer &hiz, GPUFrameBuffer *view_fb)
{
- opaque_layer_.render(gbuffer, view_fb);
- refraction_layer_.render(gbuffer, view_fb);
- volumetric_layer_.render(gbuffer, view_fb);
+ opaque_layer_.render(gbuffer, hiz, view_fb);
+ refraction_layer_.render(gbuffer, hiz, view_fb);
+ volumetric_layer_.render(gbuffer, hiz, view_fb);
gbuffer.render_end();
}
diff --git a/source/blender/draw/engines/eevee/eevee_shading.hh b/source/blender/draw/engines/eevee/eevee_shading.hh
index 691bce3e97e..e042dea1dc6 100644
--- a/source/blender/draw/engines/eevee/eevee_shading.hh
+++ b/source/blender/draw/engines/eevee/eevee_shading.hh
@@ -140,10 +140,8 @@ struct GBuffer {
Framebuffer holdout_fb = Framebuffer("Holdout");
Texture depth_behind_tx = Texture("DepthBehind");
- Texture depth_copy_tx = Texture("DepthCopy");
Framebuffer depth_behind_fb = Framebuffer("DepthCopy");
- Framebuffer depth_copy_fb = Framebuffer("DepthCopy");
/* Owner of this GBuffer. Used to query temp textures. */
void *owner;
@@ -170,10 +168,9 @@ struct GBuffer {
holdout_tx.sync_tmp();
diffuse_tx.sync_tmp();
depth_behind_tx.sync_tmp();
- depth_copy_tx.sync_tmp();
}
- void bind(eClosureBits closures_used)
+ void prepare(eClosureBits closures_used)
{
ivec2 extent = {GPU_texture_width(depth_tx), GPU_texture_height(depth_tx)};
@@ -214,7 +211,6 @@ struct GBuffer {
holdout_tx.acquire_tmp(UNPACK2(extent), GPU_R11F_G11F_B10F, owner);
depth_behind_tx.acquire_tmp(UNPACK2(extent), GPU_DEPTH24_STENCIL8, owner);
- depth_copy_tx.acquire_tmp(UNPACK2(extent), GPU_DEPTH24_STENCIL8, owner);
/* Layer attachement also works with cubemap. */
gbuffer_fb.ensure(GPU_ATTACHMENT_TEXTURE_LAYER(depth_tx, layer),
@@ -226,6 +222,10 @@ struct GBuffer {
GPU_ATTACHMENT_TEXTURE(volume_tx),
GPU_ATTACHMENT_TEXTURE(emission_tx),
GPU_ATTACHMENT_TEXTURE(transparency_tx));
+ }
+
+ void bind(void)
+ {
GPU_framebuffer_bind(gbuffer_fb);
GPU_framebuffer_clear_stencil(gbuffer_fb, 0x0);
}
@@ -262,14 +262,6 @@ struct GBuffer {
GPU_framebuffer_blit(gbuffer_fb, 0, depth_behind_fb, 0, GPU_DEPTH_BIT);
}
- void copy_depth(void)
- {
- depth_copy_fb.ensure(GPU_ATTACHMENT_TEXTURE(depth_copy_tx));
- GPU_framebuffer_bind(depth_copy_fb);
-
- GPU_framebuffer_blit(gbuffer_fb, 0, depth_copy_fb, 0, GPU_DEPTH_BIT);
- }
-
void clear_radiance(void)
{
radiance_clear_fb.ensure(GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(diffuse_tx));
@@ -292,7 +284,6 @@ struct GBuffer {
holdout_tx.release_tmp();
diffuse_tx.release_tmp();
depth_behind_tx.release_tmp();
- depth_copy_tx.release_tmp();
}
};
@@ -318,7 +309,10 @@ class DeferredLayer {
DRWShadingGroup *material_add(::Material *blender_mat, GPUMaterial *gpumat);
DRWShadingGroup *prepass_add(::Material *blender_mat, GPUMaterial *gpumat);
void volume_add(Object *ob);
- void render(GBuffer &gbuffer, GPUFrameBuffer *view_fb);
+ void render(GBuffer &gbuffer, HiZBuffer &hiz, GPUFrameBuffer *view_fb);
+
+ private:
+ void update_pass_inputs(GBuffer &gbuffer, HiZBuffer &hiz);
};
class DeferredPass {
@@ -341,16 +335,16 @@ class DeferredPass {
DRWPass *eval_volume_homogeneous_ps_ = nullptr;
/* References only. */
- GPUTexture *input_combined_tx = nullptr;
+ GPUTexture *input_combined_tx_ = nullptr;
GPUTexture *input_depth_behind_tx_ = nullptr;
- GPUTexture *input_depth_tx_ = nullptr;
+ GPUTexture *input_diffuse_tx_ = nullptr;
GPUTexture *input_emission_data_tx_ = nullptr;
- GPUTexture *input_transmit_color_tx_ = nullptr;
- GPUTexture *input_transmit_normal_tx_ = nullptr;
- GPUTexture *input_transmit_data_tx_ = nullptr;
+ GPUTexture *input_hiz_tx_ = nullptr;
GPUTexture *input_reflect_color_tx_ = nullptr;
GPUTexture *input_reflect_normal_tx_ = nullptr;
- GPUTexture *input_diffuse_tx_ = nullptr;
+ GPUTexture *input_transmit_color_tx_ = nullptr;
+ GPUTexture *input_transmit_data_tx_ = nullptr;
+ GPUTexture *input_transmit_normal_tx_ = nullptr;
GPUTexture *input_transparency_data_tx_ = nullptr;
GPUTexture *input_volume_data_tx_ = nullptr;
// GPUTexture *input_volume_radiance_tx_ = nullptr;
@@ -364,7 +358,7 @@ class DeferredPass {
DRWShadingGroup *material_add(::Material *material, GPUMaterial *gpumat);
DRWShadingGroup *prepass_add(::Material *material, GPUMaterial *gpumat);
void volume_add(Object *ob);
- void render(GBuffer &gbuffer, GPUFrameBuffer *view_fb);
+ void render(GBuffer &gbuffer, HiZBuffer &hiz, GPUFrameBuffer *view_fb);
};
/** \} */
diff --git a/source/blender/draw/engines/eevee/eevee_view.cc b/source/blender/draw/engines/eevee/eevee_view.cc
index 72e2baa6815..ef2cbf499ef 100644
--- a/source/blender/draw/engines/eevee/eevee_view.cc
+++ b/source/blender/draw/engines/eevee/eevee_view.cc
@@ -134,7 +134,7 @@ void ShadingView::render(void)
inst_.shading_passes.background.render();
}
- inst_.shading_passes.deferred.render(gbuffer_, view_fb_);
+ inst_.shading_passes.deferred.render(gbuffer_, hiz_, view_fb_);
inst_.lightprobes.draw_cache_display();
@@ -248,7 +248,7 @@ void LightProbeView::render(void)
if (!is_only_background_) {
GPU_framebuffer_clear_depth(view_fb_, 1.0f);
- inst_.shading_passes.deferred.render(gbuffer_, view_fb_);
+ inst_.shading_passes.deferred.render(gbuffer_, hiz_, view_fb_);
inst_.shading_passes.forward.render();
}
DRW_stats_group_end();
diff --git a/source/blender/draw/engines/eevee/eevee_view.hh b/source/blender/draw/engines/eevee/eevee_view.hh
index 901f6c1036f..5e3afead4c0 100644
--- a/source/blender/draw/engines/eevee/eevee_view.hh
+++ b/source/blender/draw/engines/eevee/eevee_view.hh
@@ -37,6 +37,7 @@
#include "DRW_render.h"
#include "eevee_depth_of_field.hh"
+#include "eevee_hizbuffer.hh"
#include "eevee_motion_blur.hh"
#include "eevee_renderpasses.hh"
#include "eevee_shader.hh"
@@ -56,7 +57,7 @@ class Instance;
class ShadingView {
private:
Instance &inst_;
- /** Static srting pointer. Used as debug name and as UUID for texture pool. */
+ /** Static string pointer. Used as debug name and as UUID for texture pool. */
const char *name_;
/** Matrix to apply to the viewmat. */
const float (*face_matrix_)[4];
@@ -66,7 +67,10 @@ class ShadingView {
MotionBlur mb_;
Velocity velocity_;
+ /** GBuffer for deferred passes. */
GBuffer gbuffer_;
+ /** HiZBuffer for screenspace effects. */
+ HiZBuffer hiz_;
/** Owned resources. */
eevee::Framebuffer view_fb_;
@@ -96,7 +100,8 @@ class ShadingView {
face_matrix_(face_matrix),
dof_(inst, name),
mb_(inst, name),
- velocity_(inst, name){};
+ velocity_(inst, name),
+ hiz_(inst){};
~ShadingView(){};
@@ -129,6 +134,8 @@ class LightProbeView {
const float (*face_matrix_)[4];
/** GBuffer for deferred passes. */
GBuffer gbuffer_;
+ /** HiZBuffer for screenspace effects. */
+ HiZBuffer hiz_;
/** Owned resources. */
Framebuffer view_fb_;
/** DRWView of this face. */
@@ -141,7 +148,7 @@ class LightProbeView {
public:
LightProbeView(Instance &inst, const char *name, const float (*face_matrix)[4], int layer_)
- : inst_(inst), name_(name), face_matrix_(face_matrix), layer_(layer_){};
+ : inst_(inst), name_(name), face_matrix_(face_matrix), hiz_(inst), layer_(layer_){};
~LightProbeView(){};
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl
index 9335970ba4d..dd4d0ba4f20 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_deferred_direct_frag.glsl
@@ -46,7 +46,7 @@ layout(std140) uniform lightprobes_info_block
LightProbeInfoData probes_info;
};
-uniform sampler2D depth_tx;
+uniform sampler2D hiz_tx;
uniform sampler2D emission_data_tx;
uniform sampler2D transmit_color_tx;
uniform sampler2D transmit_normal_tx;
@@ -84,7 +84,7 @@ vec3 lightprobe_cubemap_eval(vec3 P, vec3 R, float roughness, float random_thres
void main(void)
{
- float gbuffer_depth = texture(depth_tx, uvcoordsvar.xy).r;
+ float gbuffer_depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r;
vec3 vP = get_view_space_from_depth(uvcoordsvar.xy, gbuffer_depth);
vec3 P = point_view_to_world(vP);
vec3 V = cameraVec(P);
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl
new file mode 100644
index 00000000000..f0ee9f515c9
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_hiz_copy_frag.glsl
@@ -0,0 +1,17 @@
+/**
+ * Copy input depth texture to lower left corner of the destination, filling any padding with
+ * clamped texture extrapolation.
+ */
+
+#pragma BLENDER_REQUIRE(common_view_lib.glsl)
+
+uniform sampler2D depth_tx;
+
+layout(location = 0) out float out_depth;
+
+void main()
+{
+ vec2 uv = gl_FragCoord.xy / vec2(textureSize(depth_tx, 0).xy);
+
+ out_depth = texture(depth_tx, uv).r;
+}
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl
new file mode 100644
index 00000000000..9a095d960b2
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/eevee_hiz_downsample_frag.glsl
@@ -0,0 +1,40 @@
+/**
+ * Shader that down-sample depth buffer, creating a Hierarchical-Z buffer.
+ * Saves max value of each 2x2 texel in the mipmap above the one we are rendering to.
+ * Adapted from http://rastergrid.com/blog/2010/10/hierarchical-z-map-based-occlusion-culling/
+ *
+ * Major simplification has been made since we pad the buffer to always be bigger than input to
+ * avoid mipmapping misalignement.
+ */
+
+#pragma BLENDER_REQUIRE(common_math_lib.glsl)
+
+uniform sampler2D depth_tx;
+
+uniform vec2 texel_size;
+
+layout(location = 0) out float out_depth;
+
+#ifndef GPU_ARB_texture_gather
+vec4 texGather(sampler2D tex, vec2 uv)
+{
+ vec4 ofs = vec2(0.5, 0.5, -0.5, -0.5) * texel_size.xyxy;
+ return vec4(texture(tex, uv + ofs.zw).r,
+ texture(tex, uv + ofs.zy).r,
+ texture(tex, uv + ofs.xw).r,
+ texture(tex, uv + ofs.xy).r);
+}
+#else
+# define texGather(a, b) textureGather(a, b)
+#endif
+
+void main()
+{
+ /* NOTE(@fclem): textureSize() does not work the same on all implementations
+ * when changing the min and max texture levels. Use uniform instead (see T87801). */
+ vec2 uv = gl_FragCoord.xy * texel_size;
+
+ vec4 samp = texGather(depth_tx, uv);
+
+ out_depth = max_v4(samp);
+}
diff --git a/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl b/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl
index 50ec88b1990..e24c2dccdbf 100644
--- a/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/eevee_subsurface_eval_frag.glsl
@@ -23,7 +23,12 @@ layout(std140) uniform subsurface_block
SubsurfaceData sss;
};
-uniform sampler2D depth_tx;
+layout(std140) uniform hiz_block
+{
+ HiZData hiz;
+};
+
+uniform sampler2D hiz_tx;
uniform sampler2D radiance_tx;
uniform sampler2D transmit_color_tx;
uniform sampler2D transmit_normal_tx;
@@ -63,7 +68,8 @@ void main(void)
{
vec2 center_uv = uvcoordsvar.xy;
- vec3 vP = get_view_space_from_depth(center_uv, texture(depth_tx, center_uv).r);
+ float gbuffer_depth = texelFetch(hiz_tx, ivec2(gl_FragCoord.xy), 0).r;
+ vec3 vP = get_view_space_from_depth(center_uv, gbuffer_depth);
vec4 tra_col_in = texture(transmit_color_tx, center_uv);
vec4 tra_nor_in = texture(transmit_normal_tx, center_uv);
vec4 tra_dat_in = texture(transmit_data_tx, center_uv);
@@ -111,7 +117,7 @@ void main(void)
vec2 sample_uv = center_uv + sample_space * sss.samples[i].xy;
float pdf = sss.samples[i].z;
- float sample_depth = texture(depth_tx, sample_uv).r;
+ float sample_depth = texture(hiz_tx, sample_uv * hiz.uv_scale).r;
vec3 sample_vP = get_view_space_from_depth(sample_uv, sample_depth);
vec4 sample_data = texture(radiance_tx, sample_uv);