Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions scripts/startup/bl_ui/properties_data_light.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,6 @@ def draw(self, context):
row.prop(light, "shadow_maximum_resolution", text="Resolution Limit")
if light.type != 'SUN':
row.prop(light, "use_absolute_resolution", text="", icon='DRIVER_DISTANCE')
if light.type == 'SUN':
sub = sub.column(align=True)
sub.prop(light, "shadow_map_scale", text="Shadow Map Scale")


class DATA_PT_EEVEE_light_influence(DataButtonsPanel, Panel):
Expand Down
1 change: 1 addition & 0 deletions scripts/startup/bl_ui/properties_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ def draw(self, context):

col = layout.column()
col.prop(props, "shadow_resolution_scale", text="Resolution")
col.prop(props, "shadow_page_resolution", text="Page Resolution")


class RENDER_PT_eevee_sampling(RenderButtonsPanel, Panel):
Expand Down
8 changes: 0 additions & 8 deletions source/blender/blenloader/intern/versioning_510.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1306,14 +1306,6 @@ void blo_do_versions_510(FileData *fd, Library * /*lib*/, Main *bmain)
version_replace_outline_control_width_variation(bmain);
}

if (!MAIN_VERSION_FILE_ATLEAST(bmain, 501, 47)) {
for (Light &light : bmain->lights) {
if (light.shadow_map_scale <= 0.0f) {
light.shadow_map_scale = 1.0f;
}
}
}

