EEVEE-Next: Add horizon scan to raytracing module #114259

Merged
Clément Foucault merged 51 commits from fclem/blender:eevee-next-horizon-gi into main 2023-11-21 16:24:23 +01:00
7 changed files with 75 additions and 43 deletions
Showing only changes of commit 8b18deae7e - Show all commits

View File

@ -207,7 +207,8 @@ void RayTraceModule::sync()
PassSimple &pass = PASS_VARIATION(horizon_scan_, type, _ps_);
pass.init();
pass.shader_set(inst_.shaders.static_shader_get(SHADER_VARIATION(HORIZON_SCAN_, type)));
pass.bind_image("out_radiance_img", &horizon_scan_output_tx_);
pass.bind_image("radiance_img", &horizon_scan_output_tx_);
pass.bind_image("tile_mask_img", &tile_mask_tx_);
pass.bind_ssbo("tiles_coord_buf", &horizon_tiles_buf_);
pass.bind_texture("screen_radiance_tx", &screen_radiance_tx_);
pass.bind_texture(RBUFS_UTILITY_TEX_SLOT, inst_.pipelines.utility_tx);
@ -326,7 +327,11 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
data_.thickness = options.screen_trace_thickness;
data_.quality = 1.0f - 0.95f * options.screen_trace_quality;
data_.brightness_clamp = (options.sample_clamp > 0.0) ? options.sample_clamp : 1e20;
data_.max_trace_roughness = 1.0f;
float roughness_mask_start = 0.2f; /* TODO option. */
float roughness_mask_fade = 0.2f;
data_.roughness_mask_scale = 1.0 / roughness_mask_fade;
data_.roughness_mask_bias = data_.roughness_mask_scale * roughness_mask_start;
data_.resolution_scale = resolution_scale;
data_.closure_active = raytrace_closure;
@ -433,7 +438,6 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
denoise_buf->denoised_temporal_tx.release();
}
tile_mask_tx_.release();
denoise_variance_tx_.release();
if (use_horizon_scan) {
@ -441,6 +445,8 @@ RayTraceResult RayTraceModule::trace(RayTraceBuffer &rt_buffer,
inst_.manager->submit(*horizon_scan_ps, render_view);
}
tile_mask_tx_.release();
DRW_stats_group_end();
return result;

View File

@ -1200,14 +1200,14 @@ struct RayTraceData {
/** Maximum brightness during lighting evaluation. */
float brightness_clamp;
/** Maximum roughness for which we will trace a ray. */
float max_trace_roughness;
float roughness_mask_scale;
float roughness_mask_bias;
/** If set to true will bypass spatial denoising. */
bool1 skip_denoise;
/** Closure being ray-traced. */
eClosureBits closure_active;
int _pad0;
int _pad1;
int _pad2;
};
BLI_STATIC_ASSERT_ALIGN(RayTraceData, 16)

View File

@ -26,7 +26,7 @@ void main()
if (depth == 1.0) {
/* Do not trace for background */
imageStore(out_radiance_img, texel, vec4(0.0));
imageStore(radiance_img, texel, vec4(0.0));
return;
}
@ -79,22 +79,24 @@ void main()
uniform_buf.ao.angle_bias,
8);
/* TODO(fclem): Do not load non traced tiles. */
vec4 radiance_raytrace = imageLoad(out_radiance_img, texel);
float mix_fac = saturate(roughness * uniform_buf.raytrace.roughness_mask_scale -
uniform_buf.raytrace.roughness_mask_bias);
vec4 radiance_raytrace = tile_use_ray_tracing ? imageLoad(radiance_img, texel) : vec4(0.0);
vec4 radiance_horizon = vec4(1.0, 0.0, 1.0, 1.0);
#ifdef HORIZON_DIFFUSE
radiance_horizon = vec4(ctx.diffuse_result, 1.0);
float mix_fac = 1.0;
float roughness = 1.0;
#endif
#ifdef HORIZON_REFLECT
radiance_horizon = vec4(ctx.reflection_result, 1.0);
float mix_fac = saturate(ctx.reflection.roughness * 8.0 - 2.0);
float roughness = ctx.reflection.roughness;
#endif
#ifdef HORIZON_REFRACT
radiance_horizon = vec4(ctx.refraction_result, 1.0);
float mix_fac = saturate(ctx.refraction.roughness * 8.0 - 2.0);
float roughness = 1.0; /* TODO(fclem): Apparent roughness. */
#endif
vec4 radiance = mix(radiance_raytrace, radiance_horizon, mix_fac);
imageStore(out_radiance_img, texel, radiance);
imageStore(radiance_img, texel, radiance);
}

