1
1
This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/draw/engines/eevee_next/eevee_light.hh
Clément Foucault d371dfbe2c DRW: Change binding API
Using bind() overload is too error prone.
2022-08-30 21:27:02 +02:00

170 lines
5.4 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2021 Blender Foundation.
*/
/** \file
* \ingroup eevee
*
* The light module manages light data buffers and light culling system.
*
* The culling follows the principles of Tiled Culling + Z binning from:
* "Improved Culling for Tiled and Clustered Rendering"
* by Michal Drobot
* http://advances.realtimerendering.com/s2017/2017_Sig_Improved_Culling_final.pdf
*
* The culling is separated in 4 compute phases:
* - View Culling (select pass): Create a z distance and a index buffer of visible lights.
* - Light sorting: Outputs visible lights sorted by Z distance.
* - Z binning: Compute the Z bins min/max light indices.
* - Tile intersection: Fine grained 2D culling of each lights outputting a bitmap per tile.
*/
#pragma once
#include "BLI_bitmap.h"
#include "BLI_vector.hh"
#include "DNA_light_types.h"
#include "eevee_camera.hh"
#include "eevee_sampling.hh"
#include "eevee_shader.hh"
#include "eevee_shader_shared.hh"
#include "eevee_sync.hh"
namespace blender::eevee {
class Instance;
/* -------------------------------------------------------------------- */
/** \name Light Object
* \{ */
struct Light : public LightData {
public:
bool initialized = false;
bool used = false;
public:
Light()
{
shadow_id = LIGHT_NO_SHADOW;
}
void sync(/* ShadowModule &shadows, */ const Object *ob, float threshold);
// void shadow_discard_safe(ShadowModule &shadows);
void debug_draw();
private:
float attenuation_radius_get(const ::Light *la, float light_threshold, float light_power);
void shape_parameters_set(const ::Light *la, const float scale[3]);
float shape_power_get(const ::Light *la);
float point_power_get(const ::Light *la);
};
/** \} */
/* -------------------------------------------------------------------- */
/** \name LightModule
* \{ */
/**
* The light module manages light data buffers and light culling system.
*/
class LightModule {
// friend ShadowModule;
private:
/* Keep tile count reasonable for memory usage and 2D culling performance. */
static constexpr uint max_memory_threshold = 32 * 1024 * 1024; /* 32 MiB */
static constexpr uint max_word_count_threshold = max_memory_threshold / sizeof(uint);
static constexpr uint max_tile_count_threshold = 8192;
Instance &inst_;
/** Map of light objects data. Converted to flat array each frame. */
Map<ObjectKey, Light> light_map_;
/** Flat array sent to GPU, populated from light_map_. Source buffer for light culling. */
LightDataBuf light_buf_ = {"Lights_no_cull"};
/** Recorded size of light_map_ (after pruning) to detect deletion. */
int64_t light_map_size_ = 0;
/** Luminous intensity to consider the light boundary at. Used for culling. */
float light_threshold_ = 0.01f;
/** If false, will prevent all scene light from being synced. */
bool use_scene_lights_ = false;
/** Number of sun lights synced during the last sync. Used as offset. */
int sun_lights_len_ = 0;
int local_lights_len_ = 0;
/** Sun plus local lights count for convenience. */
int lights_len_ = 0;
/**
* Light Culling
*/
/** LightData buffer used for rendering. Filled by the culling pass. */
LightDataBuf culling_light_buf_ = {"Lights_culled"};
/** Culling infos. */
LightCullingDataBuf culling_data_buf_ = {"LightCull_data"};
/** Z-distance matching the key for each visible lights. Used for sorting. */
LightCullingZdistBuf culling_zdist_buf_ = {"LightCull_zdist"};
/** Key buffer containing only visible lights indices. Used for sorting. */
LightCullingKeyBuf culling_key_buf_ = {"LightCull_key"};
/** Zbins containing min and max light index for each Z bin. */
LightCullingZbinBuf culling_zbin_buf_ = {"LightCull_zbin"};
/** Bitmap of lights touching each tiles. */
LightCullingTileBuf culling_tile_buf_ = {"LightCull_tile"};
/** Culling compute passes. */
PassSimple culling_ps_ = {"LightCulling"};
/** Total number of words the tile buffer needs to contain for the render resolution. */
uint total_word_count_ = 0;
/** Debug Culling visualization. */
PassSimple debug_draw_ps_ = {"LightCulling.Debug"};
public:
LightModule(Instance &inst) : inst_(inst){};
~LightModule(){};
void begin_sync();
void sync_light(const Object *ob, ObjectHandle &handle);
void end_sync();
/**
* Update acceleration structure for the given view.
*/
void set_view(View &view, const int2 extent);
void debug_draw(View &view, GPUFrameBuffer *view_fb);
void bind_resources(DRWShadingGroup *grp)
{
DRW_shgroup_storage_block_ref(grp, "light_buf", &culling_light_buf_);
DRW_shgroup_storage_block_ref(grp, "light_cull_buf", &culling_data_buf_);
DRW_shgroup_storage_block_ref(grp, "light_zbin_buf", &culling_zbin_buf_);
DRW_shgroup_storage_block_ref(grp, "light_tile_buf", &culling_tile_buf_);
#if 0
DRW_shgroup_uniform_texture(grp, "shadow_atlas_tx", inst_.shadows.atlas_tx_get());
DRW_shgroup_uniform_texture(grp, "shadow_tilemaps_tx", inst_.shadows.tilemap_tx_get());
#endif
}
template<typename T> void bind_resources(draw::detail::PassBase<T> *pass)
{
/* Storage Buf. */
pass->bind_ssbo(LIGHT_CULL_BUF_SLOT, &culling_data_buf_);
pass->bind_ssbo(LIGHT_BUF_SLOT, &culling_light_buf_);
pass->bind_ssbo(LIGHT_ZBIN_BUF_SLOT, &culling_zbin_buf_);
pass->bind_ssbo(LIGHT_TILE_BUF_SLOT, &culling_tile_buf_);
}
private:
void culling_pass_sync();
void debug_pass_sync();
};
/** \} */
} // namespace blender::eevee