diff --git a/resources/images/tiles.png b/resources/images/tiles.png new file mode 100644 index 0000000..2198033 Binary files /dev/null and b/resources/images/tiles.png differ diff --git a/resources/images/tiles.png.kra b/resources/images/tiles.png.kra new file mode 100644 index 0000000..2a1c535 Binary files /dev/null and b/resources/images/tiles.png.kra differ diff --git a/resources/images/tiles.png~ b/resources/images/tiles.png~ new file mode 100644 index 0000000..6711326 Binary files /dev/null and b/resources/images/tiles.png~ differ diff --git a/resources/shaders/tiling.fs b/resources/shaders/tiling.fs new file mode 100644 index 0000000..a8ab20b --- /dev/null +++ b/resources/shaders/tiling.fs @@ -0,0 +1,16 @@ +#version 330 core + +uniform sampler2D diffuseMap; +uniform vec2 textureTiling; + +in vec2 fragTexCoord; +in vec2 fragTexCoord2; +in vec4 fragColor; + +out vec4 outColor; + +void main() +{ + vec2 texCoord = (floor(fragTexCoord*textureTiling) + fract(fragTexCoord2)) / textureTiling; + outColor = texture(diffuseMap, texCoord); +} diff --git a/resources/shaders/tiling.vs b/resources/shaders/tiling.vs new file mode 100644 index 0000000..d9a24bb --- /dev/null +++ b/resources/shaders/tiling.vs @@ -0,0 +1,19 @@ +#version 330 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec2 vertexTexCoord2; +in vec4 vertexColor; + +out vec2 fragTexCoord; +out vec2 fragTexCoord2; +out vec4 fragColor; + +uniform mat4 mvp; + +void main() { + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + fragTexCoord2 = vertexTexCoord2; + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/src/main.zig b/src/main.zig index 76bf7ac..4c1f3d1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4,8 +4,10 @@ const raylib = rh.raylib; const v3 = rh.v3; const chunks = @import("world/chunk.zig"); +const TILE_TEXTURE_RESOLUTION = 16; + const benchmark_chunk_meshing = false; -const debug = false; +const debug = true; pub fn drawCameraPosition(camera: raylib.Camera3D, x: i32, y: i32) !void { var buf: [256:0]u8 = undefined; @@ -51,32 +53,35 @@ pub fn main() !void { .projection = raylib.CAMERA_PERSPECTIVE, }; - const checked = raylib.GenImageChecked(2, 2, 1, 1, raylib.BLUE, raylib.GREEN); - const texture = raylib.LoadTextureFromImage(checked); + const tiles = raylib.LoadImage("resources/images/tiles.png"); + const texture = raylib.LoadTextureFromImage(tiles); + const tile_rows = @divExact(@as(u32, @intCast(tiles.height)), TILE_TEXTURE_RESOLUTION); + const tile_columns = @divExact(@as(u32, @intCast(tiles.width)), TILE_TEXTURE_RESOLUTION); defer raylib.UnloadTexture(texture); - raylib.UnloadImage(checked); + raylib.UnloadImage(tiles); + + const shader = raylib.LoadShader("resources/shaders/tiling.vs", "resources/shaders/tiling.fs"); + defer raylib.UnloadShader(shader); + raylib.SetShaderValue(shader, raylib.GetShaderLocation(shader, "textureTiling"), &.{ @as(f32, @floatFromInt(tile_columns)), @as(f32, @floatFromInt(tile_rows)) }, raylib.SHADER_UNIFORM_VEC2); var chunk = try chunks.Chunk.init(a7r); defer chunk.deinit(); - for (0..32) |raw_x| for (0..32) |raw_z| { + for (0..32) |raw_x| for (0..32) |raw_y| for (0..32) |raw_z| { const x: u5 = @intCast(raw_x); + const y: u5 = @intCast(raw_y); const z: u5 = @intCast(raw_z); - chunk.setTile(x, 0, z, 1); - chunk.setTile(x, 31, z, 1); + const xt: i32 = @as(i32, @intCast(x)) - 16; + const yt: i32 = @as(i32, @intCast(y)) - 16; + const zt: i32 = @as(i32, @intCast(z)) - 16; + if (xt * xt + yt * yt + zt * zt < 15 * 15) chunk.setTile(x, y, z, 1); }; - for (0..32) |raw_a| { - const a: u5 = @intCast(raw_a); - chunk.setTile(a, a, a, 1); - chunk.setTile(a, 31 - a, a, 1); - chunk.setTile(31 - a, a, a, 1); - chunk.setTile(31 - a, 31 - a, a, 1); - } + if (benchmark_chunk_meshing) { var tmp: u64 = 0; for (0..500) |_| { const start = try std.time.Instant.now(); - const model = raylib.LoadModelFromMesh(try chunk.createMesh()); + const model = raylib.LoadModelFromMesh(try chunk.createMesh(tile_rows, tile_columns)); defer raylib.UnloadModel(model); const end = try std.time.Instant.now(); tmp += end.since(start); @@ -86,10 +91,10 @@ pub fn main() !void { }); } - const model = raylib.LoadModelFromMesh(try chunk.createMesh()); + const model = raylib.LoadModelFromMesh(try chunk.createMesh(tile_rows, tile_columns)); defer raylib.UnloadModel(model); - model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE].texture = texture; + model.materials[0].shader = shader; while (!raylib.WindowShouldClose()) { raylib.ClearBackground(raylib.BLACK); @@ -122,6 +127,8 @@ pub fn main() !void { { raylib.BeginMode3D(camera); defer raylib.EndMode3D(); + raylib.BeginShaderMode(shader); + defer raylib.EndShaderMode(); raylib.DrawModel(model, model_position, 0.5, raylib.WHITE); } diff --git a/src/world/chunk.zig b/src/world/chunk.zig index 2e62236..aa3c9f5 100644 --- a/src/world/chunk.zig +++ b/src/world/chunk.zig @@ -54,7 +54,7 @@ pub const Chunk = struct { } } - pub fn createMesh(chunk: Chunk) !raylib.Mesh { + pub fn createMesh(chunk: Chunk, tile_rows: u32, tile_columns: u32) !raylib.Mesh { var raw_quads = try std.ArrayList(RawQuad).initCapacity(chunk.a7r, 4096); defer raw_quads.deinit(); @@ -78,14 +78,13 @@ pub const Chunk = struct { const surface = tile_surfaces[y][z]; if (surface == 0) continue; var y2 = y + 1; + var z2 = z + 1; while (y2 <= 31 and tile_surfaces[y2][z] == surface) : (y2 += 1) { tile_surfaces[y2][z] = 0; } - var z2 = z + 1; zloop: while (z2 <= 31) : (z2 += 1) { for (y..y2) |ytmp| if (tile_surfaces[ytmp][z2] != surface) break :zloop; for (y..y2) |ytmp| tile_surfaces[ytmp][z2] = 0; - tile_surfaces[y][z2] = 0; } y2 -= 1; z2 -= 1; @@ -118,50 +117,71 @@ 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 normals: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3))); for (raw_quads.items, 0..) |raw_quad, i| { + if (raw_quad.tile <= 0) continue; + const tile = @as(u32, @intCast(raw_quad.tile)); + for (0..6) |j| { normals[18 * i + 3 * j + 0] = raw_quad.normal.x; normals[18 * i + 3 * j + 1] = raw_quad.normal.y; normals[18 * i + 3 * j + 2] = raw_quad.normal.z; } + const left_uv = @as(f32, @floatFromInt(tile % tile_columns)) / @as(f32, @floatFromInt(tile_columns)); + const right_uv = @as(f32, @floatFromInt(tile % tile_columns + 1)) / @as(f32, @floatFromInt(tile_columns)); + const top_uv = @as(f32, @floatFromInt(tile / tile_columns)) / @as(f32, @floatFromInt(tile_rows)); + const bottom_uv = @as(f32, @floatFromInt(tile / tile_columns + 1)) / @as(f32, @floatFromInt(tile_rows)); + vertices[18 * i + 0] = raw_quad.top_left.x; vertices[18 * i + 1] = raw_quad.top_left.y; vertices[18 * i + 2] = raw_quad.top_left.z; - texcoords[12 * i + 0] = 0.0; - texcoords[12 * i + 1] = 0.0; + texcoords[12 * i + 0] = left_uv; + texcoords[12 * i + 1] = top_uv; + texcoords2[12 * i + 0] = 0.0; + texcoords2[12 * i + 1] = 0.0; vertices[18 * i + 3] = raw_quad.top_right.x; vertices[18 * i + 4] = raw_quad.top_right.y; vertices[18 * i + 5] = raw_quad.top_right.z; - texcoords[12 * i + 2] = raw_quad.width; - texcoords[12 * i + 3] = 0.0; + texcoords[12 * i + 2] = right_uv; + texcoords[12 * i + 3] = top_uv; + texcoords2[12 * i + 2] = raw_quad.width; + texcoords2[12 * i + 3] = 0.0; vertices[18 * i + 6] = raw_quad.bottom_left.x; vertices[18 * i + 7] = raw_quad.bottom_left.y; vertices[18 * i + 8] = raw_quad.bottom_left.z; - texcoords[12 * i + 4] = 0.0; - texcoords[12 * i + 5] = raw_quad.height; + texcoords[12 * i + 4] = left_uv; + texcoords[12 * i + 5] = bottom_uv; + texcoords2[12 * i + 4] = 0.0; + texcoords2[12 * i + 5] = raw_quad.height; vertices[18 * i + 9] = raw_quad.bottom_right.x; vertices[18 * i + 10] = raw_quad.bottom_right.y; vertices[18 * i + 11] = raw_quad.bottom_right.z; - texcoords[12 * i + 6] = raw_quad.width; - texcoords[12 * i + 7] = raw_quad.height; + texcoords[12 * i + 6] = right_uv; + texcoords[12 * i + 7] = bottom_uv; + texcoords2[12 * i + 6] = raw_quad.width; + texcoords2[12 * i + 7] = raw_quad.height; vertices[18 * i + 12] = raw_quad.bottom_left.x; vertices[18 * i + 13] = raw_quad.bottom_left.y; vertices[18 * i + 14] = raw_quad.bottom_left.z; - texcoords[12 * i + 8] = 0.0; - texcoords[12 * i + 9] = raw_quad.height; + texcoords[12 * i + 8] = left_uv; + texcoords[12 * i + 9] = bottom_uv; + texcoords2[12 * i + 8] = 0.0; + texcoords2[12 * i + 9] = raw_quad.height; vertices[18 * i + 15] = raw_quad.top_right.x; vertices[18 * i + 16] = raw_quad.top_right.y; vertices[18 * i + 17] = raw_quad.top_right.z; - texcoords[12 * i + 10] = raw_quad.width; - texcoords[12 * i + 11] = 0.0; + texcoords[12 * i + 10] = right_uv; + texcoords[12 * i + 11] = top_uv; + texcoords2[12 * i + 10] = raw_quad.width; + texcoords2[12 * i + 11] = 0.0; } var mesh = raylib.Mesh{ @@ -170,7 +190,7 @@ pub const Chunk = struct { .vertices = vertices, .texcoords = texcoords, - .texcoords2 = null, + .texcoords2 = texcoords2, .normals = normals, .tangents = null, .colors = null,