EEVEE Next: Volumes: Lighting integration improvements #110809

Merged
Clément Foucault merged 10 commits from pragma37/blender:pull-eevee-next-volumes-2-cleanup into main 2023-09-06 14:36:06 +02:00
15 changed files with 136 additions and 23 deletions
Showing only changes of commit 4fe196b9ff - Show all commits

View File

@ -452,6 +452,26 @@ class RENDER_PT_eevee_next_volumetric_lighting(RenderButtonsPanel, Panel):
layout.active = props.use_volumetric_lights
layout.prop(props, "volumetric_light_clamp", text="Light Clamping")
class RENDER_PT_eevee_next_volumetric_shadows(RenderButtonsPanel, Panel):
bl_label = "Volumetric Shadows"
bl_parent_id = "RENDER_PT_eevee_next_volumetric"
COMPAT_ENGINES = {'BLENDER_EEVEE_NEXT'}
def draw_header(self, context):
scene = context.scene
props = scene.eevee
self.layout.prop(props, "use_volumetric_shadows", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
scene = context.scene
props = scene.eevee
layout.active = props.use_volumetric_shadows
layout.prop(props, "volumetric_shadow_samples", text="Samples")
class RENDER_PT_eevee_subsurface_scattering(RenderButtonsPanel, Panel):
bl_label = "Subsurface Scattering"
@ -1201,6 +1221,7 @@ classes = (
RENDER_PT_eevee_volumetric_shadows,
RENDER_PT_eevee_next_volumetric,
RENDER_PT_eevee_next_volumetric_lighting,
RENDER_PT_eevee_next_volumetric_shadows,
RENDER_PT_eevee_performance,
RENDER_PT_eevee_hair,
RENDER_PT_eevee_shadows,

View File

@ -558,6 +558,7 @@ set(GLSL_SRC
engines/eevee_next/shaders/eevee_shadow_tag_usage_lib.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_surfels_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_vert.glsl
engines/eevee_next/shaders/eevee_shadow_tag_usage_volume_comp.glsl
engines/eevee_next/shaders/eevee_shadow_test.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_bounds_comp.glsl
engines/eevee_next/shaders/eevee_shadow_tilemap_finalize_comp.glsl

View File

@ -216,6 +216,8 @@ const char *ShaderModule::static_shader_create_info_name_get(eShaderType shader_
return "eevee_shadow_tag_usage_surfels";
case SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT:
return "eevee_shadow_tag_usage_transparent";
case SHADOW_TILEMAP_TAG_USAGE_VOLUME:
return "eevee_shadow_tag_usage_volume";
case SUBSURFACE_EVAL:
return "eevee_subsurface_eval";
case SURFEL_CLUSTER_BUILD:

View File

@ -106,6 +106,7 @@ enum eShaderType {
SHADOW_TILEMAP_TAG_USAGE_OPAQUE,
SHADOW_TILEMAP_TAG_USAGE_SURFELS,
SHADOW_TILEMAP_TAG_USAGE_TRANSPARENT,
SHADOW_TILEMAP_TAG_USAGE_VOLUME,
SUBSURFACE_EVAL,

View File

@ -457,6 +457,8 @@ struct VolumesInfoData {
packed_int3 tex_size;
float light_clamp;
packed_float3 inv_tex_size;
int tile_size;
int tile_size_lod;
float shadow_steps;
bool1 use_lights;
bool1 use_soft_shadows;
@ -464,8 +466,6 @@ struct VolumesInfoData {
float depth_far;
float depth_distribution;
float _pad0;
float _pad1;
float _pad2;
};
BLI_STATIC_ASSERT_ALIGN(VolumesInfoData, 16)

View File

@ -945,7 +945,21 @@ void ShadowModule::end_sync()
}
}
/* Usage tagging happens between these two steps. */
/* Non volume usage tagging happens between these two steps.
* (Setup at begin_sync) */
if (inst_.volume.is_enabled()) {
PassMain::Sub &sub = tilemap_usage_ps_.sub("World Volume");
sub.shader_set(inst_.shaders.static_shader_get(SHADOW_TILEMAP_TAG_USAGE_VOLUME));
sub.bind_ssbo("tilemaps_buf", &tilemap_pool.tilemaps_data);
sub.bind_ssbo("tiles_buf", &tilemap_pool.tiles_data);
sub.push_constant("tilemap_projection_ratio", &tilemap_projection_ratio_);
inst_.hiz_buffer.bind_resources(&sub);
inst_.sampling.bind_resources(&sub);
inst_.lights.bind_resources(&sub);
inst_.volume.bind_resources(sub);
sub.dispatch(math::divide_ceil(inst_.volume.grid_size(), int3(VOLUME_GROUP_SIZE)));
}
{
PassSimple &pass = tilemap_update_ps_;

View File

@ -123,8 +123,6 @@ void ShadingView::render()
/* TODO(fclem): Move it after the first prepass (and hiz update) once pipeline is stabilized. */
inst_.lights.set_view(render_view_new_, extent_);
inst_.volume.draw_compute(render_view_new_);
/* TODO: cleanup. */
View main_view_new("MainView", main_view_);
/* TODO(Miguel Pozo): Deferred and forward prepass should happen before the GBuffer pass. */
@ -136,6 +134,8 @@ void ShadingView::render()
rt_buffer_opaque_,
rt_buffer_refract_);
inst_.volume.draw_compute(render_view_new_);
// inst_.lookdev.render_overlay(view_fb_);
inst_.pipelines.forward.render(render_view_new_, prepass_fb_, combined_fb_, rbufs.combined_tx);

View File

@ -84,6 +84,9 @@ void VolumeModule::init()
const float2 viewport_size = float2(inst_.film.render_extent_get());
const int tile_size = scene_eval->eevee.volumetric_tile_size;
data_.tile_size = tile_size;
data_.tile_size_lod = int(log2(tile_size));
/* Find Froxel Texture resolution. */
int3 tex_size = int3(math::ceil(math::max(float2(1.0f), viewport_size / float(tile_size))), 0);
tex_size.z = std::max(1, scene_eval->eevee.volumetric_samples);

View File

@ -116,6 +116,11 @@ class VolumeModule {
ps.bind_image(VOLUME_PROP_PHASE_IMG_SLOT, &prop_phase_tx_);
}
bool is_enabled()
{
return enabled_;
}
int3 grid_size()
{
return data_.tex_size;

View File

@ -82,6 +82,10 @@ mat4x4 shadow_load_normal_matrix(LightData light)
* match the surface. */
float shadow_slope_bias_get(vec2 atlas_size, LightData light, vec3 lNg, vec3 lP, vec2 uv, uint lod)
{
if (lNg == vec3(0)) {
pragma37 marked this conversation as resolved Outdated

Prefer a define. Also avoid these vector comparison. They are not portable. Use is_equal instead.

Prefer a define. Also avoid these vector comparison. They are not portable. Use `is_equal` instead.
/* No bias. Used for volumes. */
return 0.0;
}
/* Compute coordinate inside the pixel we are sampling. */
vec2 uv_subpixel_coord = fract(uv * atlas_size);
/* Bias uv sample for LODs since custom raster aligns LOD pixels instead of centering them. */

View File

@ -118,6 +118,6 @@ void main()
vec3 vP = point_world_to_view(P);
shadow_tag_usage(
vP, P, ws_view_direction, step_radius, t, gl_FragCoord.xy * exp2(float(fb_lod)));
vP, P, ws_view_direction, step_radius, t, gl_FragCoord.xy * exp2(float(fb_lod)), 0);
}
}

View File

@ -40,7 +40,7 @@ void shadow_tag_usage_tilemap_directional_at_level(uint l_idx, vec3 P, int level
shadow_tag_usage_tile(light, coord.tile_coord, 0, coord.tilemap_index);
}
void shadow_tag_usage_tilemap_directional(uint l_idx, vec3 P, vec3 V, float radius)
void shadow_tag_usage_tilemap_directional(uint l_idx, vec3 P, vec3 V, float radius, int lod_bias)
{
LightData light = light_buf[l_idx];
@ -50,8 +50,10 @@ void shadow_tag_usage_tilemap_directional(uint l_idx, vec3 P, vec3 V, float radi
vec3 lP = shadow_world_to_local(light, P);
/* TODO(Miguel Pozo): Implement lod_bias support. */
if (radius == 0.0) {
ShadowCoordinates coord = shadow_directional_coordinates(light, lP);
int level = shadow_directional_level(light, lP - light._position);
ShadowCoordinates coord = shadow_directional_coordinates_at_level(light, lP, level);
shadow_tag_usage_tile(light, coord.tile_coord, 0, coord.tilemap_index);
}
else {
@ -75,7 +77,8 @@ void shadow_tag_usage_tilemap_directional(uint l_idx, vec3 P, vec3 V, float radi
}
}
void shadow_tag_usage_tilemap_punctual(uint l_idx, vec3 P, float dist_to_cam, float radius)
void shadow_tag_usage_tilemap_punctual(
uint l_idx, vec3 P, float dist_to_cam, float radius, int lod_bias)
{
LightData light = light_buf[l_idx];
@ -123,6 +126,7 @@ void shadow_tag_usage_tilemap_punctual(uint l_idx, vec3 P, float dist_to_cam, fl
ShadowCoordinates coord = shadow_punctual_coordinates(light, lP, face_id);
int lod = int(ceil(-log2(footprint_ratio) + tilemaps_buf[coord.tilemap_index].lod_bias));
lod += lod_bias;
lod = clamp(lod, 0, SHADOW_TILEMAP_LOD);
shadow_tag_usage_tile(light, coord.tile_coord, lod, coord.tilemap_index);
@ -145,6 +149,7 @@ void shadow_tag_usage_tilemap_punctual(uint l_idx, vec3 P, float dist_to_cam, fl
int tilemap_index = light.tilemap_index + face_id;
int lod = int(ceil(-log2(footprint_ratio) + tilemaps_buf[tilemap_index].lod_bias));
lod += lod_bias;
lod = clamp(lod, 0, SHADOW_TILEMAP_LOD);
vec3 _lP = shadow_punctual_local_position_to_face_local(face_id, lP);
@ -167,15 +172,16 @@ void shadow_tag_usage_tilemap_punctual(uint l_idx, vec3 P, float dist_to_cam, fl
* Used for downsampled/ray-marched tagging, so all the shadowmap texels covered get correctly
* tagged.
*/
void shadow_tag_usage(vec3 vP, vec3 P, vec3 V, float radius, float dist_to_cam, vec2 pixel)
void shadow_tag_usage(
vec3 vP, vec3 P, vec3 V, float radius, float dist_to_cam, vec2 pixel, int lod_bias)
{
LIGHT_FOREACH_BEGIN_DIRECTIONAL (light_cull_buf, l_idx) {
shadow_tag_usage_tilemap_directional(l_idx, P, V, radius);
shadow_tag_usage_tilemap_directional(l_idx, P, V, radius, lod_bias);
}
LIGHT_FOREACH_END
LIGHT_FOREACH_BEGIN_LOCAL (light_cull_buf, light_zbin_buf, light_tile_buf, pixel, vP.z, l_idx) {
shadow_tag_usage_tilemap_punctual(l_idx, P, dist_to_cam, radius);
shadow_tag_usage_tilemap_punctual(l_idx, P, dist_to_cam, radius, lod_bias);
}
LIGHT_FOREACH_END
}
@ -184,7 +190,7 @@ void shadow_tag_usage(vec3 vP, vec3 P, vec2 pixel)
{
float dist_to_cam = length(vP);
shadow_tag_usage(vP, P, vec3(0), 0, dist_to_cam, pixel);
shadow_tag_usage(vP, P, vec3(0), 0, dist_to_cam, pixel, 0);
}
void shadow_tag_usage_surfel(Surfel surfel, int directional_lvl)
@ -200,7 +206,7 @@ void shadow_tag_usage_surfel(Surfel surfel, int directional_lvl)
{
/* Set distance to camera to 1 to avoid changing footprint_ratio. */
float dist_to_cam = 1.0;
shadow_tag_usage_tilemap_punctual(l_idx, P, dist_to_cam, 0);
shadow_tag_usage_tilemap_punctual(l_idx, P, dist_to_cam, 0, 0);
}
LIGHT_FOREACH_END
}

View File

@ -0,0 +1,36 @@
/**
* Virtual shadowmapping: Usage tagging
*
* Shadow pages are only allocated if they are visible.
* This pass scans all volume froxels and tags tiles needed for shadowing.
*/
#pragma BLENDER_REQUIRE(eevee_volume_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_shadow_tag_usage_lib.glsl)
void main()
{
ivec3 froxel = ivec3(gl_GlobalInvocationID);
if (any(greaterThanEqual(froxel, volumes_info_buf.tex_size))) {
return;
}
vec3 jitter = sampling_rng_3D_get(SAMPLING_VOLUME_U);
vec3 volume_ndc = volume_to_ndc((vec3(froxel) + jitter) * volumes_info_buf.inv_tex_size);
vec3 vP = get_view_space_from_depth(volume_ndc.xy, volume_ndc.z);
vec3 P = point_view_to_world(vP);
float depth = texelFetch(hiz_tx, froxel.xy, volumes_info_buf.tile_size_lod).r;
if (depth < volume_ndc.z) {
return;
}
vec2 pixel = (vec2(froxel.xy) + vec2(0.5)) / vec2(volumes_info_buf.tex_size.xy) /
volumes_info_buf.viewport_size_inv;
int bias = volumes_info_buf.tile_size_lod;
shadow_tag_usage(vP, P, cameraVec(P), 0.01, length(vP), pixel, bias);
}

View File

@ -26,19 +26,24 @@ vec3 volume_scatter_light_eval(vec3 P, vec3 V, uint l_idx, float s_anisotropy)
float l_dist;
light_shape_vector_get(ld, P, L, l_dist);
# if 0
/* TODO(Miguel Pozo): Shadows */
float vis = light_visibility(ld, P, l_vector);
# else
float vis = light_attenuation(ld, L, l_dist);
# endif
float visibility = light_attenuation(ld, L, l_dist);
LightData light = light_buf[l_idx];
if (light.tilemap_index != LIGHT_NO_SHADOW && (visibility > 0.0)) {
vec3 lL = light_world_to_local(light, -L) * l_dist;
/* Disable shadow bias. */
vec3 lNg = vec3(0);
if (vis < 1e-4) {
ShadowSample samp = shadow_sample(
light.type <= LIGHT_SUN_ORTHO, shadow_atlas_tx, shadow_tilemaps_tx, light, lL, lNg, P);
visibility *= float(samp.occluder_delta + samp.bias >= 0.0);
}
if (visibility < 1e-4) {
return vec3(0);
}
vec3 Li = volume_light(ld, L, l_dist) * volume_shadow(ld, P, L, l_dist);
return Li * vis * volume_phase_function(-V, L, s_anisotropy);
vec3 Li = volume_light(ld, L, l_dist) * volume_shadow(ld, P, L, l_dist, extinction_tx);
return Li * visibility * volume_phase_function(-V, L, s_anisotropy);
}
#endif

View File

@ -109,6 +109,21 @@ GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_transparent)
.vertex_source("eevee_shadow_tag_usage_vert.glsl")
.fragment_source("eevee_shadow_tag_usage_frag.glsl");
GPU_SHADER_CREATE_INFO(eevee_shadow_tag_usage_volume)
.do_static_compilation(true)
.local_group_size(VOLUME_GROUP_SIZE, VOLUME_GROUP_SIZE, VOLUME_GROUP_SIZE)
.storage_buf(4, Qualifier::READ_WRITE, "ShadowTileMapData", "tilemaps_buf[]")
.storage_buf(5, Qualifier::READ_WRITE, SHADOW_TILE_DATA_PACKED, "tiles_buf[]")
.uniform_buf(VOLUMES_INFO_BUF_SLOT, "VolumesInfoData", "volumes_info_buf")
.push_constant(Type::FLOAT, "tilemap_projection_ratio")
.additional_info("eevee_shared",
"draw_view",
"draw_view_culling",
"eevee_hiz_data",
"eevee_light_data",
"eevee_sampling_data")
.compute_source("eevee_shadow_tag_usage_volume_comp.glsl");
GPU_SHADER_CREATE_INFO(eevee_shadow_page_mask)
.do_static_compilation(true)
.local_group_size(SHADOW_TILEMAP_RES, SHADOW_TILEMAP_RES)