Implement MIS into the PT#34
Conversation
| // 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 { |
There was a problem hiding this comment.
Why does the bounce being a perfectly specular reflection matter?
There was a problem hiding this comment.
BSDF PDF sampling will then return 0.0 as the pdf, which, if p_light is small, would lead to fireflies or inf/nans.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I think you might want to modify the mix function so that 0 roughness = always selects specular.
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
No description provided.