SIMD noise (not used yet)
This commit is contained in:
41
src/Game.zig
41
src/Game.zig
@@ -616,6 +616,7 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
|
||||
const block_grass = blocks.getFilename("Grass.json").?;
|
||||
const block_dirt = blocks.getFilename("Dirt.json").?;
|
||||
const block_stone = blocks.getFilename("Stone.json").?;
|
||||
const block_bedrock = blocks.getFilename("Bedrock.json").?;
|
||||
|
||||
while (it.next()) |chunk_coords| {
|
||||
@@ -636,26 +637,30 @@ 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, _ = pos;
|
||||
const fpos = Vector3.init(
|
||||
const fpos = Vector2.init(
|
||||
@floatFromInt(pos[0]),
|
||||
@floatFromInt(pos[1]),
|
||||
@floatFromInt(pos[2]),
|
||||
).add(origin);
|
||||
).add(origin.asVector2());
|
||||
|
||||
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));
|
||||
const iheight = worldHeightI(fpos);
|
||||
|
||||
chunk.blocks[0][y][x] = block_bedrock;
|
||||
var i: u32 = 0;
|
||||
var i: i32 = 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;
|
||||
const block = if (i + 1 == iheight)
|
||||
block_grass
|
||||
else if (i + 4 >= iheight)
|
||||
block_dirt
|
||||
else
|
||||
block_stone;
|
||||
chunk.blocks[@intCast(iz)][y][x] = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const camera_position = Vector3.init(0, 0, @as(f32, @floatFromInt(worldHeightI(.zero))) + 0.5 + 1.62);
|
||||
|
||||
var chunk_it = chunks.iterator();
|
||||
while (chunk_it.next()) |entry| {
|
||||
const x, const y, const z = entry.key_ptr.*;
|
||||
@@ -713,6 +718,8 @@ pub fn init(allocator: std.mem.Allocator, engine: *Engine, swapchain: *Swapchain
|
||||
.materials = materials,
|
||||
.textures = textures,
|
||||
.chunks = chunks,
|
||||
|
||||
.camera_position = camera_position,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -989,3 +996,19 @@ fn recreateSwapchain(self: *Game) !void {
|
||||
self.engine.setObjectName(semaphore.*, "S Transfer[{d}]", .{i});
|
||||
}
|
||||
}
|
||||
|
||||
fn worldHeightF(pos: Vector2) f32 {
|
||||
const noise_hscale = 80;
|
||||
|
||||
const noise_zcenter = 8;
|
||||
const noise_zscale = 5;
|
||||
|
||||
const noise = math.noise2(pos.divScalar(noise_hscale));
|
||||
const height = noise_zscale * noise + noise_zcenter;
|
||||
return height;
|
||||
}
|
||||
|
||||
fn worldHeightI(pos: Vector2) i32 {
|
||||
const iheight = worldHeightF(pos);
|
||||
return @intFromFloat(@round(iheight));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
const std = @import("std");
|
||||
|
||||
const Vector2 = @import("Vector2.zig").Vector2;
|
||||
|
||||
const f32x8 = @Vector(8, f32);
|
||||
const i32x8 = @Vector(8, i32);
|
||||
const u32x8 = @Vector(8, u32);
|
||||
|
||||
inline fn ps(value: f32) f32x8 {
|
||||
return @splat(value);
|
||||
}
|
||||
|
||||
inline fn epi32(value: i32) i32x8 {
|
||||
return @splat(value);
|
||||
}
|
||||
|
||||
inline fn epu32(value: u32) u32x8 {
|
||||
return @splat(value);
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -19,18 +37,56 @@ const permutation = [256]u8{
|
||||
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);
|
||||
inline fn perm(i: i32) i32 {
|
||||
@setRuntimeSafety(false);
|
||||
const index: u32 = @as(u32, @bitCast(i)) & 0xFF;
|
||||
return permutation[index];
|
||||
}
|
||||
|
||||
const F2: f32 = 0.5 * (@sqrt(@as(f32, 3)) - 1);
|
||||
inline fn permv(i: i32x8) i32x8 {
|
||||
@setRuntimeSafety(false);
|
||||
const index: u32x8 = @as(u32x8, @bitCast(i)) & epu32(0xFF);
|
||||
return .{
|
||||
permutation[index[0]],
|
||||
permutation[index[1]],
|
||||
permutation[index[2]],
|
||||
permutation[index[3]],
|
||||
permutation[index[4]],
|
||||
permutation[index[5]],
|
||||
permutation[index[6]],
|
||||
permutation[index[7]],
|
||||
};
|
||||
}
|
||||
|
||||
fn grad2(hash: i32, x: f32, y: f32) f32 {
|
||||
const h: i32 = hash & 0b111;
|
||||
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 (h & 0b010 != 0) -2 * v else 2 * v);
|
||||
}
|
||||
|
||||
fn grad2v(hash: i32x8, x: f32x8, y: f32x8) f32x8 {
|
||||
const h: i32x8 = hash & epi32(0b111);
|
||||
const u: f32x8 = @select(f32, h < epi32(4), x, y);
|
||||
const v: f32x8 = @select(f32, h < epi32(4), y, x);
|
||||
const r1: f32x8 = @select(f32, h & epi32(0b001) != epi32(0), -u, u);
|
||||
const r2: f32x8 = @select(f32, h & epi32(0b010) != epi32(0), ps(-2) * v, ps(2) * v);
|
||||
return r1 + r2;
|
||||
}
|
||||
|
||||
const F2: f32 = (@sqrt(@as(f32, 3)) - 1) / 2;
|
||||
const G2: f32 = (3 - @sqrt(@as(f32, 3))) / 6;
|
||||
|
||||
const F2v: f32x8 = ps(F2);
|
||||
const G2v: f32x8 = ps(G2);
|
||||
|
||||
// NOTE No idea why this value, derived experimentally
|
||||
const noise2_scale: f32 = 34.11;
|
||||
const noise2v_scale: f32x8 = ps(noise2_scale);
|
||||
|
||||
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;
|
||||
@@ -43,23 +99,65 @@ pub fn noise2(v: Vector2) f32 {
|
||||
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 _i1: i32 = if (x0 > y0) 1 else 0;
|
||||
const _j1: i32 = if (x0 > y0) 0 else 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);
|
||||
const gi0: i32 = perm(i + perm(j));
|
||||
const gi1: i32 = perm(i + _i1 + perm(j + _j1));
|
||||
const gi2: i32 = perm(i + 1 + perm(j + 1));
|
||||
|
||||
return 40 * (n0 + n1 + n2);
|
||||
const n0: f32 = if (t0 < 0) 0 else (t0 * t0) * (t0 * t0) * grad2(gi0, x0, y0);
|
||||
const n1: f32 = if (t1 < 0) 0 else (t1 * t1) * (t1 * t1) * grad2(gi1, x1, y1);
|
||||
const n2: f32 = if (t2 < 0) 0 else (t2 * t2) * (t2 * t2) * grad2(gi2, x2, y2);
|
||||
|
||||
const ret: f32 = noise2_scale * (n0 + n1 + n2);
|
||||
std.debug.assert(ret >= -1 and ret <= 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
pub fn noise2v(x: f32x8, y: f32x8) f32x8 {
|
||||
const s: f32x8 = (x + y) * F2v;
|
||||
const xs: f32x8 = x + s;
|
||||
const ys: f32x8 = y + s;
|
||||
const i: i32x8 = @intFromFloat(@floor(xs));
|
||||
const j: i32x8 = @intFromFloat(@floor(ys));
|
||||
|
||||
const t: f32x8 = @as(f32x8, @floatFromInt(i + j)) * G2v;
|
||||
const X0: f32x8 = @as(f32x8, @floatFromInt(i)) - t;
|
||||
const Y0: f32x8 = @as(f32x8, @floatFromInt(j)) - t;
|
||||
const x0: f32x8 = x - X0;
|
||||
const y0: f32x8 = y - Y0;
|
||||
|
||||
const _i1: i32x8 = @select(i32, x0 > y0, epi32(1), epi32(0));
|
||||
const _j1: i32x8 = @select(i32, x0 > y0, epi32(0), epi32(1));
|
||||
|
||||
const x1: f32x8 = x0 - @as(f32x8, @floatFromInt(_i1)) + G2v;
|
||||
const y1: f32x8 = y0 - @as(f32x8, @floatFromInt(_j1)) + G2v;
|
||||
const x2: f32x8 = x0 - ps(1) + ps(2) * G2v;
|
||||
const y2: f32x8 = y0 - ps(1) + ps(2) * G2v;
|
||||
|
||||
const t0: f32x8 = ps(0.5) - x0 * x0 - y0 * y0;
|
||||
const t1: f32x8 = ps(0.5) - x1 * x1 - y1 * y1;
|
||||
const t2: f32x8 = ps(0.5) - x2 * x2 - y2 * y2;
|
||||
|
||||
const gi0: i32x8 = permv(i + permv(j));
|
||||
const gi1: i32x8 = permv(i + _i1 + permv(j + _j1));
|
||||
const gi2: i32x8 = permv(i + epi32(1) + permv(j + epi32(1)));
|
||||
|
||||
const n0: f32x8 = @select(f32, t0 < ps(0), ps(0), (t0 * t0) * (t0 * t0) * grad2(gi0, x0, y0));
|
||||
const n1: f32x8 = @select(f32, t1 < ps(0), ps(0), (t1 * t1) * (t1 * t1) * grad2(gi1, x1, y1));
|
||||
const n2: f32x8 = @select(f32, t2 < ps(0), ps(0), (t2 * t2) * (t2 * t2) * grad2(gi2, x2, y2));
|
||||
|
||||
const ret: f32x8 = noise2v_scale * (n0 + n1 + n2);
|
||||
std.debug.assert(@reduce(.And, ret >= ps(-1)) and @reduce(.And, ret <= ps(1)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
32
src/math/noise_rangetest.zig
Normal file
32
src/math/noise_rangetest.zig
Normal file
@@ -0,0 +1,32 @@
|
||||
const std = @import("std");
|
||||
|
||||
fn noise2rangetest() void {
|
||||
const f0: u32 = @bitCast(@as(f32, 1));
|
||||
const f1: u32 = @bitCast(@as(f32, 10));
|
||||
const step: u32 = (f1 - f0) / 30000;
|
||||
|
||||
var max: f32 = -std.math.inf(f32);
|
||||
var timer = std.time.Timer.start() catch unreachable;
|
||||
|
||||
var y: u32 = f0;
|
||||
while (y <= f1) : (y += step) {
|
||||
const fy: f32 = @bitCast(@as(u32, @intCast(y)));
|
||||
|
||||
var x: u32 = f0;
|
||||
while (x <= f1) : (x += step) {
|
||||
const fx: f32 = @bitCast(@as(u32, @intCast(x)));
|
||||
|
||||
const noise = @import("noise.zig").noise2(.init(fx, fy));
|
||||
const noise_abs = @abs(noise);
|
||||
max = @max(noise_abs, max);
|
||||
|
||||
if (timer.read() > 1 * std.time.ns_per_s) {
|
||||
_ = timer.lap();
|
||||
const yp: f32 = @as(f32, @floatFromInt(y - f0)) / @as(f32, @floatFromInt(f1 - f0)) * 100.0;
|
||||
std.debug.print("[{d:.2}%] max: {d} | scale: {d}\n", .{ yp, max, 1 / max });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.print("max: {d} | scale: {d}\n", .{ max, 1 / max });
|
||||
}
|
||||
Reference in New Issue
Block a user