forked from blender/blender
me-main #1
@ -631,7 +631,7 @@ struct LightData {
|
|||||||
float2 spot_size_inv;
|
float2 spot_size_inv;
|
||||||
/** Spot angle tangent. */
|
/** Spot angle tangent. */
|
||||||
float spot_tan;
|
float spot_tan;
|
||||||
/** Reuse for directionnal lod bias. */
|
/** Reuse for directional LOD bias. */
|
||||||
#define _clipmap_lod_bias spot_tan
|
#define _clipmap_lod_bias spot_tan
|
||||||
/** Power depending on shader type. */
|
/** Power depending on shader type. */
|
||||||
float diffuse_power;
|
float diffuse_power;
|
||||||
@ -643,12 +643,12 @@ struct LightData {
|
|||||||
/** Directional : Near clip distance. Float stored as int for atomic operations. */
|
/** Directional : Near clip distance. Float stored as int for atomic operations. */
|
||||||
int clip_near;
|
int clip_near;
|
||||||
int clip_far;
|
int clip_far;
|
||||||
/** Directional : Clip-map lod range to avoid sampling outside of valid range. */
|
/** Directional : Clip-map LOD range to avoid sampling outside of valid range. */
|
||||||
int clipmap_lod_min;
|
int clipmap_lod_min;
|
||||||
int clipmap_lod_max;
|
int clipmap_lod_max;
|
||||||
/** Index of the first tile-map. */
|
/** Index of the first tile-map. */
|
||||||
int tilemap_index;
|
int tilemap_index;
|
||||||
/** Directional : Offset of the lod min in lod min tile units. */
|
/** Directional : Offset of the LOD min in LOD min tile units. */
|
||||||
int2 clipmap_base_offset;
|
int2 clipmap_base_offset;
|
||||||
/** Punctual & Directional : Normal matrix packed for automatic bias. */
|
/** Punctual & Directional : Normal matrix packed for automatic bias. */
|
||||||
float2 normal_mat_packed;
|
float2 normal_mat_packed;
|
||||||
@ -758,7 +758,7 @@ struct ShadowTileData {
|
|||||||
uint2 page;
|
uint2 page;
|
||||||
/** Page index inside pages_cached_buf. Only valid if `is_cached` is true. */
|
/** Page index inside pages_cached_buf. Only valid if `is_cached` is true. */
|
||||||
uint cache_index;
|
uint cache_index;
|
||||||
/** Lod pointed to LOD 0 tile page. (cubemap only) */
|
/** LOD pointed to LOD 0 tile page. (cube-map only). */
|
||||||
uint lod;
|
uint lod;
|
||||||
/** If the tile is needed for rendering. */
|
/** If the tile is needed for rendering. */
|
||||||
bool is_used;
|
bool is_used;
|
||||||
|
@ -137,7 +137,7 @@ void ShadowTileMap::debug_draw() const
|
|||||||
ShadowTileMapPool::ShadowTileMapPool()
|
ShadowTileMapPool::ShadowTileMapPool()
|
||||||
{
|
{
|
||||||
free_indices.reserve(SHADOW_MAX_TILEMAP);
|
free_indices.reserve(SHADOW_MAX_TILEMAP);
|
||||||
/* Reverse order to help debugging (first allocated tilemap will get 0). */
|
/* Reverse order to help debugging (first allocated tile-map will get 0). */
|
||||||
for (int i = SHADOW_MAX_TILEMAP - 1; i >= 0; i--) {
|
for (int i = SHADOW_MAX_TILEMAP - 1; i >= 0; i--) {
|
||||||
free_indices.append(i * SHADOW_TILEDATA_PER_TILEMAP);
|
free_indices.append(i * SHADOW_TILEDATA_PER_TILEMAP);
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ ShadowTileMapPool::ShadowTileMapPool()
|
|||||||
ShadowTileMap *ShadowTileMapPool::acquire()
|
ShadowTileMap *ShadowTileMapPool::acquire()
|
||||||
{
|
{
|
||||||
if (free_indices.is_empty()) {
|
if (free_indices.is_empty()) {
|
||||||
/* Grow the tilemap buffer. See `end_sync`. */
|
/* Grow the tile-map buffer. See `end_sync`. */
|
||||||
for (auto i : IndexRange(free_indices.size(), SHADOW_MAX_TILEMAP)) {
|
for (auto i : IndexRange(free_indices.size(), SHADOW_MAX_TILEMAP)) {
|
||||||
free_indices.append(i * SHADOW_TILEDATA_PER_TILEMAP);
|
free_indices.append(i * SHADOW_TILEDATA_PER_TILEMAP);
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ void ShadowTileMapPool::end_sync(ShadowModule &module)
|
|||||||
tiles_data.resize(needed_tilemap_capacity * SHADOW_TILEDATA_PER_TILEMAP);
|
tiles_data.resize(needed_tilemap_capacity * SHADOW_TILEDATA_PER_TILEMAP);
|
||||||
tilemaps_clip.resize(needed_tilemap_capacity);
|
tilemaps_clip.resize(needed_tilemap_capacity);
|
||||||
/* We reallocated the tile-map buffer, discarding all the data it contained.
|
/* We reallocated the tile-map buffer, discarding all the data it contained.
|
||||||
* We need to re-init the page heaps. */
|
* We need to re-initialize the page heaps. */
|
||||||
module.do_full_update = true;
|
module.do_full_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +191,8 @@ void ShadowTileMapPool::end_sync(ShadowModule &module)
|
|||||||
Span<uint> newly_unused_indices = free_indices.as_span().slice(last_free_len,
|
Span<uint> newly_unused_indices = free_indices.as_span().slice(last_free_len,
|
||||||
newly_unused_count);
|
newly_unused_count);
|
||||||
for (uint index : newly_unused_indices) {
|
for (uint index : newly_unused_indices) {
|
||||||
/* Push a dummy tilemap to a unused tilemap buffer. It is then processed through the some of
|
/* Push a dummy tile-map to a unused tile-map buffer. It is then processed through the some
|
||||||
* the setup steps to release the pages. */
|
* of the setup steps to release the pages. */
|
||||||
ShadowTileMapData tilemap_data = {};
|
ShadowTileMapData tilemap_data = {};
|
||||||
tilemap_data.tiles_index = index;
|
tilemap_data.tiles_index = index;
|
||||||
tilemap_data.clip_data_index = 0;
|
tilemap_data.clip_data_index = 0;
|
||||||
@ -261,7 +261,7 @@ void ShadowPunctual::end_sync(Light &light, float lod_bias)
|
|||||||
obmat_tmp[0][3] = obmat_tmp[1][3] = obmat_tmp[2][3] = 0.0f;
|
obmat_tmp[0][3] = obmat_tmp[1][3] = obmat_tmp[2][3] = 0.0f;
|
||||||
obmat_tmp[3][3] = 1.0f;
|
obmat_tmp[3][3] = 1.0f;
|
||||||
|
|
||||||
/* Acquire missing tilemaps. */
|
/* Acquire missing tile-maps. */
|
||||||
while (tilemaps_.size() < tilemaps_needed_) {
|
while (tilemaps_.size() < tilemaps_needed_) {
|
||||||
tilemaps_.append(tilemap_pool.acquire());
|
tilemaps_.append(tilemap_pool.acquire());
|
||||||
}
|
}
|
||||||
@ -311,23 +311,23 @@ void ShadowPunctual::end_sync(Light &light, float lod_bias)
|
|||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Directional Shadow Maps
|
/** \name Directional Shadow Maps
|
||||||
*
|
*
|
||||||
* In order to inprove shadow map density, we switch between two tilemap distribution mode.
|
* In order to improve shadow map density, we switch between two tile-map distribution mode.
|
||||||
* One is beter suited for large FOV (clipmap), the other for really small FOV or Orthographic
|
* One is beater suited for large FOV (clip-map), the other for really small FOV or Orthographic
|
||||||
* projections (cascade).
|
* projections (cascade).
|
||||||
*
|
*
|
||||||
* Clipmap distribution centers a number of log2 sized tilemaps around the view position.
|
* Clip-map distribution centers a number of log2 sized tile-maps around the view position.
|
||||||
* https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-2-terrain-rendering-using-gpu-based-geometry
|
* https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-2-terrain-rendering-using-gpu-based-geometry
|
||||||
*
|
*
|
||||||
* Cascade distribution puts tilemaps along the frustum projection to the light space.
|
* Cascade distribution puts tile-maps along the frustum projection to the light space.
|
||||||
* https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-10-parallel-split-shadow-maps-programmable-gpus
|
* https://developer.nvidia.com/gpugems/gpugems3/part-ii-light-and-shadows/chapter-10-parallel-split-shadow-maps-programmable-gpus
|
||||||
*
|
*
|
||||||
* We choose to distribute cascades linearly to acheive uniform density and simplify lookup.
|
* We choose to distribute cascades linearly to achieve uniform density and simplify lookup.
|
||||||
* Using clipmap instead of cascades for perspective view also allows for better caching.
|
* Using clip-map instead of cascades for perspective view also allows for better caching.
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
eShadowProjectionType ShadowDirectional::directional_distribution_type_get(const Camera &camera)
|
eShadowProjectionType ShadowDirectional::directional_distribution_type_get(const Camera &camera)
|
||||||
{
|
{
|
||||||
/* TODO(fclem): Enable the cascade projection if the fov is tiny in perspective mode. */
|
/* TODO(fclem): Enable the cascade projection if the FOV is tiny in perspective mode. */
|
||||||
return camera.is_perspective() ? SHADOW_PROJECTION_CLIPMAP : SHADOW_PROJECTION_CASCADE;
|
return camera.is_perspective() ? SHADOW_PROJECTION_CLIPMAP : SHADOW_PROJECTION_CASCADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,24 +347,24 @@ void ShadowDirectional::cascade_tilemaps_distribution_near_far_points(const Came
|
|||||||
float3x3(object_mat_.view<3, 3>());
|
float3x3(object_mat_.view<3, 3>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* \note All tilemaps are meant to have the same LOD but we still return a range starting at the
|
/* \note All tile-maps are meant to have the same LOD but we still return a range starting at the
|
||||||
* unique LOD. */
|
* unique LOD. */
|
||||||
IndexRange ShadowDirectional::cascade_level_range(const Camera &camera, float lod_bias)
|
IndexRange ShadowDirectional::cascade_level_range(const Camera &camera, float lod_bias)
|
||||||
{
|
{
|
||||||
using namespace blender::math;
|
using namespace blender::math;
|
||||||
|
|
||||||
/* 16 is arbitrary. To avoid too much tilemap per directional lights. */
|
/* 16 is arbitrary. To avoid too much tile-map per directional lights. */
|
||||||
const int max_tilemap_per_shadows = 16;
|
const int max_tilemap_per_shadows = 16;
|
||||||
const CameraData &cam_data = camera.data_get();
|
const CameraData &cam_data = camera.data_get();
|
||||||
|
|
||||||
float3 near_point, far_point;
|
float3 near_point, far_point;
|
||||||
cascade_tilemaps_distribution_near_far_points(camera, near_point, far_point);
|
cascade_tilemaps_distribution_near_far_points(camera, near_point, far_point);
|
||||||
|
|
||||||
/* This gives the maximum resolution in depth we can have with a fixed set of tilemaps. Gives
|
/* This gives the maximum resolution in depth we can have with a fixed set of tile-maps. Gives
|
||||||
* the best results when view direction is orthogonal to the light direction. */
|
* the best results when view direction is orthogonal to the light direction. */
|
||||||
float depth_range_in_shadow_space = distance(far_point.xy(), near_point.xy());
|
float depth_range_in_shadow_space = distance(far_point.xy(), near_point.xy());
|
||||||
float min_depth_tilemap_size = 2 * (depth_range_in_shadow_space / max_tilemap_per_shadows);
|
float min_depth_tilemap_size = 2 * (depth_range_in_shadow_space / max_tilemap_per_shadows);
|
||||||
/* This allow coverage of the whole view with a single tilemap if camera forward is colinear
|
/* This allow coverage of the whole view with a single tile-map if camera forward is colinear
|
||||||
* with the light direction. */
|
* with the light direction. */
|
||||||
float min_diagonal_tilemap_size = cam_data.screen_diagonal_length;
|
float min_diagonal_tilemap_size = cam_data.screen_diagonal_length;
|
||||||
|
|
||||||
@ -373,28 +373,28 @@ IndexRange ShadowDirectional::cascade_level_range(const Camera &camera, float lo
|
|||||||
min_diagonal_tilemap_size *= cam_data.clip_far / cam_data.clip_near;
|
min_diagonal_tilemap_size *= cam_data.clip_far / cam_data.clip_near;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow better tilemap usage without missing pages near end of view. */
|
/* Allow better tile-map usage without missing pages near end of view. */
|
||||||
lod_bias += 0.5f;
|
lod_bias += 0.5f;
|
||||||
/* Level of detail (or size) of every tilemaps of this light. */
|
/* Level of detail (or size) of every tile-maps of this light. */
|
||||||
int lod_level = ceil(log2(max_ff(min_depth_tilemap_size, min_diagonal_tilemap_size)) + lod_bias);
|
int lod_level = ceil(log2(max_ff(min_depth_tilemap_size, min_diagonal_tilemap_size)) + lod_bias);
|
||||||
|
|
||||||
/* Tilemaps "rotate" around the first one so their effective range is only half their size. */
|
/* Tile-maps "rotate" around the first one so their effective range is only half their size. */
|
||||||
float per_tilemap_coverage = ShadowDirectional::coverage_get(lod_level) * 0.5f;
|
float per_tilemap_coverage = ShadowDirectional::coverage_get(lod_level) * 0.5f;
|
||||||
/* Number of tilemaps needed to cover the whole view. */
|
/* Number of tile-maps needed to cover the whole view. */
|
||||||
/* Note: floor + 0.5 to avoid 0 when parallel. */
|
/* Note: floor + 0.5 to avoid 0 when parallel. */
|
||||||
int tilemap_len = ceil(0.5f + depth_range_in_shadow_space / per_tilemap_coverage);
|
int tilemap_len = ceil(0.5f + depth_range_in_shadow_space / per_tilemap_coverage);
|
||||||
return IndexRange(lod_level, tilemap_len);
|
return IndexRange(lod_level, tilemap_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Distribute tilemaps in a linear pattern along camera forward vector instead of a clipmap
|
* Distribute tile-maps in a linear pattern along camera forward vector instead of a clipmap
|
||||||
* centered on camera position.
|
* centered on camera position.
|
||||||
*/
|
*/
|
||||||
void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera &camera)
|
void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera &camera)
|
||||||
{
|
{
|
||||||
using namespace blender::math;
|
using namespace blender::math;
|
||||||
|
|
||||||
/* All tilemaps use the first level size. */
|
/* All tile-maps use the first level size. */
|
||||||
float half_size = ShadowDirectional::coverage_get(levels_range.first()) / 2.0f;
|
float half_size = ShadowDirectional::coverage_get(levels_range.first()) / 2.0f;
|
||||||
float tile_size = ShadowDirectional::tile_size_get(levels_range.first());
|
float tile_size = ShadowDirectional::tile_size_get(levels_range.first());
|
||||||
|
|
||||||
@ -407,14 +407,14 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
|
|||||||
/* Offset for smooth level transitions. */
|
/* Offset for smooth level transitions. */
|
||||||
light.object_mat.location() = near_point;
|
light.object_mat.location() = near_point;
|
||||||
|
|
||||||
/* Offset in tiles from the origin to the center of the first tilemaps. */
|
/* Offset in tiles from the origin to the center of the first tile-maps. */
|
||||||
int2 origin_offset = int2(round(float2(near_point) / tile_size));
|
int2 origin_offset = int2(round(float2(near_point) / tile_size));
|
||||||
/* Offset in tiles between the first andlod the last tilemaps. */
|
/* Offset in tiles between the first andlod the last tile-maps. */
|
||||||
int2 offset_vector = int2(round(farthest_tilemap_center / tile_size));
|
int2 offset_vector = int2(round(farthest_tilemap_center / tile_size));
|
||||||
|
|
||||||
light.clipmap_base_offset = (offset_vector * (1 << 16)) / max_ii(levels_range.size() - 1, 1);
|
light.clipmap_base_offset = (offset_vector * (1 << 16)) / max_ii(levels_range.size() - 1, 1);
|
||||||
|
|
||||||
/* \note: cascade_level_range starts the range at the unique LOD to apply to all tilemaps. */
|
/* \note: cascade_level_range starts the range at the unique LOD to apply to all tile-maps. */
|
||||||
int level = levels_range.first();
|
int level = levels_range.first();
|
||||||
for (int i : IndexRange(levels_range.size())) {
|
for (int i : IndexRange(levels_range.size())) {
|
||||||
ShadowTileMap *tilemap = tilemaps_[i];
|
ShadowTileMap *tilemap = tilemaps_[i];
|
||||||
@ -433,8 +433,8 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
|
|||||||
|
|
||||||
light.type = LIGHT_SUN_ORTHO;
|
light.type = LIGHT_SUN_ORTHO;
|
||||||
|
|
||||||
/* Not really clipmaps, but this is in order to make light_tilemap_max_get() work and determine
|
/* Not really clip-maps, but this is in order to make #light_tilemap_max_get() work and determine
|
||||||
* the scalling. */
|
* the scaling. */
|
||||||
light.clipmap_lod_min = levels_range.first();
|
light.clipmap_lod_min = levels_range.first();
|
||||||
light.clipmap_lod_max = levels_range.last();
|
light.clipmap_lod_max = levels_range.last();
|
||||||
|
|
||||||
@ -505,7 +505,7 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light,
|
|||||||
for (int lod : IndexRange(levels_range.size() - 1)) {
|
for (int lod : IndexRange(levels_range.size() - 1)) {
|
||||||
/* Since offset can only differ by one tile from the higher level, we can compress that as a
|
/* Since offset can only differ by one tile from the higher level, we can compress that as a
|
||||||
* single integer where one bit contains offset between 2 levels. Then a single bit shift in
|
* single integer where one bit contains offset between 2 levels. Then a single bit shift in
|
||||||
* the shader gives the number of tile to offset in the given tilemap space. However we need
|
* the shader gives the number of tile to offset in the given tile-map space. However we need
|
||||||
* also the sign of the offset for each level offset. To this end, we split the negative
|
* also the sign of the offset for each level offset. To this end, we split the negative
|
||||||
* offsets to a separate int.
|
* offsets to a separate int.
|
||||||
* Recovering the offset with: (pos_offset >> lod) - (neg_offset >> lod). */
|
* Recovering the offset with: (pos_offset >> lod) - (neg_offset >> lod). */
|
||||||
@ -583,7 +583,7 @@ void ShadowDirectional::end_sync(Light &light, const Camera &camera, float lod_b
|
|||||||
clipmap_level_range(camera);
|
clipmap_level_range(camera);
|
||||||
|
|
||||||
if (levels_range != levels_new) {
|
if (levels_range != levels_new) {
|
||||||
/* Acquire missing tilemaps. */
|
/* Acquire missing tile-maps. */
|
||||||
IndexRange isect_range = levels_new.intersect(levels_range);
|
IndexRange isect_range = levels_new.intersect(levels_range);
|
||||||
int64_t before_range = isect_range.start() - levels_new.start();
|
int64_t before_range = isect_range.start() - levels_new.start();
|
||||||
int64_t after_range = levels_new.one_after_last() - isect_range.one_after_last();
|
int64_t after_range = levels_new.one_after_last() - isect_range.one_after_last();
|
||||||
@ -666,7 +666,7 @@ void ShadowModule::init()
|
|||||||
inst_.info = "Error: Could not allocate shadow atlas. Most likely out of GPU memory.";
|
inst_.info = "Error: Could not allocate shadow atlas. Most likely out of GPU memory.";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read end of the swapchain to avoid stall. */
|
/* Read end of the swap-chain to avoid stall. */
|
||||||
{
|
{
|
||||||
if (inst_.sampling.finished_viewport()) {
|
if (inst_.sampling.finished_viewport()) {
|
||||||
/* Swap enough to read the last one. */
|
/* Swap enough to read the last one. */
|
||||||
@ -769,7 +769,7 @@ void ShadowModule::sync_object(const ObjectHandle &handle,
|
|||||||
|
|
||||||
void ShadowModule::end_sync()
|
void ShadowModule::end_sync()
|
||||||
{
|
{
|
||||||
/* Delete unused shadows first to release tilemaps that could be reused for new lights. */
|
/* Delete unused shadows first to release tile-maps that could be reused for new lights. */
|
||||||
for (Light &light : inst_.lights.light_map_.values()) {
|
for (Light &light : inst_.lights.light_map_.values()) {
|
||||||
if (!light.used || !enabled_) {
|
if (!light.used || !enabled_) {
|
||||||
light.shadow_discard_safe(*this);
|
light.shadow_discard_safe(*this);
|
||||||
@ -782,7 +782,7 @@ void ShadowModule::end_sync()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate new tilemaps and fill shadow data of the lights. */
|
/* Allocate new tile-maps and fill shadow data of the lights. */
|
||||||
tilemap_pool.tilemaps_data.clear();
|
tilemap_pool.tilemaps_data.clear();
|
||||||
for (Light &light : inst_.lights.light_map_.values()) {
|
for (Light &light : inst_.lights.light_map_.values()) {
|
||||||
if (light.directional != nullptr) {
|
if (light.directional != nullptr) {
|
||||||
@ -831,7 +831,7 @@ void ShadowModule::end_sync()
|
|||||||
/* Clear tiles to not reference any page. */
|
/* Clear tiles to not reference any page. */
|
||||||
tilemap_pool.tiles_data.clear_to_zero();
|
tilemap_pool.tiles_data.clear_to_zero();
|
||||||
|
|
||||||
/* Clear tilemap clip buffer. */
|
/* Clear tile-map clip buffer. */
|
||||||
union {
|
union {
|
||||||
ShadowTileMapClip clip;
|
ShadowTileMapClip clip;
|
||||||
int4 i;
|
int4 i;
|
||||||
@ -877,7 +877,7 @@ void ShadowModule::end_sync()
|
|||||||
sub.barrier(GPU_BARRIER_SHADER_STORAGE);
|
sub.barrier(GPU_BARRIER_SHADER_STORAGE);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
/** Clear usage bits. Tag update from the tilemap for sun shadow clip-maps shifting. */
|
/** Clear usage bits. Tag update from the tile-map for sun shadow clip-maps shifting. */
|
||||||
PassSimple::Sub &sub = pass.sub("Init");
|
PassSimple::Sub &sub = pass.sub("Init");
|
||||||
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_TILEMAP_INIT));
|
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_TILEMAP_INIT));
|
||||||
sub.bind_ssbo("tilemaps_buf", tilemap_pool.tilemaps_data);
|
sub.bind_ssbo("tilemaps_buf", tilemap_pool.tilemaps_data);
|
||||||
@ -1120,15 +1120,15 @@ void ShadowModule::set_view(View &view)
|
|||||||
tile_update_remains = false;
|
tile_update_remains = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* This provoke a GPU/CPU sync. Avoid it if we are sure that all tilemaps will be rendered in
|
/* This provoke a GPU/CPU sync. Avoid it if we are sure that all tile-maps will be rendered
|
||||||
* a single iteration. */
|
* in a single iteration. */
|
||||||
bool enough_tilemap_for_single_iteration = tilemap_pool.tilemaps_data.size() <=
|
bool enough_tilemap_for_single_iteration = tilemap_pool.tilemaps_data.size() <=
|
||||||
SHADOW_VIEW_MAX;
|
SHADOW_VIEW_MAX;
|
||||||
if (enough_tilemap_for_single_iteration) {
|
if (enough_tilemap_for_single_iteration) {
|
||||||
tile_update_remains = false;
|
tile_update_remains = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Readback and check if there is still tilemap to update. */
|
/* Read back and check if there is still tile-map to update. */
|
||||||
tile_update_remains = false;
|
tile_update_remains = false;
|
||||||
statistics_buf_.current().read();
|
statistics_buf_.current().read();
|
||||||
ShadowStatistics stats = statistics_buf_.current();
|
ShadowStatistics stats = statistics_buf_.current();
|
||||||
|
@ -123,7 +123,7 @@ struct ShadowTileMapPool {
|
|||||||
Vector<uint> free_indices;
|
Vector<uint> free_indices;
|
||||||
/** Pool containing shadow tile structure on CPU. */
|
/** Pool containing shadow tile structure on CPU. */
|
||||||
Pool<ShadowTileMap> tilemap_pool;
|
Pool<ShadowTileMap> tilemap_pool;
|
||||||
/** Sorted descriptions for each tilemap in the pool. Updated each frame. */
|
/** Sorted descriptions for each tile-map in the pool. Updated each frame. */
|
||||||
ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
|
ShadowTileMapDataBuf tilemaps_data = {"tilemaps_data"};
|
||||||
/** Previously used tile-maps that needs to release their tiles/pages. Updated each frame. */
|
/** Previously used tile-maps that needs to release their tiles/pages. Updated each frame. */
|
||||||
ShadowTileMapDataBuf tilemaps_unused = {"tilemaps_unused"};
|
ShadowTileMapDataBuf tilemaps_unused = {"tilemaps_unused"};
|
||||||
@ -190,7 +190,7 @@ class ShadowModule {
|
|||||||
Map<ObjectKey, ShadowObject> objects_;
|
Map<ObjectKey, ShadowObject> objects_;
|
||||||
|
|
||||||
/* -------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------- */
|
||||||
/** \name Tilemap Management
|
/** \name Tile-map Management
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
PassSimple tilemap_setup_ps_ = {"TilemapSetup"};
|
PassSimple tilemap_setup_ps_ = {"TilemapSetup"};
|
||||||
@ -214,7 +214,7 @@ class ShadowModule {
|
|||||||
StorageArrayBuffer<uint, SHADOW_MAX_PAGE> clear_page_buf_ = {"clear_page_buf"};
|
StorageArrayBuffer<uint, SHADOW_MAX_PAGE> clear_page_buf_ = {"clear_page_buf"};
|
||||||
|
|
||||||
int3 dispatch_depth_scan_size_;
|
int3 dispatch_depth_scan_size_;
|
||||||
/* Ratio between tilemap pixel world "radius" and film pixel world "radius". */
|
/* Ratio between tile-map pixel world "radius" and film pixel world "radius". */
|
||||||
float tilemap_projection_ratio_;
|
float tilemap_projection_ratio_;
|
||||||
|
|
||||||
/* Statistics that are read back to CPU after a few frame (to avoid stall). */
|
/* Statistics that are read back to CPU after a few frame (to avoid stall). */
|
||||||
@ -230,7 +230,7 @@ class ShadowModule {
|
|||||||
/** Atlas containing all physical pages. */
|
/** Atlas containing all physical pages. */
|
||||||
Texture atlas_tx_ = {"shadow_atlas_tx_"};
|
Texture atlas_tx_ = {"shadow_atlas_tx_"};
|
||||||
|
|
||||||
/** Pool of unallocated pages waiting to be assigned to specific tiles in the tilemap atlas. */
|
/** Pool of unallocated pages waiting to be assigned to specific tiles in the tile-map atlas. */
|
||||||
ShadowPageHeapBuf pages_free_data_ = {"PagesFreeBuf"};
|
ShadowPageHeapBuf pages_free_data_ = {"PagesFreeBuf"};
|
||||||
/** Pool of cached tiles waiting to be reused. */
|
/** Pool of cached tiles waiting to be reused. */
|
||||||
ShadowPageCacheBuf pages_cached_data_ = {"PagesCachedBuf"};
|
ShadowPageCacheBuf pages_cached_data_ = {"PagesCachedBuf"};
|
||||||
@ -259,7 +259,7 @@ class ShadowModule {
|
|||||||
64,
|
64,
|
||||||
nullptr,
|
nullptr,
|
||||||
SHADOW_TILEMAP_LOD + 1};
|
SHADOW_TILEMAP_LOD + 1};
|
||||||
/** An empty frame-buffer (no attachment) the size of a whole tilemap. */
|
/** An empty frame-buffer (no attachment) the size of a whole tile-map. */
|
||||||
Framebuffer render_fb_;
|
Framebuffer render_fb_;
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
@ -416,7 +416,7 @@ class ShadowDirectional : public NonCopyable, NonMovable {
|
|||||||
*/
|
*/
|
||||||
void end_sync(Light &light, const Camera &camera, float lod_bias);
|
void end_sync(Light &light, const Camera &camera, float lod_bias);
|
||||||
|
|
||||||
/* Return coverage of the whole tilemap in world unit. */
|
/* Return coverage of the whole tile-map in world unit. */
|
||||||
static float coverage_get(int lvl)
|
static float coverage_get(int lvl)
|
||||||
{
|
{
|
||||||
/* This function should be kept in sync with shadow_directional_level(). */
|
/* This function should be kept in sync with shadow_directional_level(). */
|
||||||
@ -424,7 +424,7 @@ class ShadowDirectional : public NonCopyable, NonMovable {
|
|||||||
return exp2(lvl);
|
return exp2(lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return coverage of a single tile for a tilemap of this LOD in world unit. */
|
/* Return coverage of a single tile for a tile-map of this LOD in world unit. */
|
||||||
static float tile_size_get(int lvl)
|
static float tile_size_get(int lvl)
|
||||||
{
|
{
|
||||||
return coverage_get(lvl) / SHADOW_TILEMAP_RES;
|
return coverage_get(lvl) / SHADOW_TILEMAP_RES;
|
||||||
@ -441,8 +441,8 @@ class ShadowDirectional : public NonCopyable, NonMovable {
|
|||||||
float3 &near_point,
|
float3 &near_point,
|
||||||
float3 &far_point);
|
float3 &far_point);
|
||||||
|
|
||||||
/* Choose between clipmap and cascade distribution of shadowmap precision depending on the camera
|
/* Choose between clip-map and cascade distribution of shadow-map precision depending on the
|
||||||
* projection type and bounds. */
|
* camera projection type and bounds. */
|
||||||
static eShadowProjectionType directional_distribution_type_get(const Camera &camera);
|
static eShadowProjectionType directional_distribution_type_get(const Camera &camera);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ static void sculpt_boundary_falloff_factor_init(SculptSession *ss,
|
|||||||
const int div = boundary_distance / radius;
|
const int div = boundary_distance / radius;
|
||||||
const float mod = fmodf(boundary_distance, radius);
|
const float mod = fmodf(boundary_distance, radius);
|
||||||
falloff_distance = div % 2 == 0 ? mod : radius - mod;
|
falloff_distance = div % 2 == 0 ? mod : radius - mod;
|
||||||
/* Inverts the faloff in the intervals 1 2 5 6 9 10 ... */
|
/* Inverts the falloff in the intervals 1 2 5 6 9 10 ... etc. */
|
||||||
if (((div - 1) & 2) == 0) {
|
if (((div - 1) & 2) == 0) {
|
||||||
direction = -1.0f;
|
direction = -1.0f;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user