Skip to content

Conversation

@SparkyPotato
Copy link

No description provided.

// Use emissive only on the first ray (coming from the camera)
if ray_t_min == 0.0 { radiance = ray_hit.material.emissive; }
var mis_weight = 1.0;
if !is_perfectly_specular {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the bounce being a perfectly specular reflection matter?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BSDF PDF sampling will then return 0.0 as the pdf, which, if p_light is small, would lead to fireflies or inf/nans.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, we wanna disable MIS for dirac delta functions, so it might be a good idea to special-case the BRDF lobe MIS for perfect specular reflections too.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you might want to modify the mix function so that 0 roughness = always selects specular.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't do that, we still need to select diffuse if metallic is not 1, I just added a special case if statement at the top.

ray_origin = ray_hit.world_position;
ray_t_min = RAY_T_MIN;
p_bounce = next_bounce.pdf;
is_perfectly_specular = ray_hit.material.roughness < 0.0001 && ray_hit.material.metallic > 0.9999;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this something like bounce_was_perfect_reflection?

fn importance_sample_next_bounce(wo: vec3<f32>, ray_hit: ResolvedRayHitFull, rng: ptr<function, u32>) -> NextBounce {
let diffuse_weight = 1.0 - ray_hit.material.metallic;
let specular_weight = ray_hit.material.metallic;
let diffuse_weight = mix(mix(0.4f, 0.9f, ray_hit.material.roughness), 0.f, ray_hit.material.metallic);
Copy link
Owner

@JMS55 JMS55 Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theoretically the best way to do this would be sampling a lobe based on fresnel, but I felt like keeping it simple. This is good too.

Did you want to use roughness, or linear roughness here though?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a very good way to importance sample, might as well try perceptual roughness if that is better.

vertex_buffer_offset: vertex_slice.range.start,
index_buffer_id,
index_buffer_offset: index_slice.range.start,
triangle_count: (index_slice.range.len() / 3) as u32,
Copy link
Owner

@JMS55 JMS55 Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love adding this extra field, it's now bigger than 128 bits :(

And the triangle count already exists in the light source structure, it's just you need this for ray traces, since your not directly sampling the lights. Hmm. Lets talk about this over discord more.

@JMS55 JMS55 merged commit fb0cc10 into JMS55:solari6-specular Jul 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants