implement custom chunk meshes, models and shaders.
This commit is contained in:
parent
e4d536bc87
commit
e805891885
7 changed files with 800 additions and 57 deletions
|
|
@ -4,7 +4,6 @@ const raylib = raylib_helper.raylib;
|
|||
const v3 = raylib_helper.v3;
|
||||
const A7r = std.mem.Allocator;
|
||||
const comptimePrint = std.fmt.comptimePrint;
|
||||
|
||||
const VERTICES_BLOCK_SIZE = 2 * 3 * 3;
|
||||
const TEXCOORDS_BLOCK_SIZE = 2 * 2 * 3;
|
||||
|
||||
|
|
@ -43,7 +42,7 @@ const Metadata1 = packed struct {
|
|||
|
||||
comptime {
|
||||
if (@bitSizeOf(Metadata1) != 128) {
|
||||
@compileError(comptimePrint("Metadata 1 has wrong size. Expected 128 bits, found {}", .{@bitSizeOf(Metadata1)}));
|
||||
@compileError(comptimePrint("Metadata 1 has wrong size. Expected 128 bytes, found {}", .{@bitSizeOf(Metadata1)}));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +90,18 @@ pub const Chunk = struct {
|
|||
}
|
||||
|
||||
// Create a raw quad with specified parameters and surface, accounting for dimension and sign. Surface is the block ID.
|
||||
fn pack_raw_quad(x: f32, y_start: usize, y_end: usize, z_start: usize, z_end: usize, sign: comptime_int, d: comptime_int, surface: u32) RawQuad {
|
||||
fn pack_raw_quad(
|
||||
x: f32,
|
||||
y_start: usize, y_end: usize,
|
||||
z_start: usize, z_end: usize,
|
||||
sign: comptime_int,
|
||||
d: comptime_int,
|
||||
surface: u32,
|
||||
y_minus_obscuring_pattern: u32,
|
||||
y_plus_obscuring_pattern: u32,
|
||||
z_minus_obscuring_pattern: u32,
|
||||
z_plus_obscuring_pattern: u32,
|
||||
) RawQuad {
|
||||
const ymin: f32 = @as(f32, @floatFromInt(y_start)) - 0.5;
|
||||
const ymax: f32 = @as(f32, @floatFromInt(y_end)) - 0.5;
|
||||
const zmin: f32 = @as(f32, @floatFromInt(z_start)) - 0.5;
|
||||
|
|
@ -113,10 +123,10 @@ pub const Chunk = struct {
|
|||
.width = zmax - zmin,
|
||||
.height = ymax - ymin,
|
||||
|
||||
.top_obscuring_pattern = 0,
|
||||
.left_obscuring_pattern = 0,
|
||||
.right_obscuring_pattern = 0,
|
||||
.bottom_obscuring_pattern = 0,
|
||||
.top_obscuring_pattern = z_plus_obscuring_pattern,
|
||||
.left_obscuring_pattern = z_minus_obscuring_pattern,
|
||||
.right_obscuring_pattern = y_plus_obscuring_pattern,
|
||||
.bottom_obscuring_pattern = y_minus_obscuring_pattern,
|
||||
.top_left_obscured = false,
|
||||
.top_right_obscured = false,
|
||||
.bottom_right_obscured = false,
|
||||
|
|
@ -155,10 +165,10 @@ pub const Chunk = struct {
|
|||
.width = zmax - zmin,
|
||||
.height = ymax - ymin,
|
||||
|
||||
.top_obscuring_pattern = 0xffffffff,
|
||||
.left_obscuring_pattern = 0xffffffff,
|
||||
.right_obscuring_pattern = 0xffffffff,
|
||||
.bottom_obscuring_pattern = 0xffffffff,
|
||||
.top_obscuring_pattern = 0,
|
||||
.left_obscuring_pattern = 0,
|
||||
.right_obscuring_pattern = 0,
|
||||
.bottom_obscuring_pattern = 0,
|
||||
.top_left_obscured = false,
|
||||
.top_right_obscured = false,
|
||||
.bottom_right_obscured = false,
|
||||
|
|
@ -171,7 +181,7 @@ pub const Chunk = struct {
|
|||
}
|
||||
|
||||
// Create mesh of a chunk. tile_rows and tile_columns are the dimensions of the tiles.png file, in terms of individual tile textures.
|
||||
pub fn createMesh(chunk: Chunk, tile_rows: u32, tile_columns: u32) !raylib.Mesh {
|
||||
pub fn createMesh(chunk: Chunk, tile_rows: u32, tile_columns: u32) !raylib.ChunkMesh {
|
||||
var raw_quads = try std.ArrayList(RawQuad).initCapacity(chunk.a7r, 4096);
|
||||
defer raw_quads.deinit();
|
||||
|
||||
|
|
@ -200,6 +210,7 @@ pub const Chunk = struct {
|
|||
// The end coordinates of the quad. The quad is therefore covers rectangle from start coordinates (inclusive) to end coordinates (exclusive).
|
||||
var y_end = y_start + 1;
|
||||
var z_end = z_start + 1;
|
||||
// todo: meshing can be optimized with SIMD stuff!!
|
||||
// Greedy meshing: Extend the quad in the +y direction, until we hit a tile of a different type or the end of the chunk.
|
||||
while (y_end <= 31 and tile_surfaces[y_end][z_start] == surface) : (y_end += 1) {
|
||||
tile_surfaces[y_end][z_start] = 0;
|
||||
|
|
@ -209,8 +220,41 @@ pub const Chunk = struct {
|
|||
for (y_start..y_end) |y| if (tile_surfaces[y][z_end] != surface) break :zloop; // Stop extending if we hit a tile of incorrect type.
|
||||
for (y_start..y_end) |y| tile_surfaces[y][z_end] = 0;
|
||||
}
|
||||
// todo: scan tiles around quad surface for ambient occlusion
|
||||
const raw_quad = pack_raw_quad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, d, surface);
|
||||
// Scan the line of tiles adjacent to the quad for ambient occlusion
|
||||
var z_minus_obscuring_pattern: u32 = 0;
|
||||
if (x != (if (sign == 1) 31 else 0) and z_start != 0) {
|
||||
for (y_start..y_end) |raw_y| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
z_minus_obscuring_pattern <<= 1;
|
||||
if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, y, @intCast(z_start - 1), d) != 0) z_minus_obscuring_pattern |= 1;
|
||||
}
|
||||
}
|
||||
var z_plus_obscuring_pattern: u32 = 0;
|
||||
if (x != (if (sign == 1) 31 else 0) and z_end != 32) {
|
||||
for (y_start..y_end) |raw_y| {
|
||||
const y: u5 = @intCast(raw_y);
|
||||
z_plus_obscuring_pattern <<= 1;
|
||||
if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, y, @intCast(z_end), d) != 0) z_plus_obscuring_pattern |= 1;
|
||||
}
|
||||
}
|
||||
var y_minus_obscuring_pattern: u32 = 0;
|
||||
if (x != (if (sign == 1) 31 else 0) and y_start != 0) {
|
||||
for (z_start..z_end) |raw_z| {
|
||||
const z: u5 = @intCast(raw_z);
|
||||
y_minus_obscuring_pattern <<= 1;
|
||||
if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start - 1), z, d) != 0) y_minus_obscuring_pattern |= 1;
|
||||
}
|
||||
}
|
||||
var y_plus_obscuring_pattern: u32 = 0;
|
||||
if (x != (if (sign == 1) 31 else 0) and y_end != 32) {
|
||||
for (z_start..z_end) |raw_z| {
|
||||
const z: u5 = @intCast(raw_z);
|
||||
y_plus_obscuring_pattern <<= 1;
|
||||
if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), z, d) != 0) y_plus_obscuring_pattern |= 1;
|
||||
}
|
||||
}
|
||||
// std.debug.print("{}\n", .{z_minus_obscuring_pattern});
|
||||
const raw_quad = pack_raw_quad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, d, surface, y_minus_obscuring_pattern, y_plus_obscuring_pattern, z_minus_obscuring_pattern, z_plus_obscuring_pattern);
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
}
|
||||
|
|
@ -224,7 +268,7 @@ pub const Chunk = struct {
|
|||
|
||||
const vertices: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3)));
|
||||
const texcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
||||
const texcoords2: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
||||
const tiletexcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
||||
const normals: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3)));
|
||||
const metadata1_packed: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 4)));
|
||||
|
||||
|
|
@ -249,8 +293,8 @@ pub const Chunk = struct {
|
|||
const vertex_corners = .{ raw_quad.top_left, raw_quad.bottom_left, raw_quad.top_right, raw_quad.bottom_right, raw_quad.top_right, raw_quad.bottom_left };
|
||||
const texcoords_x = .{ left_uv, left_uv, right_uv, right_uv, right_uv, left_uv };
|
||||
const texcoords_y = .{ top_uv, bottom_uv } ** 3;
|
||||
const texcoords2_x = .{ 0.0, 0.0, raw_quad.width, raw_quad.width, raw_quad.width, 0.0 };
|
||||
const texcoords2_y = .{ 0.0, raw_quad.height } ** 3;
|
||||
const tiletexcoords_x = .{ 0.0, 0.0, raw_quad.width, raw_quad.width, raw_quad.width, 0.0 };
|
||||
const tiletexcoords_y = .{ 0.0, raw_quad.height } ** 3;
|
||||
|
||||
inline for (0..6) |corner_id| {
|
||||
vertices[VERTICES_BLOCK_SIZE * i + corner_id * 3 + 0] = vertex_corners[corner_id].x;
|
||||
|
|
@ -258,8 +302,8 @@ pub const Chunk = struct {
|
|||
vertices[VERTICES_BLOCK_SIZE * i + corner_id * 3 + 2] = vertex_corners[corner_id].z;
|
||||
texcoords[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 0] = texcoords_x[corner_id];
|
||||
texcoords[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 1] = texcoords_y[corner_id];
|
||||
texcoords2[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 0] = texcoords2_x[corner_id];
|
||||
texcoords2[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 1] = texcoords2_y[corner_id];
|
||||
tiletexcoords[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 0] = tiletexcoords_x[corner_id];
|
||||
tiletexcoords[TEXCOORDS_BLOCK_SIZE * i + corner_id * 2 + 1] = tiletexcoords_y[corner_id];
|
||||
}
|
||||
|
||||
// Store metadata into OpenGL buffers.
|
||||
|
|
@ -296,21 +340,21 @@ pub const Chunk = struct {
|
|||
}
|
||||
|
||||
// Create mesh using the buffers.
|
||||
var mesh = raylib.Mesh{
|
||||
var mesh = raylib.ChunkMesh{
|
||||
.triangleCount = triangle_count,
|
||||
.vertexCount = triangle_count * 3,
|
||||
|
||||
.vertices = vertices,
|
||||
.texcoords = texcoords,
|
||||
.texcoords2 = texcoords2,
|
||||
.tiletexcoords = tiletexcoords,
|
||||
.normals = normals,
|
||||
.tangents = metadata1_packed,
|
||||
.metadata1 = metadata1_packed,
|
||||
|
||||
.vaoId = 0,
|
||||
.vboId = null,
|
||||
};
|
||||
|
||||
raylib.UploadMesh(@ptrCast(&mesh), false);
|
||||
raylib.UploadChunkMesh(@ptrCast(&mesh), false);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue