remove workgroup optimization

This commit is contained in:
SparkyPotato 2025-07-16 20:10:11 +01:00
parent 8929fa2d63
commit e12b27c2be
2 changed files with 15 additions and 74 deletions

View File

@ -8,7 +8,7 @@
#import bevy_render::maths::PI
#import bevy_render::view::View
#import bevy_solari::sampling::{
LightSample, IndependentLightSample, generate_point_independent_sample, calculate_light_contribution_from_independent, calculate_light_contribution,
LightSample, IndependentLightSample, sample_random_light_contribution, calculate_light_contribution,
trace_visibility, trace_light_visibility,
sample_disk
}
@ -29,6 +29,7 @@
struct PushConstants { frame_index: u32, reset: u32 }
var<push_constant> constants: PushConstants;
const INITIAL_SAMPLES = 32u;
const SPATIAL_REUSE_RADIUS_PIXELS = 30.0;
const CONFIDENCE_WEIGHT_CAP = 20.0;
@ -47,8 +48,7 @@ fn compute_seed(global_id: vec3<u32>) -> u32 {
}
@compute @workgroup_size(8, 8, 1)
fn initial_and_temporal(@builtin(global_invocation_id) global_id: vec3<u32>,
@builtin(local_invocation_index) local_id: u32) {
fn initial_and_temporal(@builtin(global_invocation_id) global_id: vec3<u32>) {
if any(global_id.xy >= vec2u(view.viewport.zw)) { return; }
var rng = compute_seed(global_id);
@ -66,7 +66,7 @@ fn initial_and_temporal(@builtin(global_invocation_id) global_id: vec3<u32>,
let base_color = pow(unpack4x8unorm(gpixel.r).rgb, vec3(2.2));
let diffuse_brdf = base_color / PI;
let initial_reservoir = generate_initial_reservoir(world_position, world_normal, diffuse_brdf, &rng, local_id);
let initial_reservoir = generate_initial_reservoir(world_position, world_normal, diffuse_brdf, &rng);
let temporal_reservoir = load_temporal_reservoir(global_id.xy, depth, world_position, world_normal);
let merge_result = merge_reservoirs(initial_reservoir, temporal_reservoir, world_position, world_normal, diffuse_brdf, &rng);
@ -115,19 +115,14 @@ fn spatial_and_shade(@builtin(global_invocation_id) global_id: vec3<u32>) {
textureStore(view_output, global_id.xy, vec4(pixel_color, 1.0));
}
var<workgroup> position_independent_initial_samples: array<IndependentLightSample, 64u>;
fn generate_initial_reservoir(world_position: vec3<f32>, world_normal: vec3<f32>, diffuse_brdf: vec3<f32>, rng: ptr<function, u32>, local_id: u32) -> Reservoir {
position_independent_initial_samples[local_id] = generate_point_independent_sample(rng);
workgroupBarrier();
fn generate_initial_reservoir(world_position: vec3<f32>, world_normal: vec3<f32>, diffuse_brdf: vec3<f32>, rng: ptr<function, u32>) -> Reservoir {
var reservoir = empty_reservoir();
var reservoir_target_function = 0.0;
var ray_direction = vec4<f32>(0.0);
for (var i = 0u; i < 64u; i++) {
let light_contribution = calculate_light_contribution_from_independent(position_independent_initial_samples[i], world_position, world_normal);
for (var i = 0u; i < INITIAL_SAMPLES; i++) {
let light_contribution = sample_random_light_contribution(rng, world_position, world_normal);
let mis_weight = 1.0 / 64.0;
let mis_weight = 1.0 / f32(INITIAL_SAMPLES);
let target_function = luminance(light_contribution.radiance * diffuse_brdf);
let resampling_weight = mis_weight * (target_function * light_contribution.inverse_pdf);

View File

@ -58,8 +58,7 @@ struct SampleRandomLightResult {
}
fn sample_random_light(ray_origin: vec3<f32>, origin_world_normal: vec3<f32>, rng: ptr<function, u32>) -> SampleRandomLightResult {
let pos_independent_sample = generate_point_independent_sample(rng);
let light_contribution = calculate_light_contribution_from_independent(pos_independent_sample, ray_origin, origin_world_normal);
let light_contribution = sample_random_light_contribution(rng, ray_origin, origin_world_normal);
let visibility = trace_visibility(ray_origin, light_contribution.ray_direction);
return SampleRandomLightResult(light_contribution.radiance * visibility, light_contribution.inverse_pdf);
}
@ -84,75 +83,22 @@ struct LightContribution {
ray_direction: vec4<f32>,
}
fn generate_point_independent_sample(rng: ptr<function, u32>) -> IndependentLightSample {
fn sample_random_light_contribution(rng: ptr<function, u32>, ray_origin: vec3<f32>, origin_world_normal: vec3<f32>) -> LightContribution {
let light_count = arrayLength(&light_sources);
let light_id = rand_range_u(light_count, rng);
let light_source = light_sources[light_id];
var light_sample = LightSample(vec2(light_id, 0), rand_vec2f(rng));
var sample: IndependentLightSample;
var light_contribution: LightContribution;
if light_source.kind == LIGHT_SOURCE_KIND_DIRECTIONAL {
sample = calculate_directional_light_independent_contribution(light_sample, light_source.id);
light_contribution = calculate_directional_light_contribution(light_sample, light_source.id, origin_world_normal);
} else {
let triangle_count = light_source.kind >> 1u;
light_sample.light_id.y = rand_range_u(triangle_count, rng);
sample = calculate_emissive_mesh_independent_contribution(light_sample, light_source.id, triangle_count);
light_contribution = calculate_emissive_mesh_contribution(light_sample, light_source.id, triangle_count, ray_origin, origin_world_normal);
}
light_contribution.inverse_pdf *= f32(light_count);
sample.inverse_pdf *= f32(light_count);
return sample;
}
fn calculate_directional_light_independent_contribution(light_sample: LightSample, directional_light_id: u32) -> IndependentLightSample {
let directional_light = directional_lights[directional_light_id];
#ifdef DIRECTIONAL_LIGHT_SOFT_SHADOWS
// Sample a random direction within a cone whose base is the sun approximated as a disk
// https://www.realtimerendering.com/raytracinggems/unofficial_RayTracingGems_v1.9.pdf#0004286901.INDD%3ASec30%3A305
let cos_theta = (1.0 - light_sample.random.x) + light_sample.random.x * directional_light.cos_theta_max;
let sin_theta = sqrt(1.0 - cos_theta * cos_theta);
let phi = light_sample.random.y * PI_2;
let x = cos(phi) * sin_theta;
let y = sin(phi) * sin_theta;
var ray_direction = vec3(x, y, cos_theta);
// Rotate the ray so that the cone it was sampled from is aligned with the light direction
ray_direction = build_orthonormal_basis(directional_light.direction_to_light) * ray_direction;
#else
let ray_direction = directional_light.direction_to_light;
#endif
return IndependentLightSample(light_sample, directional_light.luminance, directional_light.inverse_pdf, vec4<f32>(ray_direction, 0.0), vec3<f32>(0.0));
}
fn calculate_emissive_mesh_independent_contribution(light_sample: LightSample, instance_id: u32, triangle_count: u32) -> IndependentLightSample {
let barycentrics = triangle_barycentrics(light_sample.random);
let triangle_id = light_sample.light_id.y;
let triangle_data = resolve_triangle_for_di(instance_id, triangle_id, barycentrics);
let inverse_pdf = f32(triangle_count) * triangle_data.triangle_area;
return IndependentLightSample(light_sample, triangle_data.emissive, inverse_pdf, vec4<f32>(triangle_data.world_position, 1.0), triangle_data.world_normal);
}
fn calculate_light_contribution_from_independent(sample: IndependentLightSample, ray_origin: vec3<f32>, origin_world_normal: vec3<f32>) -> LightContribution {
var radiance = vec3<f32>(0.0);
var ray_direction = vec4<f32>(0.0);
if sample.pos_or_direction.w == 0.0 {
// Directional light
ray_direction = vec4<f32>(sample.pos_or_direction.xyz, RAY_T_MAX);
let cos_theta_origin = saturate(dot(ray_direction.xyz, origin_world_normal));
radiance = sample.radiance * cos_theta_origin;
} else {
// Emissive mesh
let end_point = sample.pos_or_direction.xyz;
ray_direction = vec4<f32>(end_point - ray_origin, 0.0);
let light_distance_squared = dot(ray_direction.xyz, ray_direction.xyz);
ray_direction.w = sqrt(light_distance_squared);
ray_direction = vec4<f32>(ray_direction.xyz / ray_direction.w, ray_direction.w);
let cos_theta_origin = saturate(dot(ray_direction.xyz, origin_world_normal));
let cos_theta_light = saturate(dot(-ray_direction.xyz, sample.normal));
radiance = sample.radiance * cos_theta_origin * (cos_theta_light / light_distance_squared);
}
return LightContribution(sample.sample, radiance, sample.inverse_pdf, ray_direction);
return light_contribution;
}
fn calculate_light_contribution(light_sample: LightSample, ray_origin: vec3<f32>, origin_world_normal: vec3<f32>) -> LightContribution {