EEVEE Next: Volumes: Lighting integration improvements #110809
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
/* 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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue
Prefer a define. Also avoid these vector comparison. They are not portable. Use
is_equal
instead.