this repo has no description
1const std = @import("std");
2
3const spall = @import("spall");
4const zigimg = @import("zigimg");
5const zm = @import("zmath");
6
7const Camera = @import("camera.zig");
8const hittable = @import("hittable.zig");
9const material = @import("material.zig");
10const Ray = @import("ray.zig");
11const util = @import("util.zig");
12
13const interval = @import("a").interval;
14const IntervalUsize = interval.IntervalUsize;
15const IntervalF32 = interval.IntervalF32;
16
17const log = std.log.scoped(.renderer);
18
19pub const Context = struct {
20 cam: *Camera,
21 world: *hittable.HittableList,
22};
23
24pub fn rayColor(r: *Ray, world: *hittable.HittableList, depth: usize) zm.Vec {
25 if (depth <= 0) return zm.f32x4(0, 0, 0, 1.0);
26
27 if (world.hit(r, IntervalF32.init(0.001, std.math.inf(f32)))) |rec| {
28 var attenuation = zm.f32x4s(1.0);
29 if (rec.mat.scatter(r, @constCast(&rec), &attenuation)) |new_r| {
30 return attenuation * rayColor(@constCast(&new_r), world, depth - 1);
31 }
32
33 return zm.f32x4(0, 0, 0, 1.0);
34 }
35
36 const unit_direction = zm.normalize3(r.dir);
37 const a = 0.5 * (unit_direction[1] + 1.0);
38 return zm.f32x4s(1.0 - a) * zm.f32x4s(1.0) + zm.f32x4s(a) * zm.f32x4(0.5, 0.7, 1.0, 1.0);
39}
40
41pub fn run(ctx: Context, height: IntervalUsize, width: IntervalUsize) void {
42 var height_iter = height.iter();
43 while (height_iter.nextInc()) |j| {
44 if (j >= ctx.cam.image_height) break;
45
46 var width_iter = width.iter();
47 while (width_iter.nextExc()) |i| {
48 var col = zm.f32x4(0.0, 0.0, 0.0, 1.0);
49 for (0..ctx.cam.samples_per_pixel) |_| {
50 var ray = ctx.cam.getRay(i, j);
51 col += rayColor(&ray, ctx.world, ctx.cam.max_depth);
52 }
53
54 ctx.cam.setPixel(i, j, vecToRgba(col, ctx.cam.samples_per_pixel)) catch break;
55 }
56 }
57}
58
59fn vecToRgba(v: zm.Vec, samples_per_pixel: usize) zigimg.color.Rgba32 {
60 const scale: f32 = 1.0 / @as(f32, @floatFromInt(samples_per_pixel));
61 const intensity = IntervalF32.init(0.0, 0.999);
62
63 const r_scaled = linearToGamma(v[0] * scale);
64 const g_scaled = linearToGamma(v[1] * scale);
65 const b_scaled = linearToGamma(v[2] * scale);
66 const a_scaled = linearToGamma(v[3] * scale);
67
68 const r: u8 = @intFromFloat(256 * intensity.clamp(r_scaled));
69 const g: u8 = @intFromFloat(256 * intensity.clamp(g_scaled));
70 const b: u8 = @intFromFloat(256 * intensity.clamp(b_scaled));
71 const a: u8 = @intFromFloat(256 * intensity.clamp(a_scaled));
72
73 return zigimg.color.Rgba32.initRgba(r, g, b, a);
74}
75
76inline fn linearToGamma(linear_component: f32) f32 {
77 return @sqrt(linear_component);
78}