View File

@ -159,17 +159,17 @@ void horizon_scan_context_sample_finish(
horizon_scan_context_sample_finish(context.occlusion_common, vec3(0.0), theta, bias);
#endif
#ifdef HORIZON_DIFFUSE
sample_radiance *= bxdf_eval(context.diffuse, L, V) * M_PI;
sample_radiance *= bxdf_eval(context.diffuse, L, V);
horizon_scan_context_sample_finish(context.diffuse_common, sample_radiance, theta, bias);
#endif
#ifdef HORIZON_REFLECT
/* TODO(fclem): Loosing energy here. */
sample_radiance *= bxdf_eval(context.reflection, L, V) * M_PI;
sample_radiance *= bxdf_eval(context.reflection, L, V);
horizon_scan_context_sample_finish(context.reflection_common, sample_radiance, theta, bias);
#endif
#ifdef HORIZON_REFRACT
/* TODO(fclem): Broken: Black. */
sample_radiance *= bxdf_eval(context.refraction, L, V) * M_PI;
sample_radiance *= bxdf_eval(context.refraction, L, V);
horizon_scan_context_sample_finish(context.refraction_common, sample_radiance, theta, bias);
#endif
}

View File

@ -12,13 +12,13 @@
#pragma BLENDER_REQUIRE(gpu_shader_codegen_lib.glsl)
#pragma BLENDER_REQUIRE(eevee_gbuffer_lib.glsl)
shared uint tile_contains_glossy_rays;
shared uint tile_contains_ray_tracing;
shared uint tile_contains_horizon_scan;
/* Returns a blend factor between different irradiance fetching method for reflections. */
float ray_glossy_factor(float roughness)
/* Returns a blend factor between different tracing method. */
float ray_glossy_factor(RayTraceData raytrace, float roughness)
{
/* TODO */
return 1.0;
return saturate(roughness * raytrace.roughness_mask_scale - raytrace.roughness_mask_bias);
fclem marked this conversation as resolved
Review

It took me some effort to realize this is just a map_range.
Wouldn't make more sense to just do:
saturate(mask_scale * (roughness - mask_start)) ?

Note that I was looking at this because raytracing is not working for materials with high roughness, but the issue must be elsewhere.

It took me some effort to realize this is just a map_range. Wouldn't make more sense to just do: `saturate(mask_scale * (roughness - mask_start))` ? Note that I was looking at this because raytracing is not working for materials with high roughness, but the issue must be elsewhere.

This is made so that it is optimized as single MADD instruction. But I agree should have a map range structure/type + function that improves the semantic.

This is made so that it is optimized as single MADD instruction. But I agree should have a map range structure/type + function that improves the semantic.
}
void main()
@ -38,7 +38,8 @@ void main()
ray_dispatch_buf.num_groups_z = 1u;
/* Init shared variables. */
tile_contains_glossy_rays = 0;
tile_contains_ray_tracing = 0;
tile_contains_horizon_scan = 0;
}
barrier();
@ -51,13 +52,20 @@ void main()
if (flag_test(closure_bits, uniform_buf.raytrace.closure_active)) {
GBufferData gbuf = gbuffer_read(gbuf_header_tx, gbuf_closure_tx, gbuf_color_tx, texel);
float roughness = (uniform_buf.raytrace.closure_active == CLOSURE_REFRACTION) ?
gbuf.refraction.roughness :
gbuf.reflection.roughness;
float roughness = (uniform_buf.raytrace.closure_active == CLOSURE_DIFFUSE) ?
1.0 :
((uniform_buf.raytrace.closure_active == CLOSURE_REFRACTION) ?
gbuf.refraction.roughness :
gbuf.reflection.roughness);
if (ray_glossy_factor(roughness) > 0.0) {
float ray_glossy_factor = ray_glossy_factor(uniform_buf.raytrace, roughness);
if (ray_glossy_factor > 0.0) {
/* We don't care about race condition here. */
tile_contains_glossy_rays = 1;
tile_contains_ray_tracing = 1;
}
if (ray_glossy_factor < 1.0) {
/* We don't care about race condition here. */
tile_contains_horizon_scan = 1;
}
}
@ -67,8 +75,11 @@ void main()
ivec2 tile_co = ivec2(gl_WorkGroupID.xy);
uint tile_mask = 0u;
if (tile_contains_glossy_rays > 0) {
tile_mask = 1u;
if (tile_contains_ray_tracing > 0) {
tile_mask = 1u << 0u;
}
if (tile_contains_horizon_scan > 0) {
tile_mask = 1u << 1u;
}
imageStore(tile_mask_img, tile_co, uvec4(tile_mask));

View File

@ -22,6 +22,8 @@ void main()
bool tile_is_sampled = false;
/* True if this tile is shooting and tracing rays. */
bool tile_is_tracing = false;
/* True if this tile is using horizon scan. */
bool tile_is_scaning = false;
/* Could be optimized if that becomes an issue. */
for (int x_tile = -1; x_tile <= 1; x_tile++) {
for (int y_tile = -1; y_tile <= 1; y_tile++) {
@ -32,18 +34,32 @@ void main()
if (any(greaterThanEqual(full_res_tile, imageSize(tile_mask_img)))) {
continue;
}
bool denoise_tile_is_used = imageLoad(tile_mask_img, full_res_tile).r != 0u;
if (denoise_tile_is_used) {
uint tile_mask = imageLoad(tile_mask_img, full_res_tile).r;
bool tile_uses_ray_tracing = flag_test(tile_mask, 1u << 0u);
bool tile_uses_horizon_scan = flag_test(tile_mask, 1u << 1u);
if (tile_uses_ray_tracing) {
if (x_tile == 0 && y_tile == 0) {
/* Dispatch full resolution denoise tile. */
uint tile_index = atomicAdd(denoise_dispatch_buf.num_groups_x, 1u);
denoise_tiles_buf[tile_index] = packUvec2x16(uvec2(full_res_tile));
tile_is_tracing = true;
if (tile_uses_ray_tracing) {
/* Dispatch full resolution denoise tile. */
uint tile_index = atomicAdd(denoise_dispatch_buf.num_groups_x, 1u);
denoise_tiles_buf[tile_index] = packUvec2x16(uvec2(full_res_tile));
tile_is_tracing = true;
}
}
else {
/* This denoise tile will sample the target tracing tile. Make sure it is cleared. */
tile_is_sampled = true;
}
}
/* Dispatch full resolution horizon scan. */
/* TODO(fclem): Limit that to high roughness pixels. */
uint tile_horizon_index = atomicAdd(horizon_dispatch_buf.num_groups_x, 1u);
horizon_tiles_buf[tile_horizon_index] = packUvec2x16(uvec2(full_res_tile));
if (tile_uses_horizon_scan) {
if (x_tile == 0 && y_tile == 0) {
if (tile_uses_ray_tracing) {
/* Dispatch full resolution horizon scan. */
uint tile_horizon_index = atomicAdd(horizon_dispatch_buf.num_groups_x, 1u);
horizon_tiles_buf[tile_horizon_index] = packUvec2x16(uvec2(full_res_tile));
tile_is_scaning = true;
}
}
else {
/* This denoise tile will sample the target tracing tile. Make sure it is cleared. */

View File

@ -176,11 +176,8 @@ GPU_SHADER_CREATE_INFO(eevee_horizon_scan)
"eevee_lightprobe_data",
"draw_view")
.sampler(0, ImageType::FLOAT_2D, "screen_radiance_tx")
.image(2,
RAYTRACE_RADIANCE_FORMAT,
Qualifier::READ_WRITE,
ImageType::FLOAT_2D,
"out_radiance_img")
.image(2, RAYTRACE_RADIANCE_FORMAT, Qualifier::READ_WRITE, ImageType::FLOAT_2D, "radiance_img")
.image(6, RAYTRACE_TILEMASK_FORMAT, Qualifier::READ, ImageType::UINT_2D, "tile_mask_img")
.storage_buf(7, Qualifier::READ, "uint", "tiles_coord_buf[]")
.compute_source("eevee_horizon_scan_comp.glsl");