zigrtiow: add camera class and support supersampling.
This commit is contained in:
parent
84a0ba2ec6
commit
e31f5e0a3a
33
zigrtiow/src/camera.zig
Normal file
33
zigrtiow/src/camera.zig
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const vec = @import("./vec.zig");
|
||||||
|
|
||||||
|
const Ray = @import("./ray.zig").Ray;
|
||||||
|
|
||||||
|
const Point3 = vec.Point3;
|
||||||
|
const Vec3 = vec.Vec3;
|
||||||
|
|
||||||
|
pub const Camera = struct {
|
||||||
|
origin: Point3,
|
||||||
|
lower_left_corner: Point3,
|
||||||
|
horizontal: Vec3,
|
||||||
|
vertical: Vec3,
|
||||||
|
|
||||||
|
pub fn init() Camera {
|
||||||
|
const aspect_ratio = 16.0 / 9.0;
|
||||||
|
const viewport_height = 2.0;
|
||||||
|
const viewport_width = aspect_ratio * viewport_height;
|
||||||
|
const focal_length = 1.0;
|
||||||
|
const origin = Point3.init(0, 0, 0);
|
||||||
|
const horizontal = Vec3.init(viewport_width, 0.0, 0.0);
|
||||||
|
const vertical = Vec3.init(0.0, viewport_height, 0.0);
|
||||||
|
|
||||||
|
return Camera{
|
||||||
|
.origin = origin,
|
||||||
|
.horizontal = horizontal,
|
||||||
|
.vertical = vertical,
|
||||||
|
.lower_left_corner = origin.sub(horizontal.scale(0.5)).sub(vertical.scale(0.5)).sub(Vec3.init(0, 0, focal_length)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
pub fn get_ray(camera: Camera, u: f32, v: f32) Ray {
|
||||||
|
return Ray.init(camera.origin, camera.lower_left_corner.add(camera.horizontal.scale(u).add(camera.vertical.scale(v).sub(camera.origin))));
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -1,10 +1,24 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const clamp = @import("./utils.zig").clamp;
|
||||||
const Color = @import("./vec.zig").Color;
|
const Color = @import("./vec.zig").Color;
|
||||||
|
|
||||||
pub fn write_color(c: Color) anyerror!void {
|
pub fn write_color(c: Color, samples_per_pixel: isize) anyerror!void {
|
||||||
var ir = @floatToInt(u8, 255.999 * c.x());
|
var r = c.x();
|
||||||
var ig = @floatToInt(u8, 255.999 * c.y());
|
var g = c.y();
|
||||||
var ib = @floatToInt(u8, 255.999 * c.z());
|
var b = c.z();
|
||||||
|
|
||||||
|
// Divide the color by the number of samples.
|
||||||
|
var scale = 1.0 / @intToFloat(f32, samples_per_pixel);
|
||||||
|
r *= scale;
|
||||||
|
g *= scale;
|
||||||
|
b *= scale;
|
||||||
|
|
||||||
|
// Write the translated [0,255] value of each color component.
|
||||||
|
var ir = @floatToInt(u8, 256 * clamp(r, 0, 0.999));
|
||||||
|
var ig = @floatToInt(u8, 256 * clamp(g, 0, 0.999));
|
||||||
|
var ib = @floatToInt(u8, 256 * clamp(b, 0, 0.999));
|
||||||
|
|
||||||
const stdout = std.io.getStdOut();
|
const stdout = std.io.getStdOut();
|
||||||
try stdout.writer().print("{d} {d} {d}\n", .{ ir, ig, ib });
|
try stdout.writer().print("{d} {d} {d}\n", .{ ir, ig, ib });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const camera = @import("./camera.zig");
|
||||||
const color = @import("./color.zig");
|
const color = @import("./color.zig");
|
||||||
const ray = @import("./ray.zig");
|
const ray = @import("./ray.zig");
|
||||||
const vec = @import("./vec.zig");
|
const vec = @import("./vec.zig");
|
||||||
@ -6,6 +7,7 @@ const sphere = @import("./sphere.zig");
|
|||||||
const hittable = @import("./hittable.zig");
|
const hittable = @import("./hittable.zig");
|
||||||
const hittable_list = @import("./hittable_list.zig");
|
const hittable_list = @import("./hittable_list.zig");
|
||||||
|
|
||||||
|
const Camera = camera.Camera;
|
||||||
const Color = vec.Color;
|
const Color = vec.Color;
|
||||||
const Hittable = hittable.Hittable;
|
const Hittable = hittable.Hittable;
|
||||||
const HittableList = hittable_list.HittableList;
|
const HittableList = hittable_list.HittableList;
|
||||||
@ -36,6 +38,7 @@ pub fn main() anyerror!void {
|
|||||||
const aspect_ratio: f32 = 16.0 / 9.0;
|
const aspect_ratio: f32 = 16.0 / 9.0;
|
||||||
const image_width = 400;
|
const image_width = 400;
|
||||||
const image_height = @floatToInt(isize, @intToFloat(f32, image_width) / aspect_ratio);
|
const image_height = @floatToInt(isize, @intToFloat(f32, image_width) / aspect_ratio);
|
||||||
|
const samples_per_pixel = 100;
|
||||||
|
|
||||||
// World
|
// World
|
||||||
var world = HittableList.init();
|
var world = HittableList.init();
|
||||||
@ -43,31 +46,32 @@ pub fn main() anyerror!void {
|
|||||||
try world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, -100.5, -1), 100) });
|
try world.add(Hittable{ .sphere = Sphere.init(Point3.init(0, -100.5, -1), 100) });
|
||||||
|
|
||||||
// Camera
|
// Camera
|
||||||
const viewport_height = 2;
|
const cam = Camera.init();
|
||||||
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));
|
|
||||||
|
|
||||||
|
// Render
|
||||||
const stdout = std.io.getStdOut();
|
const stdout = std.io.getStdOut();
|
||||||
|
|
||||||
info("Writing image {d}x{d}", .{ image_width, image_height });
|
info("Writing image {d}x{d}", .{ image_width, image_height });
|
||||||
try stdout.writer().print("P3\n{d} {d}\n255\n", .{ 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;
|
var j: isize = image_height - 1;
|
||||||
while (j >= 0) : (j -= 1) {
|
while (j >= 0) : (j -= 1) {
|
||||||
//info("Scanlines remaining: {d}", .{j});
|
//info("Scanlines remaining: {d}", .{j});
|
||||||
|
|
||||||
var i: isize = 0;
|
var i: isize = 0;
|
||||||
while (i < image_width) : (i += 1) {
|
while (i < image_width) : (i += 1) {
|
||||||
const u = @intToFloat(f32, i) / @intToFloat(f32, image_width - 1);
|
var pixel_color = Color.init(0, 0, 0);
|
||||||
const v = @intToFloat(f32, j) / @intToFloat(f32, image_height - 1);
|
var s: isize = 0;
|
||||||
const r = Ray.init(origin, lower_left_corner.add(horizontal.scale(u)).add(vertical.scale(v)).sub(origin));
|
while (s < samples_per_pixel) : (s += 1) {
|
||||||
const pixel_color = ray_color(r, Hittable{ .hittable_list = world });
|
const u = (@intToFloat(f32, i) + rand.float(f32)) / @intToFloat(f32, image_width - 1);
|
||||||
try write_color(pixel_color);
|
const v = (@intToFloat(f32, j) + rand.float(f32)) / @intToFloat(f32, image_height - 1);
|
||||||
|
const r = cam.get_ray(u, v);
|
||||||
|
//Ray.init(origin, lower_left_corner.add(horizontal.scale(u)).add(vertical.scale(v)).sub(origin));
|
||||||
|
pixel_color = pixel_color.add(ray_color(r, Hittable{ .hittable_list = world }));
|
||||||
|
}
|
||||||
|
try write_color(pixel_color, samples_per_pixel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info("Done", .{});
|
info("Done", .{});
|
||||||
|
|||||||
5
zigrtiow/src/utils.zig
Normal file
5
zigrtiow/src/utils.zig
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
pub fn clamp(x: f32, min: f32, max: f32) f32 {
|
||||||
|
if (x < min) return min;
|
||||||
|
if (x > max) return max;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user