if (!MAIN_VERSION_FILE_ATLEAST(bmain, 501, 48) ||
!DNA_struct_member_exists(fd->filesdna, "Material", "char", "stencil_enabled"))
{
Expand Down
6 changes: 6 additions & 0 deletions source/blender/blenloader/intern/versioning_520.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,12 @@ void blo_do_versions_520(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
version_npr_image_sample_offset_socket_identifier(bmain);
}

if (!MAIN_VERSION_FILE_ATLEAST(bmain, 502, 47)) {
for (Scene &scene : bmain->scenes) {
scene.eevee.shadow_page_resolution = 256;
}
}

/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.
Expand Down
2 changes: 1 addition & 1 deletion source/blender/draw/engines/eevee/eevee_defines.hh
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@
# define SHADOW_PAGE_LOD 3 /* LOG2(SHADOW_PAGE_RES) */
#else
# define SHADOW_PAGE_CLEAR_GROUP_SIZE 32
# define SHADOW_PAGE_RES 256
# define SHADOW_PAGE_LOD 8 /* LOG2(SHADOW_PAGE_RES) */
# define SHADOW_PAGE_RES (1 << SHADOW_PAGE_LOD)
#endif
/* For testing only. */
// #define SHADOW_FORCE_LOD0
Expand Down
6 changes: 4 additions & 2 deletions source/blender/draw/engines/eevee/eevee_light.cc
Original file line number Diff line number Diff line change
Expand Up @@ -499,11 +499,12 @@ void Light::sync(ShadowModule &shadows,
this->power[LIGHT_VOLUME] = la->volume_fac * point_power * volume_visibility;

this->lod_bias = shadows.global_lod_bias();
this->shadow_page_lod = float(shadows.shadow_page_lod());
this->shadow_page_res = float(1 << shadows.shadow_page_lod());
this->lod_min = shadow_lod_min_get(la);
this->filter_radius = la->shadow_filter_radius;
this->shadow_jitter = (la->mode & LA_SHADOW_JITTER) != 0;
this->lightgroup_id = max_ii(lightgroup_id, 0);
this->shadow_map_scale = max_ff(la->shadow_map_scale, 0.0001f);
this->visible_camera = (visibility_flag & OB_HIDE_CAMERA) == 0;

if (la->mode & LA_SHADOW) {
Expand Down Expand Up @@ -531,7 +532,8 @@ float Light::shadow_lod_min_get(const blender::Light *la)
/* Property is in mm. Convert to unit. */
float max_res_unit = la->shadow_maximum_resolution;
if (is_sun_light(this->type)) {
return log2f(max_res_unit * SHADOW_MAP_MAX_RES) - 1.0f;
float map_max_res = float((1 << int(this->shadow_page_lod)) * SHADOW_TILEMAP_RES);
return log2f(max_res_unit * map_max_res) - 1.0f;
}
/* Store absolute mode as negative. */
return (la->mode & LA_SHAD_RES_ABSOLUTE) ? -max_res_unit : max_res_unit;
Expand Down
6 changes: 3 additions & 3 deletions source/blender/draw/engines/eevee/eevee_light_shared.hh
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,12 @@ struct [[host_shared]] LightData {
* to zero after each sync cycle. */
uint2 shadow_set_membership;

float shadow_map_scale;
float _pad7;
float _pad8;
float shadow_page_lod;
float shadow_page_res;
float _pad9;
float _pad10;
float _pad11;
float _pad13;

union {
union_t<struct LightLocalData> local;
Expand Down
2 changes: 2 additions & 0 deletions source/blender/draw/engines/eevee/eevee_pipeline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,8 @@ PassMain::Sub *ShadowPipeline::surface_material_add(blender::Material *material,
material_pass->shader_set(GPU_pass_shader_get(gpupass));
material_pass->push_constant("use_shadow_caster_atlas",
inst_.shadows.use_caster_atlas_push_ref());
material_pass->push_constant("shadow_page_lod",
inst_.shadows.shadow_page_lod_push_ref());
return material_pass;
}

Expand Down
44 changes: 26 additions & 18 deletions source/blender/draw/engines/eevee/eevee_shadow.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ ShadowTechnique ShadowModule::shadow_technique = ShadowTechnique::ATOMIC_RASTER;
void ShadowTileMap::sync_orthographic(const float4x4 &object_mat_,
int2 origin_offset,
int clipmap_level,
float shadow_map_scale_,
eShadowProjectionType projection_type_,
uint2 shadow_set_membership_)
{
Expand All @@ -77,13 +76,6 @@ void ShadowTileMap::sync_orthographic(const float4x4 &object_mat_,
light_type = eLightType::LIGHT_SUN;
shadow_set_membership = shadow_set_membership_;

/* If the shadow map scale changed, mark the tilemap dirty so it gets re-generated.
* This mirrors the behaviour when the light direction / object matrix changes. */
if (shadow_map_scale != shadow_map_scale_) {
set_dirty();
}
shadow_map_scale = shadow_map_scale_;

grid_shift = origin_offset - grid_offset;
grid_offset = origin_offset;

Expand Down Expand Up @@ -328,8 +320,11 @@ void ShadowPunctual::end_sync(Light &light)

eShadowProjectionType ShadowDirectional::directional_distribution_type_get(const Camera &camera)
{
/* TODO(fclem): Enable the cascade projection if the FOV is tiny in perspective mode. */
return camera.is_perspective() ? SHADOW_PROJECTION_CLIPMAP : SHADOW_PROJECTION_CASCADE;
if (camera.is_perspective()) {
/* TODO: Make telephoto auto-switch a user-configurable option. */
return SHADOW_PROJECTION_CLIPMAP;
}
return SHADOW_PROJECTION_CASCADE;
}

static int clipmap_level_perspective_bias(const Camera &camera)
Expand Down Expand Up @@ -521,7 +516,6 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
tilemap->sync_orthographic(object_mat,
level_offset,
level,
light.shadow_map_scale,
SHADOW_PROJECTION_CASCADE,
light.shadow_set_membership);

Expand Down Expand Up @@ -550,7 +544,7 @@ ShadowDirectional::LevelSpan ShadowDirectional::clipmap_level_range(const Camera

const CameraData &cam_data = cam.data_get();
/* Covers the closest points of the view. */
int min_level = max_ii(0, floor(log2(max_ff(cam_data.clip_near, 1e-8f))));
int min_level = floor(log2(max_ff(cam_data.clip_near, 1e-8f)));
/* Covers the farthest points of the view. */
int max_level = ceil(log2(cam.bound_radius() + distance(cam.bound_center(), cam.position())));

Expand Down Expand Up @@ -594,7 +588,6 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light, const Camera
tilemap->sync_orthographic(object_mat,
level_offset,
level,
light.shadow_map_scale,
SHADOW_PROJECTION_CLIPMAP,
light.shadow_set_membership);

Expand Down Expand Up @@ -813,7 +806,18 @@ void ShadowModule::init()
data_.step_count = 1;
}

const int2 atlas_extent = shadow_page_size_ * int2(SHADOW_PAGE_PER_ROW, SHADOW_PAGE_PER_COL);
/* Read shadow page resolution from user setting. */
const int new_lod = log2_ceil_u(scene.eevee.shadow_page_resolution);
if (shadow_page_lod_ != new_lod) {
shadow_page_lod_ = new_lod;
/* Force full rebuild on resolution change. */
do_full_update_ = true;
for (Light &light : inst_.lights.light_map_.values()) {
light.initialized = false;
}
}

const int2 atlas_extent = (1 << shadow_page_lod_) * int2(SHADOW_PAGE_PER_ROW, SHADOW_PAGE_PER_COL);

eGPUTextureUsage tex_usage = GPU_TEXTURE_USAGE_SHADER_READ | GPU_TEXTURE_USAGE_SHADER_WRITE;
if (ShadowModule::shadow_technique == ShadowTechnique::ATOMIC_RASTER) {
Expand All @@ -834,7 +838,7 @@ void ShadowModule::init()
shadow_pool_retry_countdown_ = 0;
}

const size_t page_byte_size = square_i(shadow_page_size_) * sizeof(int);
const size_t page_byte_size = square_i(1 << shadow_page_lod_) * sizeof(int);
const uint64_t requested_pool_byte_size = uint64_t(shadow_pool_size_requested_) * square_i(1024);
const int requested_page_len = enabled_ ?
max_ii(1,
Expand Down Expand Up @@ -964,8 +968,8 @@ void ShadowModule::init()
int size_in_tile = min_ii(1 << i, SHADOW_TILEMAP_RES);
multi_viewports_[i][0] = 0;
multi_viewports_[i][1] = 0;
multi_viewports_[i][2] = size_in_tile * shadow_page_size_;
multi_viewports_[i][3] = size_in_tile * shadow_page_size_;
multi_viewports_[i][2] = size_in_tile * (1 << shadow_page_lod_);
multi_viewports_[i][3] = size_in_tile * (1 << shadow_page_lod_);
}
}

Expand Down Expand Up @@ -1396,6 +1400,8 @@ void ShadowModule::end_sync()
/* De-fragment the free page heap after cache reuse phase which can leave hole. */
PassSimple::Sub &sub = pass.sub("Defrag");
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_PAGE_DEFRAG));
sub.push_constant("shadow_page_lod", shadow_page_lod_);
sub.push_constant("shadow_page_res", 1 << shadow_page_lod_);
sub.bind_ssbo("pages_infos_buf", pages_infos_data_);
sub.bind_ssbo("pages_free_buf", pages_free_data_);
sub.bind_ssbo("pages_cached_buf", pages_cached_data_);
Expand Down Expand Up @@ -1469,6 +1475,8 @@ void ShadowModule::end_sync()
sub.framebuffer_set(&render_fb_);
sub.state_set(DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS);
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_PAGE_CLEAR));
sub.push_constant("shadow_page_lod", shadow_page_lod_);
sub.push_constant("shadow_page_res", 1 << shadow_page_lod_);
sub.bind_ssbo("pages_infos_buf", pages_infos_data_);
sub.bind_ssbo("dst_coord_buf", dst_coord_buf_);
sub.push_constant("use_shadow_caster_atlas", use_caster_atlas_push_);
Expand Down Expand Up @@ -1680,7 +1688,7 @@ void ShadowModule::render(View &view, int2 extent)
usage_tag_fb.ensure(usage_tag_fb_resolution_);

eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_MEMORYLESS;
int2 fb_size = int2(SHADOW_TILEMAP_RES * shadow_page_size_);
int2 fb_size = int2(SHADOW_TILEMAP_RES * (1 << shadow_page_lod_));
int fb_layers = SHADOW_VIEW_MAX;

if (shadow_technique == ShadowTechnique::ATOMIC_RASTER) {
Expand Down
18 changes: 12 additions & 6 deletions source/blender/draw/engines/eevee/eevee_shadow.hh
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ struct ShadowTileMap : public ShadowTileMapData {
eCubeFace cubeface = Z_NEG;
/** Cached, used for detecting updates. */
float4x4 object_mat = float4x4::identity();
float shadow_map_scale = 1.0f;

public:
ShadowTileMap(int tiles_index_) : ShadowTileMapData{}
Expand All @@ -96,7 +95,6 @@ struct ShadowTileMap : public ShadowTileMapData {
void sync_orthographic(const float4x4 &object_mat_,
int2 origin_offset,
int clipmap_level,
float shadow_map_scale,
eShadowProjectionType projection_type_,
uint2 shadow_set_membership_ = ~uint2(0));

Expand Down Expand Up @@ -350,10 +348,8 @@ class ShadowModule {

/* Render setting that reduces the LOD for every light. */
float global_lod_bias_ = 0.0f;
/* Scale of sunlight shadow map size, also length of LOD0. */
float shadow_map_scale = 1.0f;
/** For now, needs to be hardcoded. */
int shadow_page_size_ = SHADOW_PAGE_RES;
/** Page pixel resolution LOD. Page resolution = 1 << shadow_page_lod_. */
int shadow_page_lod_ = SHADOW_PAGE_LOD;
/** Maximum number of allocated pages. Maximum value is SHADOW_MAX_PAGE. */
int shadow_page_len_ = SHADOW_MAX_PAGE;
/** Requested and effectively allocated pool size in megabytes. */
Expand Down Expand Up @@ -446,6 +442,16 @@ class ShadowModule {
return global_lod_bias_;
}

int shadow_page_lod() const
{
return shadow_page_lod_;
}

const int *shadow_page_lod_push_ref() const
{
return &shadow_page_lod_;
}

bool viewport_history_invalidated() const
{
return viewport_history_invalidated_;
Expand Down
4 changes: 2 additions & 2 deletions source/blender/draw/engines/eevee/shaders/eevee_debug.bsl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ ShadowDebugOutput debug_atlas_values([[resource_table]] const ShadowDebug &srt,
[[resource_table]] const ShadowRenderData &srd = srt.shadow_data;

ShadowCoordinates coord = srt.debug_coord_get(P, light);
float depth = srd.read_depth(coord);
float depth = srd.read_depth(coord, int(light.shadow_page_lod));
return {
.valid = true,
.color_add = float4((depth == -1) ? float3(1.0f, 0.0f, 0.0f) : float3(1.0f / depth), 0.0f) *
Expand All @@ -263,7 +263,7 @@ struct AtomicCostCtx {
[[resource_table]] const ShadowRenderData &srd = srt.shadow_data;

ShadowCoordinates coord = srt.debug_coord_get(P, light);
uint u_cost = floatBitsToUint(srd.read_depth(coord));
uint u_cost = floatBitsToUint(srd.read_depth(coord, int(light.shadow_page_lod)));
return float(u_cost - floatBitsToUint(FLT_MAX));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

namespace eevee::light {

int shadow_directional_coverage_get(int level)
float shadow_directional_coverage_get(int level)
{
return 1 << level;
return exp2(float(level));
}

struct Resources {
Expand Down Expand Up @@ -166,7 +166,7 @@ struct Resources {
int level = level_min + lod;
/* Compute full offset from world origin to the smallest clipmap tile centered around the
* camera position. The offset is computed in smallest tile unit. */
float tile_size = float(1 << level) / float(SHADOW_TILEMAP_RES);
float tile_size = exp2(float(level)) / float(SHADOW_TILEMAP_RES);
int2 level_offset = int2(round(ls_camera_position.xy / tile_size));

orthographic_sync(light.tilemap_index + lod,
Expand Down
13 changes: 6 additions & 7 deletions source/blender/draw/engines/eevee/shaders/eevee_shadow.bsl.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,19 @@ struct ShadowRenderData {
[[resource_table, condition(shadow_random)]] srt_t<Sampling> sampling;
[[resource_table, condition(shadow_random)]] srt_t<UtilityTexture> util_tx;

float read_depth(ShadowCoordinates coord) const
float read_depth(ShadowCoordinates coord, int shadow_page_lod) const
{
ShadowSamplingTile tile = shadow_tile_load(
shadow_tilemaps_tx, coord.tilemap_tile, coord.tilemap_index);
if (!tile.is_valid) {
return -1.0f;
}
/* Using bitwise ops is way faster than integer ops. */
constexpr uint page_shift = uint(SHADOW_PAGE_LOD);
constexpr uint page_mask = ~(0xFFFFFFFFu << uint(SHADOW_PAGE_LOD));
uint page_shift = uint(shadow_page_lod);
uint page_mask = ~(0xFFFFFFFFu << page_shift);

uint2 texel = coord.tilemap_texel;
/* Shift LOD0 pixels so that they get wrapped at the right position for the given LOD. */
texel += uint2(tile.lod_offset << SHADOW_PAGE_LOD);
texel += uint2(tile.lod_offset << page_shift);
/* Scale to LOD pixels (merge LOD0 pixels together) then mask to get pixel in page. */
uint2 texel_page = (texel >> tile.lod) & page_mask;
texel = (uint2(tile.page.xy) << page_shift) | texel_page;
Expand All @@ -56,7 +55,7 @@ struct ShadowRenderData {
lP = shadow_punctual_local_position_to_face_local(face_id, lP);
ShadowCoordinates coord = shadow_punctual_coordinates(light, lP, face_id);

float radial_dist = read_depth(coord);
float radial_dist = read_depth(coord, int(light.shadow_page_lod));
if (radial_dist == -1.0f) {
return 1e10f;
}
Expand All @@ -70,7 +69,7 @@ struct ShadowRenderData {
float3 lP = transform_direction_transposed(light.object_to_world, P);
ShadowCoordinates coord = shadow_directional_coordinates(light, lP);

float depth = read_depth(coord);
float depth = read_depth(coord, int(light.shadow_page_lod));
if (depth == -1.0f) {
return 1e10f;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ struct PageClear {
shadow_caster_atlas_img;

[[push_constant]] const int use_shadow_caster_atlas;
[[push_constant]] const int shadow_page_lod;
[[push_constant]] const int shadow_page_res;
};

/**
Expand All @@ -32,7 +34,7 @@ void page_clear_comp([[resource_table]] PageClear &srt,
/* We clear the destination pixels directly for the atomicMin technique. */
uint page_packed = srt.dst_coord_buf[global_id.z];
uint3 page_co = shadow_page_unpack(page_packed);
page_co.xy = page_co.xy * SHADOW_PAGE_RES + global_id.xy;
page_co.xy = page_co.xy * srt.shadow_page_res + global_id.xy;

imageStoreFast(srt.shadow_atlas_img, int3(page_co), uint4(floatBitsToUint(FLT_MAX)));
if (srt.use_shadow_caster_atlas != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ using TileMaps = eevee::shadow::TileMaps;
struct Commands {
[[storage(5, write)]] DispatchCommand &clear_dispatch_buf;
[[storage(6, write)]] DrawCommandArray &tile_draw_buf;
[[push_constant]] const int shadow_page_lod;
[[push_constant]] const int shadow_page_res;
};

[[compute, local_size(1)]]
Expand All @@ -49,8 +51,8 @@ void defrag([[resource_table]] PageAllocator &allocator,
stats.statistics_buf.view_needed_count = 0;

/* Reset clear command indirect buffer. */
cmds.clear_dispatch_buf.num_groups_x = SHADOW_PAGE_RES / SHADOW_PAGE_CLEAR_GROUP_SIZE;
cmds.clear_dispatch_buf.num_groups_y = SHADOW_PAGE_RES / SHADOW_PAGE_CLEAR_GROUP_SIZE;
cmds.clear_dispatch_buf.num_groups_x = cmds.shadow_page_res / SHADOW_PAGE_CLEAR_GROUP_SIZE;
cmds.clear_dispatch_buf.num_groups_y = cmds.shadow_page_res / SHADOW_PAGE_CLEAR_GROUP_SIZE;
cmds.clear_dispatch_buf.num_groups_z = 0;

/* Reset TBDR command indirect buffer. */
Expand Down
Loading