Add fresnel in raytracer example

This commit is contained in:
Nikita Lisitsa 2026-04-04 16:53:10 +03:00
parent 028895ce7f
commit bd9425ebec
2 changed files with 21 additions and 10 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

After

Width:  |  Height:  |  Size: 423 KiB

View file

@ -211,6 +211,9 @@ func log(x: f32) -> f32:
func abs(x: f32) -> f32: func abs(x: f32) -> f32:
return if x >= 0.0 then x else -x return if x >= 0.0 then x else -x
func sqr(x: f32) -> f32:
return x * x
func min(x: f32, y: f32) -> f32: func min(x: f32, y: f32) -> f32:
return if x <= y then x else y return if x <= y then x else y
@ -598,21 +601,29 @@ func raytrace(scene: scene*, camera_ray: ray, rng: rng mut*) -> vec3:
new_direction = normalized(add(new_direction, mults(next_vec3_normal(rng), cosine * intersection.material.roughness))) new_direction = normalized(add(new_direction, mults(next_vec3_normal(rng), cosine * intersection.material.roughness)))
else if intersection.material.type == glass_tag: else if intersection.material.type == glass_tag:
// This should also contain multiplication by brdf and division by direction pdf,
// but we'll just pretend that the random refracted ray pdf coincides with brdf and thus cancels out
factor = multv(factor, intersection.material.color)
mut ior = intersection.material.ior mut ior = intersection.material.ior
if inside: if inside:
ior = 1.0 / ior ior = 1.0 / ior
// Compute perfect refracted ray // Schlick's approximation for Fresnel term
let k = 1.0 - ior * ior * (1.0 - cosine * cosine) let r0 = sqr((1.0 - ior) / (1.0 + ior))
if k >= 0.0: let reflectance = r0 + (1.0 - r0) * pow(max(0.0, 1.0 - abs(cosine)), 5.0)
new_direction = add(mults(current_ray.direction, ior), mults(intersection.normal, ior * abs(cosine) - sqrt(k)))
else: if next_f32(rng) < reflectance:
// Total internal reflection // Compute perfect-mirror reflected direction
new_direction = add(current_ray.direction, mults(intersection.normal, 2.0 * cosine)) new_direction = add(current_ray.direction, mults(intersection.normal, 2.0 * cosine))
else:
// This should also contain multiplication by brdf and division by direction pdf,
// but we'll just pretend that the random refracted ray pdf coincides with brdf and thus cancels out
factor = multv(factor, intersection.material.color)
// Compute perfect refracted ray
let k = 1.0 - ior * ior * (1.0 - cosine * cosine)
if k >= 0.0:
new_direction = add(mults(current_ray.direction, ior), mults(intersection.normal, ior * abs(cosine) - sqrt(k)))
else:
// Total internal reflection
new_direction = add(current_ray.direction, mults(intersection.normal, 2.0 * cosine))
// Alter the direction based on roughness // Alter the direction based on roughness
new_direction = normalized(add(new_direction, mults(next_vec3_normal(rng), intersection.material.roughness))) new_direction = normalized(add(new_direction, mults(next_vec3_normal(rng), intersection.material.roughness)))