EEVEE-Next: Add horizon scan to raytracing module #114259
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
Loading…
Reference in New Issue
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.