78 lines
2.6 KiB
Zig

const std = @import("std");
const color = @import("./color.zig");
const ray = @import("./ray.zig");
const vec = @import("./vec.zig");
const Color = vec.Color;
const Vec3 = vec.Vec3;
const Point3 = vec.Point3;
const info = std.log.info;
const write_color = color.write_color;
const Ray = ray.Ray;
fn hit_sphere(center: Point3, radius: f32, r: Ray) f32 {
const oc = r.origin().sub(center);
const a = Vec3.dot(r.direction(), r.direction());
const b = Vec3.dot(oc, r.direction()) * 2;
const c = Vec3.dot(oc, oc) - radius * radius;
const discriminant = b * b - 4 * a * c;
return if (discriminant < 0) -1 else (-b - @sqrt(discriminant)) / (2 * a);
}
fn ray_color(r: Ray) Color {
var t = hit_sphere(Point3.init(0, 0, -1), 0.5, r);
if (t > 0) {
const n = r.at(t).sub(Vec3.init(0, 0, -1)).unit();
return Color.init(
n.x() + 1,
n.y() + 1,
n.z() + 1,
).scale(0.5);
}
var unit_direction = r.direction().unit();
t = 0.5 * (unit_direction.y() + 1);
return Color.init(1, 1, 1).scale(1 - t).add(Color.init(0.5, 0.7, 1.0).scale(t));
}
pub fn main() anyerror!void {
// Image
const aspect_ratio: f32 = 16.0 / 9.0;
const image_width = 400;
const image_height = @floatToInt(isize, @intToFloat(f32, image_width) / aspect_ratio);
// Camera
const viewport_height = 2;
const viewport_width = aspect_ratio * viewport_height;
const focal_length = 1;
const origin = Point3.init(0, 0, 0);
const horizontal = Vec3.init(viewport_width, 0, 0);
const vertical = Vec3.init(0, viewport_height, 0);
const lower_left_corner = origin.sub(horizontal.scale(0.5)).sub(vertical.scale(0.5)).sub(Vec3.init(0, 0, focal_length));
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 j: isize = image_height - 1;
while (j >= 0) : (j -= 1) {
//info("Scanlines remaining: {d}", .{j});
var i: isize = 0;
while (i < image_width) : (i += 1) {
const u = @intToFloat(f32, i) / @intToFloat(f32, image_width - 1);
const v = @intToFloat(f32, j) / @intToFloat(f32, image_height - 1);
const r = Ray.init(origin, lower_left_corner.add(horizontal.scale(u)).add(vertical.scale(v)).sub(origin));
const pixel_color = ray_color(r);
try write_color(pixel_color);
}
}
info("Done", .{});
}
test {
// Run tests in imported source.
std.testing.refAllDecls(@This());
}