Files
test2/source/blender/draw/intern/draw_view.hh
Clément Foucault 17db856686 EEVEE-Next: Ray-tracing Denoise Pipeline
This is a full rewrite of the raytracing denoise pipeline. It uses the
same principle as before but now uses compute shaders for every stages
and a tile base approach. More aggressive filtering is needed since we
are moving towards having no prefiltered screen radiance buffer. Thus
we introduce a temporal denoise and a bilateral denoise stage to the
denoising. These are optionnal and can be disabled.

Note that this patch does not include any tracing part and only samples
the reflection probes. It is focused on denoising only. Tracing will
come in another PR.

The motivation for this is that having hardware raytracing support
means we can't prefilter the radiance in screen space so we have to
have better denoising. Also this means we can have better surface
appearance with support for other BxDF model than GGX. Also GGX support
is improved.

Technically, the new denoising fixes some implementation mistake the
old pipeline did. It separates all 3 stages (spatial, temporal,
bilateral) and use random sampling for all stages hoping to create
a noisy enough (but still stable) output so that the TAA soaks the
remaining noise. However that's not always the case. Depending on the
nature of the scene, the input can be very high frequency and might
create lots of flickering. That why another solution needs to be found
for the higher roughness material as denoising them becomes expensive
and low quality.

Pull Request: https://projects.blender.org/blender/blender/pulls/110117
2023-08-03 15:32:06 +02:00

179 lines
4.8 KiB
C++

/* SPDX-FileCopyrightText: 2022 Blender Foundation
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/** \file
* \ingroup draw
*
* View description and states.
*
* A `draw::View` object is required for drawing geometry using the DRW api and its internal
* culling system.
*
* One `View` object can actually contain multiple view matrices if the template parameter
* `view_len` is greater than 1. This is called multi-view rendering and the vertex shader must
* setting `drw_view_id` accordingly.
*/
#include "DRW_gpu_wrapper.hh"
#include "DRW_render.h"
#include "draw_shader_shared.h"
namespace blender::draw {
class Manager;
/* TODO: de-duplicate. */
using ObjectBoundsBuf = StorageArrayBuffer<ObjectBounds, 128>;
using VisibilityBuf = StorageArrayBuffer<uint, 4, true>;
class View {
friend Manager;
protected:
/** TODO(fclem): Maybe try to reduce the minimum cost if the number of view is lower. */
UniformArrayBuffer<ViewMatrices, DRW_VIEW_MAX> data_;
UniformArrayBuffer<ViewCullingData, DRW_VIEW_MAX> culling_;
/** Frozen version of data_ used for debugging culling. */
UniformArrayBuffer<ViewMatrices, DRW_VIEW_MAX> data_freeze_;
UniformArrayBuffer<ViewCullingData, DRW_VIEW_MAX> culling_freeze_;
/** Result of the visibility computation. 1 bit or 1 or 2 word per resource ID per view. */
VisibilityBuf visibility_buf_;
const char *debug_name_;
int view_len_ = 0;
bool is_inverted_ = false;
bool do_visibility_ = true;
bool dirty_ = true;
bool frozen_ = false;
bool procedural_ = false;
public:
View(const char *name, int view_len = 1, bool procedural = false)
: visibility_buf_(name), debug_name_(name), view_len_(view_len), procedural_(procedural)
{
BLI_assert(view_len <= DRW_VIEW_MAX);
}
/* For compatibility with old system. Will be removed at some point. */
View(const char *name, const DRWView *view)
: visibility_buf_(name), debug_name_(name), view_len_(1)
{
this->sync(view);
}
void sync(const float4x4 &view_mat, const float4x4 &win_mat, int view_id = 0);
/* For compatibility with old system. Will be removed at some point. */
void sync(const DRWView *view);
/** Disable a range in the multi-view array. Disabled view will not produce any instances. */
void disable(IndexRange range);
/** Enable or disable every visibility test (frustum culling, HiZ culling). */
void visibility_test(bool enable)
{
do_visibility_ = enable;
}
/**
* Update culling data using a compute shader.
* This is to be used if the matrices were updated externally
* on the GPU (not using the `sync()` method).
**/
void compute_procedural_bounds();
bool is_persp(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].winmat[3][3] == 0.0f;
}
bool is_inverted(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
UNUSED_VARS_NDEBUG(view_id);
return is_inverted_;
}
float far_clip(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
if (is_persp(view_id)) {
return -data_[view_id].winmat[3][2] / (data_[view_id].winmat[2][2] + 1.0f);
}
return -(data_[view_id].winmat[3][2] - 1.0f) / data_[view_id].winmat[2][2];
}
float near_clip(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
if (is_persp(view_id)) {
return -data_[view_id].winmat[3][2] / (data_[view_id].winmat[2][2] - 1.0f);
}
return -(data_[view_id].winmat[3][2] + 1.0f) / data_[view_id].winmat[2][2];
}
const float4x4 &viewmat(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].viewmat;
}
const float4x4 &viewinv(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].viewinv;
}
const float4x4 &winmat(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].winmat;
}
const float4x4 &wininv(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].wininv;
}
/* Compute and return the perspective matrix. */
const float4x4 persmat(int view_id = 0) const
{
BLI_assert(view_id < view_len_);
return data_[view_id].winmat * data_[view_id].viewmat;
}
int visibility_word_per_draw() const
{
return (view_len_ == 1) ? 0 : divide_ceil_u(view_len_, 32);
}
UniformArrayBuffer<ViewMatrices, DRW_VIEW_MAX> &matrices_ubo_get()
{
return data_;
}
protected:
/** Called from draw manager. */
void bind();
virtual void compute_visibility(ObjectBoundsBuf &bounds, uint resource_len, bool debug_freeze);
virtual VisibilityBuf &get_visibility_buffer();
void update_viewport_size();
/* WARNING: These 3 functions must be called in order */
void frustum_boundbox_calc(int view_id);
void frustum_culling_planes_calc(int view_id);
void frustum_culling_sphere_calc(int view_id);
};
} // namespace blender::draw