remove workgroup optimization
This commit is contained in:
parent
8929fa2d63
commit
e12b27c2be
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user