aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2023-03-05 17:55:51 +0900
committernsfisis <nsfisis@gmail.com>2023-05-07 10:09:08 +0900
commitca914b32fabdc5bb3e2782d91cc323205d0714fd (patch)
tree6862d744e41286d5e371c5a19946e7fa400285db
parent9ab677e15853814079583257d11256bdcdc88cbe (diff)
downloadRayTracingInOneWeekend.zig-ca914b32fabdc5bb3e2782d91cc323205d0714fd.tar.gz
RayTracingInOneWeekend.zig-ca914b32fabdc5bb3e2782d91cc323205d0714fd.tar.zst
RayTracingInOneWeekend.zig-ca914b32fabdc5bb3e2782d91cc323205d0714fd.zip
6.2
-rw-r--r--src/main.zig20
-rw-r--r--src/rtw/texture.zig48
2 files changed, 67 insertions, 1 deletions
diff --git a/src/main.zig b/src/main.zig
index 00bc7e6..4a667f9 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -244,6 +244,19 @@ fn generateRandomScene(rng: Random, allocator: anytype) !Hittable {
return .{ .list = .{ .objects = hittable_objects } };
}
+fn generateEarthScene(allocator: anytype) !Hittable {
+ var hittable_objects = ArrayList(Hittable).init(allocator);
+
+ const earth_texture = try Texture.makeImage(allocator, "assets/sekaichizu.png");
+ var earth_surface = try allocator.create(Material);
+
+ earth_surface.* = .{ .diffuse = .{ .albedo = earth_texture } };
+
+ try hittable_objects.append(makeSphere(.{ .x = 0, .y = 0, .z = 0 }, 2, earth_surface));
+
+ return .{ .list = .{ .objects = hittable_objects } };
+}
+
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
@@ -259,7 +272,7 @@ pub fn main() !void {
const samples_per_pixel = 50;
const max_depth = 50;
- const scene = 3;
+ const scene = 4;
// World
var world: Hittable = undefined;
@@ -284,6 +297,11 @@ pub fn main() !void {
lookFrom = .{ .x = 13, .y = 2, .z = 3 };
lookAt = .{ .x = 0, .y = 0, .z = 0 };
vFov = 20.0;
+ } else if (scene == 4) {
+ world = try generateEarthScene(allocator);
+ lookFrom = .{ .x = 13, .y = 2, .z = 3 };
+ lookAt = .{ .x = 0, .y = 0, .z = 0 };
+ vFov = 20.0;
}
defer world.deinit(allocator);
diff --git a/src/rtw/texture.zig b/src/rtw/texture.zig
index ae24265..95cbef4 100644
--- a/src/rtw/texture.zig
+++ b/src/rtw/texture.zig
@@ -1,4 +1,5 @@
const std = @import("std");
+const Image = @import("zigimg").Image;
const Color = @import("vec.zig").Color;
const Vec3 = @import("vec.zig").Vec3;
@@ -10,12 +11,14 @@ const TextureTag = enum {
solid,
checker,
noise,
+ image,
};
pub const Texture = union(TextureTag) {
solid: SolidTexture,
checker: CheckerTexture,
noise: NoiseTexture,
+ image: ImageTexture,
pub fn makeSolid(color: Color) Texture {
return .{ .solid = .{ .color = color } };
@@ -33,11 +36,16 @@ pub const Texture = union(TextureTag) {
return .{ .noise = try NoiseTexture.init(allocator, rng, scale) };
}
+ pub fn makeImage(allocator: std.mem.Allocator, file_path: []const u8) !Texture {
+ return .{ .image = try ImageTexture.init(allocator, file_path) };
+ }
+
pub fn value(tx: Texture, u: f64, v: f64, p: Vec3) Color {
return switch (tx) {
TextureTag.solid => |solidTx| solidTx.value(u, v, p),
TextureTag.checker => |checkerTx| checkerTx.value(u, v, p),
TextureTag.noise => |noiseTx| noiseTx.value(u, v, p),
+ TextureTag.image => |imageTx| imageTx.value(u, v, p),
};
}
};
@@ -102,3 +110,43 @@ pub const NoiseTexture = struct {
return rgb(1, 1, 1).mul(0.5 * (1.0 + @sin(tx.scale * p.z + 10.0 * tx.perlin.turb(p, 7))));
}
};
+
+pub const ImageTexture = struct {
+ image: Image,
+
+ fn init(allocator: std.mem.Allocator, file_path: []const u8) !ImageTexture {
+ const image = try Image.fromFilePath(allocator, file_path);
+ return .{
+ .image = image,
+ };
+ }
+
+ fn deinit(tx: ImageTexture) void {
+ tx.image.deinit();
+ }
+
+ fn value(tx: ImageTexture, u: f64, v: f64, p: Vec3) Color {
+ _ = p;
+ // Clamp input texture coordinates to [0, 1] x [1, 0]
+ const u_ = std.math.clamp(u, 0.0, 1.0);
+ const v_ = 1.0 - std.math.clamp(v, 0.0, 1.0); // Flip v to image coordinates
+ const i = @floatToInt(usize, u_ * @intToFloat(f64, tx.image.width));
+ const j = @floatToInt(usize, v_ * @intToFloat(f64, tx.image.height));
+ // Clamp integer mapping, since actual coordinates should be less than 1.0
+ const i_ = @min(i, tx.image.width - 1);
+ const j_ = @min(j, tx.image.width - 1);
+ const color_scale = 1.0 / 255.0;
+ const pixels = tx.image.pixels.asBytes();
+ const offset = j_ * tx.image.width * 4 + i_ * 4;
+ const r = @intToFloat(f64, pixels[offset + 0]);
+ const g = @intToFloat(f64, pixels[offset + 1]);
+ const b = @intToFloat(f64, pixels[offset + 2]);
+ const a = @intToFloat(f64, pixels[offset + 3]);
+ if (a == 0) {
+ // Ocean
+ return rgb(0, 0, 1.0);
+ } else {
+ return rgb(color_scale * r, color_scale * g, color_scale * b);
+ }
+ }
+};