Compare commits

...

3 Commits

Author SHA1 Message Date
59bc5b640f per-vertex lighting! 2025-11-24 18:31:23 +03:00
41579bbb5d split colormap 2025-11-24 18:23:35 +03:00
722e5d4b6e split light calculations and camera rays 2025-11-24 18:21:31 +03:00

View File

@ -249,26 +249,6 @@ impl Core {
sphere(vec3(0.1, 0.3, 0.1)), sphere(vec3(0.1, 0.3, 0.1)),
], ],
}; };
if args.show_shapes {
let mut meshes = Vec::new();
for obj in &scene.objects {
let mesh = shape::sphere((obj.radius * 15.) as usize + 7);
let obj_mesh = render::faces::Mesh::new(
&self.device,
&mesh
.vertices
.iter()
.map(|v| render::faces::Vertex {
pos: obj.position + obj.radius * v,
color: 0.5 * (v + 1.),
})
.collect::<Vec<_>>(),
bytemuck::cast_slice(&mesh.indices),
);
meshes.push(obj_mesh);
}
self.mesh_pipe.render(&mut pass, &meshes);
}
let mut prng = rand_pcg::Pcg64::new(42, 0); let mut prng = rand_pcg::Pcg64::new(42, 0);
let source_rays: Vec<Ray> = (0..10240).map(|_| source.make_ray(&mut prng)).collect(); let source_rays: Vec<Ray> = (0..10240).map(|_| source.make_ray(&mut prng)).collect();
@ -346,16 +326,13 @@ impl Core {
hits1 = hits2; hits1 = hits2;
} }
} }
let mut camera_ray_display: Vec<Vertex> = Vec::with_capacity(camera_rays.len()); let light_at = {
if args.show_light {
let sigma2 = args.accum_sigma.powi(2); let sigma2 = args.accum_sigma.powi(2);
let accum_normalizator = (2. * PI * sigma2).sqrt().recip(); let accum_normalizator = (2. * PI * sigma2).sqrt().recip();
for ray in camera_rays { let hits = &hits;
let Some(hit) = scene.trace_ray(ray) else { move |hit: Hit| -> f32 {
continue;
};
let mut total_cd = 0.0f32; let mut total_cd = 0.0f32;
for light_hit in &hits { for light_hit in hits {
let d2 = hit.incident.base.distance_squared(light_hit.incident.base); let d2 = hit.incident.base.distance_squared(light_hit.incident.base);
if d2 > 9. * sigma2 { if d2 > 9. * sigma2 {
continue; continue;
@ -368,14 +345,28 @@ impl Core {
assert!(hit.incident.dir.is_normalized()); assert!(hit.incident.dir.is_normalized());
let reflector = Lambertian; let reflector = Lambertian;
let in_lm = 1.0; let in_lm = 1.0;
let out_cd = in_lm * reflector.brdf(normal, light_hit.incident.dir, -ray.dir); let out_cd =
in_lm * reflector.brdf(normal, light_hit.incident.dir, -hit.incident.dir);
let weight = accum_normalizator * (-0.5 * d2 / sigma2).exp(); let weight = accum_normalizator * (-0.5 * d2 / sigma2).exp();
total_cd += weight * out_cd; total_cd += weight * out_cd;
} }
let brightness = 3. * (1. - (1. + total_cd * args.accum_scale).recip()); total_cd * args.accum_scale
let r = args.accum_sigma; }
let color = vec3(brightness, brightness - 1., brightness - 2.) };
.clamp(Vec3::splat(0.), Vec3::splat(1.)); let colormap = |light: f32| {
let brightness = 3. * (1. - (1. + light).recip());
vec3(brightness, brightness - 1., brightness - 2.)
.clamp(Vec3::splat(0.), Vec3::splat(1.))
};
let mut camera_ray_display: Vec<Vertex> = Vec::with_capacity(camera_rays.len());
if args.show_light {
let r = args.accum_sigma;
for ray in camera_rays {
let Some(hit) = scene.trace_ray(ray) else {
continue;
};
let light = light_at(hit);
let color = colormap(light);
let vertex = |off: Vec3| Vertex { let vertex = |off: Vec3| Vertex {
pos: hit.incident.base + r * off, pos: hit.incident.base + r * off,
color, color,
@ -390,6 +381,33 @@ impl Core {
]); ]);
} }
} }
if args.show_shapes {
let mut meshes = Vec::new();
for obj in &scene.objects {
let mesh = shape::sphere((obj.radius * 45.) as usize + 7);
let obj_mesh = render::faces::Mesh::new(
&self.device,
&mesh
.vertices
.iter()
.map(|&v| {
let pos = obj.position + obj.radius * v;
let normal = v;
let dir = (pos - camera.position()).normalize();
let light = light_at(Hit {
incident: Ray::new(pos, dir),
normal,
});
let color = colormap(light);
render::faces::Vertex { pos, color }
})
.collect::<Vec<_>>(),
bytemuck::cast_slice(&mesh.indices),
);
meshes.push(obj_mesh);
}
self.mesh_pipe.render(&mut pass, &meshes);
}
if !source_ray_display.is_empty() { if !source_ray_display.is_empty() {
self.pipeline self.pipeline
.render(&mut pass, [&Mesh::new(&self.device, &source_ray_display)]); .render(&mut pass, [&Mesh::new(&self.device, &source_ray_display)]);