From 0fbc7f32f278f8cc3da828eb156cb5ee2cdbe1cf Mon Sep 17 00:00:00 2001 From: Szymon Nowakowski Date: Sun, 30 Nov 2025 00:06:04 +0100 Subject: [PATCH] Grass, debugger, noise height gen --- .vscode/extensions.json | 5 ++ .vscode/launch.json | 15 +----- assets/blocks/Grass.json | 10 ++++ assets/materials/GrassSide.json | 5 ++ assets/materials/GrassTop.json | 5 ++ assets/textures/GrassSide_BaseColor.png | 3 ++ assets/textures/GrassTop_BaseColor.png | 3 ++ build.zig | 3 ++ src/Game.zig | 28 +++++++++-- src/math.zig | 7 +++ src/math/noise.zig | 65 +++++++++++++++++++++++++ 11 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 assets/blocks/Grass.json create mode 100644 assets/materials/GrassSide.json create mode 100644 assets/materials/GrassTop.json create mode 100644 assets/textures/GrassSide_BaseColor.png create mode 100644 assets/textures/GrassTop_BaseColor.png create mode 100644 src/math/noise.zig diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..7a693ea --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "vadimcn.vscode-lldb", + ], +} diff --git a/.vscode/launch.json b/.vscode/launch.json index 68248b3..81b47b8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -3,23 +3,10 @@ "configurations": [ { "name": "Launch", - "type": "cppdbg", + "type": "lldb", "request": "launch", "program": "${workspaceFolder}/zig-out/bin/voxel-game", "cwd": "${workspaceFolder}", - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true, - }, - { - "description": "Set Disassembly Flavor to Intel", - "text": "-gdb-set disassembly-flavor intel", - "ignoreFailures": true, - }, - ], }, ], } diff --git a/assets/blocks/Grass.json b/assets/blocks/Grass.json new file mode 100644 index 0000000..0eb5910 --- /dev/null +++ b/assets/blocks/Grass.json @@ -0,0 +1,10 @@ +{ + "materials": [ + "GrassSide.json", + "GrassSide.json", + "GrassSide.json", + "GrassSide.json", + "GrassTop.json", + "Dirt.json" + ] +} diff --git a/assets/materials/GrassSide.json b/assets/materials/GrassSide.json new file mode 100644 index 0000000..520f424 --- /dev/null +++ b/assets/materials/GrassSide.json @@ -0,0 +1,5 @@ +{ + "baseColorTexture": "GrassSide_BaseColor.png", + "roughness": 1, + "metallic": 0 +} diff --git a/assets/materials/GrassTop.json b/assets/materials/GrassTop.json new file mode 100644 index 0000000..1e9feae --- /dev/null +++ b/assets/materials/GrassTop.json @@ -0,0 +1,5 @@ +{ + "baseColorTexture": "GrassTop_BaseColor.png", + "roughness": 1, + "metallic": 0 +} diff --git a/assets/textures/GrassSide_BaseColor.png b/assets/textures/GrassSide_BaseColor.png new file mode 100644 index 0000000..7de3067 --- /dev/null +++ b/assets/textures/GrassSide_BaseColor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:762b42e31e0f9f6c520af8304850d57eb35cc9de103a4890ee3344d7c4298717 +size 771 diff --git a/assets/textures/GrassTop_BaseColor.png b/assets/textures/GrassTop_BaseColor.png new file mode 100644 index 0000000..fd42a6f --- /dev/null +++ b/assets/textures/GrassTop_BaseColor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:51a5b1a7279b8f64beaa0190f20172f40936b169831c7a2b9c5df9a8a64e01dd +size 345 diff --git a/build.zig b/build.zig index 82dac20..c6388a1 100644 --- a/build.zig +++ b/build.zig @@ -5,6 +5,7 @@ const zon = @import("build.zig.zon"); pub fn build(b: *std.Build) !void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); + const llvm = b.option(bool, "llvm", "Use LLVM and LLD") orelse false; const vulkan_dep = b.dependency("vulkan_zig", .{ .registry = b.path("vendor/vk.xml") }); const zglfw_dep = b.dependency("zglfw", .{ .import_vulkan = true }); @@ -36,6 +37,8 @@ pub fn build(b: *std.Build) !void { const exe = b.addExecutable(.{ .name = "voxel-game", .root_module = exe_mod, + .use_llvm = llvm, + .use_lld = llvm, }); b.installArtifact(exe); diff --git a/src/Game.zig b/src/Game.zig index df9ac28..8ef7246 100644 --- a/src/Game.zig +++ b/src/Game.zig @@ -613,6 +613,11 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain } var it = Interator3(i16).init(-10, -10, 0, 9, 9, 0); + + const block_grass = blocks.getFilename("Grass.json").?; + const block_dirt = blocks.getFilename("Dirt.json").?; + const block_bedrock = blocks.getFilename("Bedrock.json").?; + while (it.next()) |chunk_coords| { const origin = Vector3.init( @floatFromInt(chunk_coords[0]), @@ -630,9 +635,24 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain var it2 = Interator3(usize).init(0, 0, 0, 15, 15, 0); while (it2.next()) |pos| { - const x, const y, const z = pos; - const block: Blocks.Id = @enumFromInt(engine.random.intRangeLessThan(u12, 1, @intCast(blocks.blocks.items.len))); - chunk.blocks[z][y][x] = block; + const x, const y, _ = pos; + const fpos = Vector3.init( + @floatFromInt(pos[0]), + @floatFromInt(pos[1]), + @floatFromInt(pos[2]), + ).add(origin); + + const noise = std.math.clamp(math.noise2(fpos.asVector2().divScalar(30)), -1, 1); + const fheight = (0.5 * noise + 0.5) * 4 + 1; + const iheight: u32 = @intFromFloat(@round(fheight)); + + chunk.blocks[0][y][x] = block_bedrock; + var i: u32 = 0; + while (i < iheight) : (i += 1) { + const iz = i + 1; + const block = if (i + 1 == iheight) block_grass else block_dirt; + chunk.blocks[iz][y][x] = block; + } } } @@ -772,7 +792,7 @@ pub fn update(self: *Game, dt: f32) void { ); // zig fmt: on - const ambient_light = Vector3.init(0.001, 0.001, 0.001); + const ambient_light = Vector3.init(0.01, 0.01, 0.01); const global_uniforms_data: GlobalUniforms = .{ .matrixWStoVS = matrix_ws_to_vs.asArray(), diff --git a/src/math.zig b/src/math.zig index 72e5fce..cbf20f0 100644 --- a/src/math.zig +++ b/src/math.zig @@ -5,3 +5,10 @@ pub const Quaternion = @import("math/Quaternion.zig").Quaternion; pub const Vector2 = @import("math/Vector2.zig").Vector2; pub const Vector3 = @import("math/Vector3.zig").Vector3; pub const Vector4 = @import("math/Vector4.zig").Vector4; + +pub inline fn lerp(a: f32, b: f32, t: f32) f32 { + const s = 1.0 - t; + return a * t + b * s; +} + +pub const noise2 = @import("math/noise.zig").noise2; diff --git a/src/math/noise.zig b/src/math/noise.zig new file mode 100644 index 0000000..af58c6b --- /dev/null +++ b/src/math/noise.zig @@ -0,0 +1,65 @@ +const Vector2 = @import("Vector2.zig").Vector2; + +const permutation = [256]u8{ + 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, + 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, + 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, + 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, + 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, + 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, + 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, + 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, + 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, + 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, + 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, + 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, + 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, + 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, + 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, + 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180, +}; + +fn grad2(hash: u8, x: f32, y: f32) f32 { + const h: u3 = @truncate(hash); + const u: f32 = if (h < 4) x else y; + const v: f32 = if (h < 4) x else x; + return (if (h & 0b001 != 0) -u else u) + (if (hash & 0b010 != 0) -2 * v else 2 * v); +} + +const F2: f32 = 0.5 * (@sqrt(@as(f32, 3)) - 1); +const G2: f32 = (3 - @sqrt(@as(f32, 3))) / 6; + +pub fn noise2(v: Vector2) f32 { + const x: f32, const y: f32 = v.asArray(); + const s: f32 = (x + y) * F2; + const xs: f32 = x + s; + const ys: f32 = y + s; + const i: i32 = @intFromFloat(@floor(xs)); + const j: i32 = @intFromFloat(@floor(ys)); + + const t: f32 = @as(f32, @floatFromInt(i + j)) * G2; + const X0: f32 = @as(f32, @floatFromInt(i)) - t; + const Y0: f32 = @as(f32, @floatFromInt(j)) - t; + const x0: f32 = x - X0; + const y0: f32 = y - Y0; + + const _i1: u8, const _j1: u8 = if (x0 > y0) .{ 1, 0 } else .{ 0, 1 }; + + const x1: f32 = x0 - @as(f32, @floatFromInt(_i1)) + G2; + const y1: f32 = y0 - @as(f32, @floatFromInt(_j1)) + G2; + const x2: f32 = x0 - 1 + 2 * G2; + const y2: f32 = y0 - 1 + 2 * G2; + + const ii: u8 = @truncate(@as(u32, @bitCast(i))); + const jj: u8 = @truncate(@as(u32, @bitCast(j))); + + const t0: f32 = 0.5 - x0 * x0 - y0 * y0; + const t1: f32 = 0.5 - x1 * x1 - y1 * y1; + const t2: f32 = 0.5 - x2 * x2 - y2 * y2; + + const n0 = if (t0 < 0) 0 else (t0 * t0) * (t0 * t0) * grad2(permutation[ii +% permutation[jj]], x0, y0); + const n1 = if (t1 < 0) 0 else (t1 * t1) * (t1 * t1) * grad2(permutation[ii +% _i1 +% permutation[jj +% _j1]], x1, y1); + const n2 = if (t2 < 0) 0 else (t2 * t2) * (t2 * t2) * grad2(permutation[ii +% 1 +% permutation[jj +% 1]], x2, y2); + + return 40 * (n0 + n1 + n2); +}