zigrtiow: multithreaded renderer.
This commit is contained in:
parent
ac73d13fb0
commit
e5ffe87192
@ -8,6 +8,8 @@ const hittable = @import("./hittable.zig");
|
||||
const hittable_list = @import("./hittable_list.zig");
|
||||
const material = @import("./material.zig");
|
||||
|
||||
const Thread = std.Thread;
|
||||
const Queue = std.atomic.Queue;
|
||||
const Camera = camera.Camera;
|
||||
const Color = vec.Color;
|
||||
const Hittable = hittable.Hittable;
|
||||
@ -38,6 +40,43 @@ fn ray_color(r: Ray, world: Hittable, depth: isize) Color {
|
||||
return Color.init(1, 1, 1).scale(1 - t).add(Color.init(0.5, 0.7, 1.0).scale(t));
|
||||
}
|
||||
|
||||
const Task = struct {
|
||||
cam: Camera,
|
||||
samples_per_pixel: usize,
|
||||
max_depth: isize,
|
||||
row_idx: usize,
|
||||
image_height: isize,
|
||||
image_width: isize,
|
||||
row_pixels: []Color,
|
||||
world: Hittable,
|
||||
};
|
||||
|
||||
fn render_row(q: *Queue(Task)) void {
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
const rand = prng.random();
|
||||
while (true) {
|
||||
if (q.get()) |node| {
|
||||
const task = node.data;
|
||||
info("Rendering row: {}", .{task.row_idx});
|
||||
const j = task.row_idx;
|
||||
var i: usize = 0;
|
||||
while (i < task.image_width) : (i += 1) {
|
||||
var pixel_color = Color.init(0, 0, 0);
|
||||
var s: isize = 0;
|
||||
while (s < task.samples_per_pixel) : (s += 1) {
|
||||
const u = (@intToFloat(f32, i) + rand.float(f32)) / @intToFloat(f32, task.image_width - 1);
|
||||
const v = (@intToFloat(f32, j) + rand.float(f32)) / @intToFloat(f32, task.image_height - 1);
|
||||
const r = task.cam.get_ray(u, v);
|
||||
pixel_color = pixel_color.add(ray_color(r, task.world, task.max_depth));
|
||||
}
|
||||
task.row_pixels[i] = pixel_color;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Image
|
||||
const aspect_ratio: f32 = 16.0 / 9.0;
|
||||
@ -64,27 +103,56 @@ pub fn main() anyerror!void {
|
||||
const cam = Camera.init();
|
||||
|
||||
// Render
|
||||
const Node = Queue(Task).Node;
|
||||
const allocator = std.heap.page_allocator;
|
||||
const cpus = try Thread.getCpuCount();
|
||||
var pixels: [image_width * image_height]Color = undefined;
|
||||
var q = Queue(Task).init();
|
||||
var threads: std.ArrayList(std.Thread) = std.ArrayList(std.Thread).init(allocator);
|
||||
var row: usize = 0;
|
||||
while (row < image_height) : (row += 1) {
|
||||
const node = try allocator.create(Node);
|
||||
const start: usize = row * image_width;
|
||||
const end: usize = (row + 1) * image_width;
|
||||
node.* = .{
|
||||
.prev = undefined,
|
||||
.next = undefined,
|
||||
.data = Task{
|
||||
.cam = cam,
|
||||
.samples_per_pixel = samples_per_pixel,
|
||||
.max_depth = max_depth,
|
||||
.row_idx = row,
|
||||
.image_width = image_width,
|
||||
.image_height = image_height,
|
||||
.row_pixels = pixels[start..end],
|
||||
.world = world,
|
||||
},
|
||||
};
|
||||
q.put(node);
|
||||
}
|
||||
|
||||
var t: usize = 0;
|
||||
while (t < cpus) : (t += 1) {
|
||||
try threads.append(try Thread.spawn(.{}, render_row, .{&q}));
|
||||
}
|
||||
|
||||
// Wait for all threads to finish.
|
||||
for (threads.items) |thread| {
|
||||
Thread.join(thread);
|
||||
}
|
||||
|
||||
const stdout = std.io.getStdOut();
|
||||
|
||||
info("Writing image {d}x{d}", .{ image_width, image_height });
|
||||
try stdout.writer().print("P3\n{d} {d}\n255\n", .{ image_width, image_height });
|
||||
|
||||
var prng = std.rand.DefaultPrng.init(0);
|
||||
const rand = prng.random();
|
||||
var j: isize = image_height - 1;
|
||||
while (j >= 0) : (j -= 1) {
|
||||
info("Scanlines remaining: {d}", .{j});
|
||||
|
||||
var i: isize = 0;
|
||||
var j: usize = 0;
|
||||
while (j < image_height) : (j += 1) {
|
||||
var i: usize = 0;
|
||||
while (i < image_width) : (i += 1) {
|
||||
var pixel_color = Color.init(0, 0, 0);
|
||||
var s: isize = 0;
|
||||
while (s < samples_per_pixel) : (s += 1) {
|
||||
const u = (@intToFloat(f32, i) + rand.float(f32)) / @intToFloat(f32, image_width - 1);
|
||||
const v = (@intToFloat(f32, j) + rand.float(f32)) / @intToFloat(f32, image_height - 1);
|
||||
const r = cam.get_ray(u, v);
|
||||
pixel_color = pixel_color.add(ray_color(r, world, max_depth));
|
||||
}
|
||||
// Flip image upside down.
|
||||
const j_idx = @as(usize, image_height) - j - 1;
|
||||
const pixel_color = pixels[i + j_idx * image_width];
|
||||
try write_color(pixel_color, samples_per_pixel);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user