diff --git a/resources/images/ambient_occlusion.png b/resources/images/ambient_occlusion.png new file mode 100644 index 0000000..9b56dcf Binary files /dev/null and b/resources/images/ambient_occlusion.png differ diff --git a/resources/images/tiles.png b/resources/images/tiles.png index 9f807c7..4d91f61 100644 Binary files a/resources/images/tiles.png and b/resources/images/tiles.png differ diff --git a/resources/images/tiles.png~ b/resources/images/tiles.png~ index 8eafed8..9f807c7 100644 Binary files a/resources/images/tiles.png~ and b/resources/images/tiles.png~ differ diff --git a/resources/scripts/ambient_occlusion_texture_generator.py b/resources/scripts/ambient_occlusion_texture_generator.py new file mode 100644 index 0000000..8b9aa2c --- /dev/null +++ b/resources/scripts/ambient_occlusion_texture_generator.py @@ -0,0 +1,100 @@ +from PIL import Image, ImageFilter +import random +import math + +SQUARE_SIZE = 32 +SQUARES = 2**8 +ITERATIONS_PER_PIXEL = 1000 +COORDS = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)] + + +def random_point_on_sphere(): + theta = random.uniform(0, 2 * math.pi) + phi = math.acos(random.uniform(-1, 1)) + x = math.sin(phi) * math.cos(theta) + y = math.sin(phi) * math.sin(theta) + z = math.cos(phi) + return [x, y, z] + + +calculated_squares = dict() +with Image.new("RGBA", (SQUARE_SIZE*SQUARES, SQUARE_SIZE), "black") as im: + px = im.load() + + for square_id in range(SQUARES): + print(f"square {square_id}: ", end="") + square = square_id + + # if 2 side touching tiles are obscuring, then we can assume the corner is obscuring as well + if square & (1 << 6) > 0 and square & (1 << 4) > 0: + square = square | (1 << 5) + if square & (1 << 4) > 0 and square & (1 << 2) > 0: + square = square | (1 << 3) + if square & (1 << 2) > 0 and square & (1 << 0) > 0: + square = square | (1 << 1) + if square & (1 << 0) > 0 and square & (1 << 6) > 0: + square = square | (1 << 7) + + # check if we've already done the task in a rotated variation + instance_found = False + for rotation in range(4): # clockwise rotations by pi/2 + rotated_square = (square >> (rotation * 2)) | ((square & ((1 << rotation*2)-1)) << 2*(4 - rotation)) + if rotated_square in calculated_squares: + square_id_from = calculated_squares[rotated_square] + print(f"already calculated at {square_id_from}") + + box_from = (SQUARE_SIZE*square_id_from, 0, SQUARE_SIZE*(square_id_from+1), SQUARE_SIZE) + box_to = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE) + region = im.crop(box_from) + if rotation == 1: + region = region.transpose(Image.Transpose.ROTATE_270) + if rotation == 2: + region = region.transpose(Image.Transpose.ROTATE_180) + if rotation == 3: + region = region.transpose(Image.Transpose.ROTATE_90) + im.paste(region, box_to) + + instance_found = True + break + if instance_found: + continue + + # actually calculate the occlusion + obscured = [i for c, i in enumerate(COORDS) if (square >> c) & 1 == 1] + for x in range(SQUARE_SIZE): + for y in range(SQUARE_SIZE): + point_coord = ((x+0.5)/SQUARE_SIZE-0.5, (y+0.5)/SQUARE_SIZE-0.5, 0) + count = 0 + for i in range(ITERATIONS_PER_PIXEL): + point = random_point_on_sphere() + point[0] += point_coord[0] + point[1] += point_coord[1] + rounded_point = (round(point[0]), round(point[1])) + if rounded_point in obscured: + count += 1 + result_color = 255-255*count//ITERATIONS_PER_PIXEL + px[x+square_id*SQUARE_SIZE, y] = (result_color, result_color, result_color, 255) + calculated_squares[square] = square_id + + # smooth it + box = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE) + region = im.crop(box) + region = region.filter(filter=ImageFilter.GaussianBlur(2)) + im.paste(region, box) + + print(f"calculated") + + print(f"total squares calculated: {len(calculated_squares)}") + + # result_side_length = int(SQUARES**0.5) + # with Image.new("RGBA", (SQUARE_SIZE*result_side_length, SQUARE_SIZE*result_side_length), "black") as new_im: + # for i in range(result_side_length): + # box_from = (SQUARE_SIZE*result_side_length*i, 0, SQUARE_SIZE*result_side_length*(i+1), SQUARE_SIZE) + # box_to = (0, SQUARE_SIZE*i, SQUARE_SIZE*result_side_length, SQUARE_SIZE*(i+1)) + # new_im.paste(im.crop(box_from), box_to) + # new_im.show() + # new_im.save("../images/ambient_occlusion.png") + + im.show() + im.save("../images/ambient_occlusion.png") + diff --git a/resources/shaders/tiling.fs b/resources/shaders/tiling.fs index 8da9038..7430751 100644 --- a/resources/shaders/tiling.fs +++ b/resources/shaders/tiling.fs @@ -1,6 +1,7 @@ #version 330 core uniform sampler2D diffuseMap; +uniform sampler2D occlusionMap; uniform vec2 textureTiling; in vec2 fragTexCoord; @@ -17,30 +18,52 @@ flat in int quadWidth; out vec4 outColor; -// this is a shitty approximation of arcsin(x)/pi that gets the tails right and is reasonably close to the actual arcsin(x)/pi curve. -float fakeArcsin(float x) { - x = clamp(x, -1.0, 1.0); - float ax = abs(x); - float sqrtPart = sqrt(1.0 - ax); - float result = 0.5 - sqrtPart * (0.5 - 0.06667 * ax); - return x < 0.0 ? -result : result; +int calculate_ao_square() +{ + ivec2 tileCoord = ivec2(fragTileTexCoord); + int ao_square = 0; + + if(tileCoord.x == quadWidth - 1 && ((occlusionSides.x & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 0; + + if(tileCoord.x == quadWidth - 1 && tileCoord.y == quadHeight - 1 && bottomRightObscured > 0) ao_square |= 1 << 1; + if(tileCoord.x == quadWidth - 1 && tileCoord.y != quadHeight - 1 && ((occlusionSides.x & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 1; + if(tileCoord.x != quadWidth - 1 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 1; + + if(tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 2; + + if(tileCoord.x == 0 && tileCoord.y == quadHeight - 1 && bottomLeftObscured > 0) ao_square |= 1 << 3; + if(tileCoord.x == 0 && tileCoord.y != quadHeight - 1 && ((occlusionSides.y & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 3; + if(tileCoord.x != 0 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 3; + + if(tileCoord.x == 0 && ((occlusionSides.y & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 4; + + if(tileCoord.x == 0 && tileCoord.y == 0 && topRightObscured > 0) ao_square |= 1 << 5; + if(tileCoord.x == 0 && tileCoord.y != 0 && ((occlusionSides.y & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 5; + if(tileCoord.x != 0 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 5; + + if(tileCoord.y == 0 && ((occlusionSides.z & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 6; + + if(tileCoord.x == quadWidth - 1 && tileCoord.y == 0 && topLeftObscured > 0) ao_square |= 1 << 7; + if(tileCoord.x == quadWidth - 1 && tileCoord.y != 0 && ((occlusionSides.x & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 7; + if(tileCoord.x != quadWidth - 1 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 7; + + return ao_square; } void main() { vec2 texCoord = (floor(fragTexCoord*textureTiling) + fract(fragTileTexCoord)) / textureTiling; + + int ao_square = calculate_ao_square(); + outColor = texture(diffuseMap, texCoord); - - ivec2 floorFragTileTexCoord = ivec2(fragTileTexCoord); - - if(floorFragTileTexCoord.x < 1 && ((occlusionSides.x >> floorFragTileTexCoord.x) & uint(1)) == uint(1)) { - outColor *= 0.5 + fakeArcsin(fragTileTexCoord.x); - } + outColor *= texture(occlusionMap, (vec2(ao_square, 0)+fract(fragTileTexCoord))/vec2(256, 1)); outColor.a = 1; - uint bit = uint(fragTileTexCoord * 32); - outColor.g = (((occlusionSides.x >> bit) & uint(1)) == uint(1)) ? - ((bit % uint(2) == uint(0)) ? 1.0 : 0.8): - ((bit % uint(2) == uint(0)) ? 0.0 : 0.2); + //uint bit = uint(fragTileTexCoord * 32); + //outColor.g = (((uint(quadWidth) >> bit) & uint(1)) == uint(1)) ? + // ((bit % uint(2) == uint(0)) ? 1.0 : 0.8): + // ((bit % uint(2) == uint(0)) ? 0.0 : 0.2); } + diff --git a/resources/shaders/tiling.vs b/resources/shaders/tiling.vs index 0efd713..5fa028f 100644 --- a/resources/shaders/tiling.vs +++ b/resources/shaders/tiling.vs @@ -29,7 +29,7 @@ void main() { gl_Position = mvp*vec4(vertexPosition, 1.0); // metadata 1 parsing - int metadata1W = int(vertexMetadata1.w); + int metadata1W = int(vertexMetadata1.x); topLeftObscured = (metadata1W & 0x1); // Take 0th bit. topRightObscured = (metadata1W & 0x2) >> 1; // Take 1st bits. bottomLeftObscured = (metadata1W & 0x4) >> 2; // Take 2nd bits. diff --git a/src/lib_helpers/raylib_helper.zig b/src/lib_helpers/raylib_helper.zig index 8ad5c5f..c30455f 100644 --- a/src/lib_helpers/raylib_helper.zig +++ b/src/lib_helpers/raylib_helper.zig @@ -33,6 +33,9 @@ pub const v3 = struct { pub inline fn nor(a: raylib.Vector3) raylib.Vector3 { return raylib.Vector3Normalize(a); } + pub inline fn dot(a: raylib.Vector3, b: raylib.Vector3) f32 { + return raylib.Vector3DotProduct(a, b); + } pub inline fn cross(a: raylib.Vector3, b: raylib.Vector3) raylib.Vector3 { return raylib.Vector3CrossProduct(a, b); } diff --git a/src/main.zig b/src/main.zig index 985c06f..a8c6a75 100644 --- a/src/main.zig +++ b/src/main.zig @@ -64,11 +64,13 @@ pub fn main() !void { defer raylib.UnloadTexture(texture); raylib.UnloadImage(tiles); + const ambient_occlusion_image = raylib.LoadImage("resources/images/ambient_occlusion.png"); + const ambient_occlusion_texture = raylib.LoadTextureFromImage(ambient_occlusion_image); + defer raylib.UnloadTexture(ambient_occlusion_texture); + raylib.UnloadImage(ambient_occlusion_image); + const shader = raylib.LoadChunkShader("resources/shaders/tiling.vs", "resources/shaders/tiling.fs"); defer raylib.UnloadShader(shader); - //for (0..32) |i|{ - // std.debug.print("shader loc {}: {}\n", .{i, shader.locs[i]}); - //} 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); @@ -83,7 +85,7 @@ pub fn main() !void { const xf: f32 = @floatFromInt(raw_x); const yf: f32 = @floatFromInt(raw_y); const zf: f32 = @floatFromInt(raw_z); - const tile_type: u32 = if (tile_type_generator.noise3(xf, yf, zf) > 0) 1 else 2; + const tile_type: u32 = if (tile_type_generator.noise3(xf, yf, zf) > 0) 2 else 2; // const height: f32 = (height_generator.noise2(xf, zf) + 1) * 16 + @as(f32, if(x > 24) 4.0 else 0.0) + @as(f32, if(z < 8) 4.0 else 0.0); // if (height >= yf) chunk.setTile(x, y, z, tile_type); if((xf-16)*(xf-16)+(yf-16)*(yf-16)+(zf-16)*(zf-16) < 16*16) chunk.setTile(x, y, z, tile_type); @@ -108,6 +110,13 @@ pub fn main() !void { model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE].texture = texture; model.materials[0].shader = shader; + model.materials[0].shader.locs[raylib.SHADER_LOC_MAP_DIFFUSE+1] = raylib.GetShaderLocation(shader, "occlusionMap"); + raylib.SetShaderValueTexture(shader, model.materials[0].shader.locs[raylib.SHADER_LOC_MAP_DIFFUSE+1], ambient_occlusion_texture); model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE+1].texture = ambient_occlusion_texture; + + // for (0..32) |i|{ + // std.debug.print("shader loc {}: {}\n", .{i, shader.locs[i]}); + // } + while (!raylib.WindowShouldClose()) { raylib.ClearBackground(raylib.BLACK); @@ -128,10 +137,17 @@ pub fn main() !void { moveCamera(&camera, v3.scl(v3.nor(movement), speed)); const delta = raylib.GetMouseDelta(); - // on the first mouse movement, for some reason mouse delta is completely insane, so we just ignore too large deltas + // on the first mouse movement, for some reason mouse delta is way too large, so we just ignore too large deltas if(delta.x < 1000 and delta.y < 1000 and delta.x > -1000 and delta.y > -1000){ - camera.target = v3.add(camera.position, v3.rotate(v3.sub(camera.target, camera.position), camera.up, -0.005 * delta.x)); - camera.target = v3.add(camera.position, v3.rotate(v3.sub(camera.target, camera.position), right, -0.005 * delta.y)); + var direction = v3.sub(camera.target, camera.position); + direction = v3.rotate(direction, camera.up, -0.005 * delta.x); + const tmp_direction = direction; + direction = v3.rotate(direction, right, -0.005 * delta.y); + if(tmp_direction.x*direction.x+tmp_direction.z*direction.z > 0){ + camera.target = v3.add(camera.position, direction); + } else { + camera.target = v3.add(camera.position, tmp_direction); + } } raylib.BeginDrawing(); @@ -145,6 +161,7 @@ pub fn main() !void { raylib.BeginShaderMode(shader); defer raylib.EndShaderMode(); + raylib.SetShaderValueTexture(shader, raylib.GetShaderLocation(shader, "ambientOcclusionTexture"), ambient_occlusion_texture); raylib.DrawChunkModel(model, model_position, 0.5, raylib.WHITE); } diff --git a/src/world/chunk.zig b/src/world/chunk.zig index 6bb0613..e57c88b 100644 --- a/src/world/chunk.zig +++ b/src/world/chunk.zig @@ -21,6 +21,8 @@ const RawQuad = struct { normal: raylib.Vector3, width: f32, height: f32, + flip_x: bool, + flip_y: bool, top_obscuring_pattern: u32, left_obscuring_pattern: u32, @@ -85,12 +87,12 @@ pub const Chunk = struct { } // This cyclically permutes the x, y, z coordinates at compile time. Useful when iterating over x, y, and z axis. - inline fn getTileRawShifted(self: Chunk, x: u5, y: u5, z: u5, comptime dimention: comptime_int) u32 { - if (dimention % 3 == 0) { + inline fn getTileRawShifted(self: Chunk, x: u5, y: u5, z: u5, comptime dimension: comptime_int) u32 { + if (dimension % 3 == 0) { return self.getTileRaw(x, y, z); - } else if (dimention % 3 == 1) { + } else if (dimension % 3 == 1) { return self.getTileRaw(y, z, x); - } else if (dimention % 3 == 2) { + } else if (dimension % 3 == 2) { return self.getTileRaw(z, x, y); } } @@ -101,12 +103,16 @@ pub const Chunk = struct { y_start: usize, y_end: usize, z_start: usize, z_end: usize, sign: comptime_int, - dimention: comptime_int, + dimension: comptime_int, surface: u32, y_minus_obscuring_pattern: u32, y_plus_obscuring_pattern: u32, z_minus_obscuring_pattern: u32, z_plus_obscuring_pattern: u32, + y_minus_z_minus_obscured: bool, + y_minus_z_plus_obscured: bool, + y_plus_z_plus_obscured: bool, + y_plus_z_minus_obscured: bool, ) RawQuad { const ymin: f32 = @as(f32, @floatFromInt(y_start)) - 0.5; const ymax: f32 = @as(f32, @floatFromInt(y_end)) - 0.5; @@ -117,16 +123,8 @@ pub const Chunk = struct { const zleft: f32 = if (sign == 1) zmin else zmax; const zright: f32 = if (sign == 1) zmax else zmin; - if(dimention == 0 and z_minus_obscuring_pattern == 0b10000){ - std.debug.print("z_minus_obscuring_pattern {b}\n", .{z_minus_obscuring_pattern}); - std.debug.print("dimension {}\n", .{dimention}); - std.debug.print("x {}\n", .{x}); - std.debug.print("y {}-{}\n", .{y_start, y_end}); - std.debug.print("z {}-{}\n", .{z_start, z_end}); - } - var raw_quad: RawQuad = undefined; - switch (dimention) { + switch (dimension) { X_DIRECTION => { raw_quad = .{ .tile = surface, @@ -137,15 +135,17 @@ pub const Chunk = struct { .normal = v3.new(sign, 0, 0), .width = zmax - zmin, .height = ymax - ymin, + .flip_x = sign == -1, + .flip_y = false, - .top_obscuring_pattern = z_plus_obscuring_pattern, + .top_obscuring_pattern = y_plus_obscuring_pattern, .left_obscuring_pattern = z_minus_obscuring_pattern, - .right_obscuring_pattern = y_plus_obscuring_pattern, + .right_obscuring_pattern = z_plus_obscuring_pattern, .bottom_obscuring_pattern = y_minus_obscuring_pattern, - .top_left_obscured = false, - .top_right_obscured = false, - .bottom_right_obscured = false, - .bottom_left_obscured = false, + .top_left_obscured = y_plus_z_minus_obscured, + .top_right_obscured = y_plus_z_plus_obscured, + .bottom_right_obscured = y_minus_z_plus_obscured, + .bottom_left_obscured = y_minus_z_minus_obscured, }; }, Y_DIRECTION => { @@ -158,15 +158,17 @@ pub const Chunk = struct { .normal = v3.new(0, 0, sign), .height = zmax - zmin, .width = ymax - ymin, + .flip_x = sign == 1, + .flip_y = false, - .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, - .bottom_left_obscured = false, + .top_obscuring_pattern = z_plus_obscuring_pattern, + .left_obscuring_pattern = y_minus_obscuring_pattern, + .right_obscuring_pattern = y_plus_obscuring_pattern, + .bottom_obscuring_pattern = z_minus_obscuring_pattern, + .top_left_obscured = y_minus_z_plus_obscured, + .top_right_obscured = y_plus_z_plus_obscured, + .bottom_right_obscured = y_plus_z_minus_obscured, + .bottom_left_obscured = y_minus_z_minus_obscured, }; }, Z_DIRECTION => { @@ -179,15 +181,17 @@ pub const Chunk = struct { .normal = v3.new(0, sign, 0), .width = zmax - zmin, .height = ymax - ymin, + .flip_x = sign == 1, + .flip_y = true, - .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, - .bottom_left_obscured = false, + .top_obscuring_pattern = y_plus_obscuring_pattern, + .left_obscuring_pattern = z_minus_obscuring_pattern, + .right_obscuring_pattern = z_plus_obscuring_pattern, + .bottom_obscuring_pattern = y_minus_obscuring_pattern, + .top_left_obscured = y_plus_z_minus_obscured, + .top_right_obscured = y_plus_z_plus_obscured, + .bottom_right_obscured = y_minus_z_plus_obscured, + .bottom_left_obscured = y_minus_z_minus_obscured, }; }, else => unreachable, @@ -201,7 +205,7 @@ pub const Chunk = struct { defer raw_quads.deinit(); // Begin scanning the chunk for tile surfaces to make raw quads. - inline for (0..3) |dimention| { // Iterate over the 3 dimensions, X, Y and Z. + inline for (0..3) |dimension| { // Iterate over the 3 dimensions, X, Y and Z. for (0..32) |raw_x| { const x: u5 = @intCast(raw_x); // Create surface arrays for the +x side of the layer and the -x side. @@ -210,11 +214,11 @@ pub const Chunk = struct { for (0..32) |raw_y| for (0..32) |raw_z| { const y: u5 = @intCast(raw_y); const z: u5 = @intCast(raw_z); - const tile: u32 = chunk.getTileRawShifted(x, y, z, dimention); + const tile: u32 = chunk.getTileRawShifted(x, y, z, dimension); if (tile == 0) continue; // If air, there is no surface. // If either at the edge of the chunk or the tile is exposed, create a tile surface. - if (x == 31 or chunk.getTileRawShifted(x + 1, y, z, dimention) == 0) positive_tile_surfaces[y][z] = tile; - if (x == 0 or chunk.getTileRawShifted(x - 1, y, z, dimention) == 0) negative_tile_surfaces[y][z] = tile; + if (x == 31 or chunk.getTileRawShifted(x + 1, y, z, dimension) == 0) positive_tile_surfaces[y][z] = tile; + if (x == 0 or chunk.getTileRawShifted(x - 1, y, z, dimension) == 0) negative_tile_surfaces[y][z] = tile; }; inline for (.{ -1, 1 }) |sign| { var tile_surfaces = if (sign == 1) positive_tile_surfaces else negative_tile_surfaces; @@ -241,7 +245,7 @@ pub const Chunk = struct { 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), dimention) != 0) z_minus_obscuring_pattern |= 1; + if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, y, @intCast(z_start - 1), dimension) != 0) z_minus_obscuring_pattern |= 1; } } var z_plus_obscuring_pattern: u32 = 0; @@ -249,7 +253,7 @@ pub const Chunk = struct { 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), dimention) != 0) z_plus_obscuring_pattern |= 1; + if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, y, @intCast(z_end), dimension) != 0) z_plus_obscuring_pattern |= 1; } } var y_minus_obscuring_pattern: u32 = 0; @@ -257,7 +261,7 @@ pub const Chunk = struct { 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, dimention) != 0) y_minus_obscuring_pattern |= 1; + if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start - 1), z, dimension) != 0) y_minus_obscuring_pattern |= 1; } } var y_plus_obscuring_pattern: u32 = 0; @@ -265,11 +269,22 @@ pub const Chunk = struct { 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, dimention) != 0) y_plus_obscuring_pattern |= 1; + if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), z, dimension) != 0) y_plus_obscuring_pattern |= 1; } } - // std.debug.print("{}\n", .{z_minus_obscuring_pattern}); - const raw_quad = packRawQuad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, dimention, surface, y_minus_obscuring_pattern, y_plus_obscuring_pattern, z_minus_obscuring_pattern, z_plus_obscuring_pattern); + var y_minus_z_minus_obscured = false; + var y_minus_z_plus_obscured = false; + var y_plus_z_plus_obscured = false; + var y_plus_z_minus_obscured = false; + if(x != (if (sign == 1) 31 else 0) and y_start != 0 and z_start != 0) + y_minus_z_minus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start-1), @intCast(z_start-1), dimension) != 0; + if(x != (if (sign == 1) 31 else 0) and y_start != 0 and z_end != 32) + y_minus_z_plus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start-1), @intCast(z_end), dimension) != 0; + if(x != (if (sign == 1) 31 else 0) and y_end != 32 and z_end != 32) + y_plus_z_plus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), @intCast(z_end), dimension) != 0; + if(x != (if (sign == 1) 31 else 0) and y_end != 32 and z_start != 0) + y_plus_z_minus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), @intCast(z_start-1), dimension) != 0; + const raw_quad = packRawQuad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, dimension, surface, y_minus_obscuring_pattern, y_plus_obscuring_pattern, z_minus_obscuring_pattern, z_plus_obscuring_pattern, y_minus_z_minus_obscured, y_minus_z_plus_obscured, y_plus_z_plus_obscured, y_plus_z_minus_obscured); try raw_quads.append(raw_quad); }; } @@ -309,8 +324,10 @@ 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 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; + const tiletexcoords_x = if(raw_quad.flip_x) + .{raw_quad.width, raw_quad.width, 0.0, 0.0, 0.0, raw_quad.width} else + .{ 0.0, 0.0, raw_quad.width, raw_quad.width, raw_quad.width, 0.0 }; + const tiletexcoords_y = if(raw_quad.flip_y) .{ raw_quad.height, 0.0 } ** 3 else .{ 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; @@ -332,9 +349,9 @@ pub const Chunk = struct { .quad_height = @intFromFloat(raw_quad.height), .quad_width = @intFromFloat(raw_quad.width), }; - const metadata1_baked: [4]f32 = @bitCast(metadata1); + const metadata1_baked: [4]u32 = @bitCast(metadata1); for (0..4) |k| { - metadata1_packed[24 * i + 4 * j + k] = @bitCast(@as(f32, metadata1_baked[k])); + metadata1_packed[24 * i + 4 * j + k] = metadata1_baked[k]; } }