EEVEE-Next: Split clipmap_base_offset into two int2
This avoid uneeded complexity since we have a lot of space inside the sunlight struct.
This commit is contained in:
parent
b59059a518
commit
28c53cccd3
|
@ -793,12 +793,12 @@ static inline bool is_local_light(eLightType type)
|
||||||
/** --- Shadow Data --- */ \
|
/** --- Shadow Data --- */ \
|
||||||
/** Other parts of the perspective matrix. Assumes symmetric frustum. */ \
|
/** Other parts of the perspective matrix. Assumes symmetric frustum. */ \
|
||||||
float clip_side; \
|
float clip_side; \
|
||||||
|
/** Number of allocated tilemap for this local light. */ \
|
||||||
|
int tilemaps_count; \
|
||||||
/** Scaling factor to the light shape for shadow ray casting. */ \
|
/** Scaling factor to the light shape for shadow ray casting. */ \
|
||||||
float shadow_scale; \
|
float shadow_scale; \
|
||||||
/** Shift to apply to the light origin to get the shadow projection origin. */ \
|
/** Shift to apply to the light origin to get the shadow projection origin. */ \
|
||||||
float shadow_projection_shift; \
|
float shadow_projection_shift;
|
||||||
/** Number of allocated tilemap for this local light. */ \
|
|
||||||
int tilemaps_count;
|
|
||||||
|
|
||||||
/* Untyped local light data. Gets reinterpreted to LightSpotData and LightAreaData.
|
/* Untyped local light data. Gets reinterpreted to LightSpotData and LightAreaData.
|
||||||
* Allow access to local light common data without casting. */
|
* Allow access to local light common data without casting. */
|
||||||
|
@ -861,12 +861,11 @@ struct LightSunData {
|
||||||
|
|
||||||
float _pad3;
|
float _pad3;
|
||||||
float _pad4;
|
float _pad4;
|
||||||
float _pad5;
|
|
||||||
float _pad6;
|
|
||||||
|
|
||||||
/** --- Shadow Data --- */
|
/** --- Shadow Data --- */
|
||||||
/** Offset of the LOD min in LOD min tile units. */
|
/** Offset of the LOD min in LOD min tile units. Split positive and negative for bit-shift. */
|
||||||
int2 clipmap_base_offset;
|
int2 clipmap_base_offset_neg;
|
||||||
|
|
||||||
|
int2 clipmap_base_offset_pos;
|
||||||
/** Angle covered by the light shape for shadow ray casting. */
|
/** Angle covered by the light shape for shadow ray casting. */
|
||||||
float shadow_angle;
|
float shadow_angle;
|
||||||
/** Trace distance around the shading point. */
|
/** Trace distance around the shading point. */
|
||||||
|
@ -1073,7 +1072,8 @@ static inline LightSunData light_sun_data_get(LightData light)
|
||||||
{
|
{
|
||||||
SAFE_BEGIN(LightSunData, is_sun_light(light.type))
|
SAFE_BEGIN(LightSunData, is_sun_light(light.type))
|
||||||
SAFE_ASSIGN_FLOAT(radius, radius_squared)
|
SAFE_ASSIGN_FLOAT(radius, radius_squared)
|
||||||
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset, _pad0_reserved, _pad1_reserved)
|
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset_neg, shadow_scale, shadow_projection_shift)
|
||||||
|
SAFE_ASSIGN_FLOAT_AS_INT2_COMBINE(clipmap_base_offset_pos, _pad0_reserved, _pad1_reserved)
|
||||||
SAFE_ASSIGN_FLOAT(shadow_angle, _pad1)
|
SAFE_ASSIGN_FLOAT(shadow_angle, _pad1)
|
||||||
SAFE_ASSIGN_FLOAT(shadow_trace_distance, _pad2)
|
SAFE_ASSIGN_FLOAT(shadow_trace_distance, _pad2)
|
||||||
SAFE_ASSIGN_FLOAT2(clipmap_origin, _pad3)
|
SAFE_ASSIGN_FLOAT2(clipmap_origin, _pad3)
|
||||||
|
|
|
@ -490,12 +490,13 @@ 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 tile-maps. */
|
/* Offset in tiles from the scene 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 and the last tile-maps. */
|
/* Offset in tiles between the first and 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.sun.clipmap_base_offset = (offset_vector * (1 << 16)) / max_ii(levels_range.size() - 1, 1);
|
light.sun.clipmap_base_offset_pos = (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 tile-maps. */
|
/* \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();
|
||||||
|
@ -504,7 +505,7 @@ void ShadowDirectional::cascade_tilemaps_distribution(Light &light, const Camera
|
||||||
|
|
||||||
/* Equal spacing between cascades layers since we want uniform shadow density. */
|
/* Equal spacing between cascades layers since we want uniform shadow density. */
|
||||||
int2 level_offset = origin_offset +
|
int2 level_offset = origin_offset +
|
||||||
shadow_cascade_grid_offset(light.sun.clipmap_base_offset, i);
|
shadow_cascade_grid_offset(light.sun.clipmap_base_offset_pos, i);
|
||||||
tilemap->sync_orthographic(object_mat_, level_offset, level, 0.0f, SHADOW_PROJECTION_CASCADE);
|
tilemap->sync_orthographic(object_mat_, level_offset, level, 0.0f, SHADOW_PROJECTION_CASCADE);
|
||||||
|
|
||||||
/* Add shadow tile-maps grouped by lights to the GPU buffer. */
|
/* Add shadow tile-maps grouped by lights to the GPU buffer. */
|
||||||
|
@ -535,8 +536,8 @@ IndexRange ShadowDirectional::clipmap_level_range(const Camera &camera)
|
||||||
{
|
{
|
||||||
using namespace blender::math;
|
using namespace blender::math;
|
||||||
|
|
||||||
/* Take 16 to be able to pack offset into a single int2. */
|
/* 32 to be able to pack offset into two single int2. */
|
||||||
const int max_tilemap_per_shadows = 16;
|
const int max_tilemap_per_shadows = 32;
|
||||||
|
|
||||||
int user_min_level = floorf(log2(min_resolution_));
|
int user_min_level = floorf(log2(min_resolution_));
|
||||||
/* Covers the farthest points of the view. */
|
/* Covers the farthest points of the view. */
|
||||||
|
@ -586,8 +587,7 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light,
|
||||||
* 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 tile-map 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). */
|
|
||||||
int2 lvl_offset_next = tilemaps_[lod + 1]->grid_offset;
|
int2 lvl_offset_next = tilemaps_[lod + 1]->grid_offset;
|
||||||
int2 lvl_offset = tilemaps_[lod]->grid_offset;
|
int2 lvl_offset = tilemaps_[lod]->grid_offset;
|
||||||
int2 lvl_delta = lvl_offset - (lvl_offset_next << 1);
|
int2 lvl_delta = lvl_offset - (lvl_offset_next << 1);
|
||||||
|
@ -596,9 +596,9 @@ void ShadowDirectional::clipmap_tilemaps_distribution(Light &light,
|
||||||
neg_offset |= math::max(-lvl_delta, int2(0)) << lod;
|
neg_offset |= math::max(-lvl_delta, int2(0)) << lod;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compressing to a single value to save up storage in light data. Number of levels is limited to
|
/* Number of levels is limited to 32 by `clipmap_level_range()` for this reason. */
|
||||||
* 16 by `clipmap_level_range()` for this reason. */
|
light.sun.clipmap_base_offset_pos = pos_offset;
|
||||||
light.sun.clipmap_base_offset = pos_offset | (neg_offset << 16);
|
light.sun.clipmap_base_offset_neg = neg_offset;
|
||||||
|
|
||||||
float tile_size_max = ShadowDirectional::tile_size_get(levels_range.last());
|
float tile_size_max = ShadowDirectional::tile_size_get(levels_range.last());
|
||||||
int2 level_offset_max = tilemaps_[levels_range.size() - 1]->grid_offset;
|
int2 level_offset_max = tilemaps_[levels_range.size() - 1]->grid_offset;
|
||||||
|
|
|
@ -210,7 +210,10 @@ ShadowDirectionalSampleInfo shadow_directional_sample_info_get(LightData light,
|
||||||
level;
|
level;
|
||||||
|
|
||||||
info.clipmap_offset = shadow_decompress_grid_offset(
|
info.clipmap_offset = shadow_decompress_grid_offset(
|
||||||
light.type, light_sun_data_get(light).clipmap_base_offset, info.level_relative);
|
light.type,
|
||||||
|
light_sun_data_get(light).clipmap_base_offset_neg,
|
||||||
|
light_sun_data_get(light).clipmap_base_offset_pos,
|
||||||
|
info.level_relative);
|
||||||
info.clipmap_origin = light_sun_data_get(light).clipmap_origin;
|
info.clipmap_origin = light_sun_data_get(light).clipmap_origin;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
|
|
|
@ -30,6 +30,8 @@ void set_clipmap_data(inout LightData light,
|
||||||
void set_clipmap_base_offset(inout LightData light, ivec2 clipmap_base_offset)
|
void set_clipmap_base_offset(inout LightData light, ivec2 clipmap_base_offset)
|
||||||
{
|
{
|
||||||
/* WATCH: Can get out of sync with light_sun_data_get(). */
|
/* WATCH: Can get out of sync with light_sun_data_get(). */
|
||||||
|
light.do_not_access_directly.shadow_scale = intBitsToFloat(0);
|
||||||
|
light.do_not_access_directly.shadow_projection_shift = intBitsToFloat(0);
|
||||||
light.do_not_access_directly._pad0_reserved = intBitsToFloat(clipmap_base_offset.x);
|
light.do_not_access_directly._pad0_reserved = intBitsToFloat(clipmap_base_offset.x);
|
||||||
light.do_not_access_directly._pad1_reserved = intBitsToFloat(clipmap_base_offset.y);
|
light.do_not_access_directly._pad1_reserved = intBitsToFloat(clipmap_base_offset.y);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +49,7 @@ void main()
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_min, 1);
|
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_min, 1);
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_max, 2);
|
EXPECT_EQ(light_sun_data_get(light).clipmap_lod_max, 2);
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_origin, vec2(3.0, 4.0));
|
EXPECT_EQ(light_sun_data_get(light).clipmap_origin, vec2(3.0, 4.0));
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(5, 6));
|
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(5, 6));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(eevee_shadow, DirectionalClipmapLevel)
|
TEST(eevee_shadow, DirectionalClipmapLevel)
|
||||||
|
@ -119,7 +121,7 @@ void main()
|
||||||
camera_lP = vec3(0.0, 0.0, 0.0);
|
camera_lP = vec3(0.0, 0.0, 0.0);
|
||||||
/* Follows ShadowDirectional::end_sync(). */
|
/* Follows ShadowDirectional::end_sync(). */
|
||||||
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(0));
|
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(0));
|
||||||
|
|
||||||
/* Test UVs and tile mapping. */
|
/* Test UVs and tile mapping. */
|
||||||
|
|
||||||
|
@ -152,7 +154,7 @@ void main()
|
||||||
camera_lP = vec3(2.0, 2.0, 0.0);
|
camera_lP = vec3(2.0, 2.0, 0.0);
|
||||||
/* Follows ShadowDirectional::end_sync(). */
|
/* Follows ShadowDirectional::end_sync(). */
|
||||||
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
||||||
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(32));
|
EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(32));
|
||||||
|
|
||||||
lP = vec3(2.00001, 2.00001, 0.0);
|
lP = vec3(2.00001, 2.00001, 0.0);
|
||||||
coords = shadow_directional_coordinates(light, lP);
|
coords = shadow_directional_coordinates(light, lP);
|
||||||
|
@ -278,7 +280,7 @@ void main()
|
||||||
// camera_lP = vec3(2.0, 2.0, 0.0);
|
// camera_lP = vec3(2.0, 2.0, 0.0);
|
||||||
/* Follows ShadowDirectional::end_sync(). */
|
/* Follows ShadowDirectional::end_sync(). */
|
||||||
// set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
// set_clipmap_base_offset(light, ivec2(round(camera_lP.xy / lod_min_tile_size)));
|
||||||
// EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset, ivec2(32));
|
// EXPECT_EQ(light_sun_data_get(light).clipmap_base_offset_pos, ivec2(32));
|
||||||
|
|
||||||
// lP = vec3(2.00001, 2.00001, 0.0);
|
// lP = vec3(2.00001, 2.00001, 0.0);
|
||||||
// coords = shadow_directional_coordinates(light, lP);
|
// coords = shadow_directional_coordinates(light, lP);
|
||||||
|
|
|
@ -176,13 +176,16 @@ struct ShadowCoordinates {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Retain sign bit and avoid costly int division. */
|
/* Retain sign bit and avoid costly int division. */
|
||||||
ivec2 shadow_decompress_grid_offset(eLightType light_type, ivec2 offset, int level_relative)
|
ivec2 shadow_decompress_grid_offset(eLightType light_type,
|
||||||
|
ivec2 offset_neg,
|
||||||
|
ivec2 offset_pos,
|
||||||
|
int level_relative)
|
||||||
{
|
{
|
||||||
if (light_type == LIGHT_SUN_ORTHO) {
|
if (light_type == LIGHT_SUN_ORTHO) {
|
||||||
return shadow_cascade_grid_offset(offset, level_relative);
|
return shadow_cascade_grid_offset(offset_pos, level_relative);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return ((offset & 0xFFFF) >> level_relative) - ((offset >> 16) >> level_relative);
|
return (offset_pos >> level_relative) - (offset_neg >> level_relative);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +206,10 @@ ShadowCoordinates shadow_directional_coordinates_at_level(LightData light, vec3
|
||||||
|
|
||||||
/* Compute offset in tile. */
|
/* Compute offset in tile. */
|
||||||
ivec2 clipmap_offset = shadow_decompress_grid_offset(
|
ivec2 clipmap_offset = shadow_decompress_grid_offset(
|
||||||
light.type, light_sun_data_get(light).clipmap_base_offset, level_relative);
|
light.type,
|
||||||
|
light_sun_data_get(light).clipmap_base_offset_neg,
|
||||||
|
light_sun_data_get(light).clipmap_base_offset_pos,
|
||||||
|
level_relative);
|
||||||
|
|
||||||
ret.uv = lP.xy - light_sun_data_get(light).clipmap_origin;
|
ret.uv = lP.xy - light_sun_data_get(light).clipmap_origin;
|
||||||
ret.uv /= exp2(float(ret.lod_relative));
|
ret.uv /= exp2(float(ret.lod_relative));
|
||||||
|
|
|
@ -252,7 +252,10 @@ ShadowTracingSample shadow_map_trace_sample(ShadowMapTracingState state,
|
||||||
|
|
||||||
/* Compute offset in tile. */
|
/* Compute offset in tile. */
|
||||||
ivec2 clipmap_offset = shadow_decompress_grid_offset(
|
ivec2 clipmap_offset = shadow_decompress_grid_offset(
|
||||||
ray.light.type, light_sun_data_get(ray.light).clipmap_base_offset, level_relative);
|
ray.light.type,
|
||||||
|
light_sun_data_get(ray.light).clipmap_base_offset_neg,
|
||||||
|
light_sun_data_get(ray.light).clipmap_base_offset_pos,
|
||||||
|
level_relative);
|
||||||
/* Translate tilemap UVs to its origin. */
|
/* Translate tilemap UVs to its origin. */
|
||||||
tilemap_uv -= vec2(clipmap_offset) / float(SHADOW_TILEMAP_RES);
|
tilemap_uv -= vec2(clipmap_offset) / float(SHADOW_TILEMAP_RES);
|
||||||
/* Clamp to avoid out of tilemap access. */
|
/* Clamp to avoid out of tilemap access. */
|
||||||
|
|
Loading…
Reference in New Issue