From 7cb6dbc3e62fb9d1f26f5db46c0280fb0a8f5317 Mon Sep 17 00:00:00 2001 From: Sven Balzer <4653051+Kyuusokuna@users.noreply.github.com> Date: Fri, 1 May 2026 19:15:03 +0200 Subject: [PATCH] remove rotation from world tiles and instead apply it on load into atlas --- assets/maps/map.sv | Bin 3340 -> 1676 bytes src/main.cpp | 258 +++++++++++++++++++---------------------- src/shaders/world.wgsl | 16 +-- 3 files changed, 125 insertions(+), 149 deletions(-) diff --git a/assets/maps/map.sv b/assets/maps/map.sv index 17251b7e539b7dc10ee4405f59a07818ba5fba08..47cc6c26eca1694d148d1bb691d9d2bf61b6d0ac 100644 GIT binary patch literal 1676 zcmdUvZBN2L5QHafN-<&y_`wKjNEFfk{|A}9?RM^JNt6&G-P{Xz^K|$2wp0K%Y&$lf z!+jcWziZL{=@6#AE0`L;F*%W1YnXh8_WuWy$CJ+^I<4tETB|ihMQhj&tfSn%QXV8M z86z6j-W)SFGaDCVDk1!(#|dX#?W8g9k`+wFokvFX*1z9~8E^avORibHwAkXKU>dBc zF`IMOV=H^37MVvdW@Dtv=e|0{bcu28l&2}?6AvSMPNy(!*f=)JoLdCl_1c&8t`%0; z7dh}7^?uA)zT?r%auAemF#KGSX;?RIhX{jp{A?0xN=pR1emV=N;R?8L3= zowI0weTE}`1twl(Z#l@7F!wV0U;?NGtyAUUJ}ZG;c~G}JEtfcG6VDdS;DCqc;-0D2 zYVGn72Q_5qjl{?fYb<>+;4TVFQ5BCn|daevjY+MId#JDYw{-5#a zeINV=JUtiJ2kG*8T^_u(e2+5Y`h*_Lrw>=wO-%Lw(%8y-!`rg6$JN}Dz}Uw$@0oL^ tpFQE7J-}moXwW~F>Owxx;BoU|We=MA-PwMc5AU*rtiles = (Uint32*)malloc(result->size.x * result->size.y * sizeof(Uint32)); for (int i = 0; i < result->size.x * result->size.y; i++) { - Uint32 tile = 0; - if (!SDL_ReadU32LE(file, &tile)) { - free(result->tiles); - return false; - } - - Uint32 type = tile & 0xffff; - Uint32 orientation = tile & 0x30000; - - Uint32 kind = 0; - for (int i = 0; i < SDL_arraysize(tile_infos); i++) { - if (tile_infos[i].type == type) { - kind = i; - break; + if (result->version == 2) { + Uint16 serialization_id = 0; + if (!SDL_ReadU16LE(file, &serialization_id)) { + free(result->tiles); + return false; } - } - result->tiles[i] = orientation | kind; + Uint16 info_index = 0; + for (int i = 0; i < SDL_arraysize(tile_infos); i++) { + if (tile_infos[i].serialization_id == serialization_id) { + info_index = i; + break; + } + } + + result->tiles[i] = info_index; + } else { + assert(false && "Tried to load an unsupported map version."); + log_error("Tried to load an unsupported map version. Aborting."); + free(result->tiles); + return 1; + } } char buffer_name[256] = "Map "; SDL_strlcat(buffer_name, result->name, SDL_arraysize(buffer_name)); - result->gpu_buffer = create_buffer(WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, result->size.x * result->size.y * 4, result->tiles, buffer_name); + result->gpu_buffer = create_buffer(WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, result->size.x * result->size.y * sizeof(Uint32), result->tiles, buffer_name); if (!result->gpu_buffer) { log_error("Failed to create buffer. Exiting."); return 1; @@ -533,7 +585,7 @@ static void change_map_size(Map *map, char direction, int amount) { to_fill_y_offset = old_map_height; } - map->tiles = (Uint32*)malloc(map->size.x * map->size.y * sizeof(Uint32)); + map->tiles = (Uint32 *)malloc(map->size.x * map->size.y * sizeof(Uint32)); for (int y = 0; y < min(old_map_height, map->size.y); y++) { for (int x = 0; x < min(old_map_width, map->size.x); x++) { @@ -549,7 +601,7 @@ static void change_map_size(Map *map, char direction, int amount) { player.position = clamp(player.position, i32vec2(0, 0), map->size - 2); - map->gpu_buffer = create_buffer(WGPUBufferUsage_Vertex, map->size.x * map->size.y * 4, map->tiles, "world_buffer"); + map->gpu_buffer = create_buffer(WGPUBufferUsage_Vertex | WGPUBufferUsage_CopyDst, map->size.x * map->size.y * sizeof(Uint32), map->tiles, "world_buffer"); if (!map->gpu_buffer) { log_error("Failed to create buffer. Exiting."); exit(1); @@ -631,7 +683,7 @@ static void blit(char *dst, Sint32 dst_pitch, Sint32 dst_x, Sint32 dst_y, char * memmove(&dst[((dst_y + y) * dst_pitch + dst_x) * components], &src[y * src_pitch * components], width * components); } -static bool SelectableTile(const char *label, bool selected, Uint32 tile_index, const ImVec2& image_size, Uint8 orientation = 0) { +static bool SelectableTile(const char *label, bool selected, Uint32 tile_index, const ImVec2& image_size) { const ImGuiContext *context = ImGui::GetCurrentContext(); const ImVec2 padding = context->Style.FramePadding; @@ -641,14 +693,7 @@ static bool SelectableTile(const char *label, bool selected, Uint32 tile_index, ImVec2 max = ImGui::GetItemRectMax(); vec4 uv = tile_uvs[tile_index] / (float)TILE_ATLAS_SIZE; - - switch (orientation) { - case 0: context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.x, uv.y), ImVec2(uv.z, uv.y), ImVec2(uv.z, uv.w), ImVec2(uv.x, uv.w)); break; - case 1: context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.z, uv.y), ImVec2(uv.z, uv.w), ImVec2(uv.x, uv.w), ImVec2(uv.x, uv.y)); break; - case 2: context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.z, uv.w), ImVec2(uv.x, uv.w), ImVec2(uv.x, uv.y), ImVec2(uv.z, uv.y)); break; - case 3: context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.x, uv.w), ImVec2(uv.x, uv.y), ImVec2(uv.z, uv.y), ImVec2(uv.z, uv.w)); break; - default: SDL_assert_always(false); break; - } + context->CurrentWindow->DrawList->AddImageQuad((ImTextureID)tile_textures_atlas_view_unorm, min + padding, ImVec2(max.x - padding.x, min.y + padding.y), max - padding, ImVec2(min.x + padding.x, max.y - padding.y), ImVec2(uv.x, uv.y), ImVec2(uv.z, uv.y), ImVec2(uv.z, uv.w), ImVec2(uv.x, uv.w)); return pressed; } @@ -1246,6 +1291,21 @@ static bool recreate_tile_textures() { .depthOrArrayLayers = 1, }; + if (tile_infos[i].rotation) { + Uint32 copy[TILE_SIZE * TILE_SIZE]; memcpy(copy, data, TILE_SIZE * TILE_SIZE * 4); + + for (int y = 0; y < TILE_SIZE; y++) { + for (int x = 0; x < TILE_SIZE; x++) { + switch(tile_infos[i].rotation) { + case 1: ((Uint32 *)data)[(TILE_SIZE - x - 1) * TILE_SIZE + (y)] = copy[y * TILE_SIZE + x]; break; + case 2: ((Uint32 *)data)[(TILE_SIZE - y - 1) * TILE_SIZE + (TILE_SIZE - x - 1)] = copy[y * TILE_SIZE + x]; break; + case 3: ((Uint32 *)data)[(x) * TILE_SIZE + (TILE_SIZE - y - 1)] = copy[y * TILE_SIZE + x]; break; + default: assert(false); break; + }; + } + } + } + wgpuQueueWriteTexture(queue, &texel_copy_texture_info, data, width * height * 4, &texel_copy_buffer_layout, &extent); stbi_image_free(data); } @@ -1277,39 +1337,13 @@ static Uint32 get_corner_info(Sint32 tile_pos_x, Sint32 tile_pos_y) { if (tile_pos_x < 0 || tile_pos_x >= current_map.size.x || tile_pos_y < 0 || tile_pos_y >= current_map.size.y) return 0; - Uint32 tile = current_map.tiles[tile_pos_y * current_map.size.x + tile_pos_x]; - - Uint32 index = tile & 0xffff; - Uint32 rotation = (tile & 0x30000) >> 16; - - Uint32 base_corner_info = tile_infos[index].corner_info; - - switch (rotation) { - case 0: return base_corner_info; - case 1: return std::rotl(base_corner_info, 8); - case 2: return std::rotl(base_corner_info, 16); - case 3: return std::rotl(base_corner_info, 24); - default: return tile_infos[0].corner_info; - } + return tile_infos[current_map.tiles[tile_pos_y * current_map.size.x + tile_pos_x]].corner_info; } static Uint32 find_matching_tile(Uint32 corner_info) { - Uint32 corner_info_1 = std::rotr(corner_info, 8); - Uint32 corner_info_2 = std::rotr(corner_info, 16); - Uint32 corner_info_3 = std::rotr(corner_info, 24); - for (Uint32 i = 0; i < SDL_arraysize(tile_infos); i++) { if (corner_info == tile_infos[i].corner_info) return i; - - if (corner_info_1 == tile_infos[i].corner_info) - return (1 << 16) | i; - - if (corner_info_2 == tile_infos[i].corner_info) - return (2 << 16) | i; - - if (corner_info_3 == tile_infos[i].corner_info) - return (3 << 16) | i; } return 0; @@ -1342,7 +1376,7 @@ static void change_map_tile(Sint32 pos_x, Sint32 pos_y, TileKind kind) { if (0 <= pos_x + 0 && pos_x + 0 < current_map.size.x && 0 <= pos_y + 0 && pos_y + 0 < current_map.size.y) current_map.tiles[(pos_y + 0) * current_map.size.x + pos_x + 0] = find_matching_tile(corner_infos[3]); - update_buffer(current_map.gpu_buffer, 0, current_map.size.x * current_map.size.y * sizeof(Uint32), current_map.tiles); + update_buffer(current_map.gpu_buffer, 0, current_map.size.x * current_map.size.y * sizeof(Uint16), current_map.tiles); } static void SameLineOrWrap(const ImVec2& size) { @@ -1671,18 +1705,6 @@ static void process_event_editor(SDL_Event event) { if (io.WantCaptureKeyboard) return; - - SDL_Keymod modifiers = SDL_GetModState(); - - if (event.key.key == SDLK_R) { - if (selected_tile != -1 && selected_rotation != -1) { - if (modifiers & SDL_KMOD_SHIFT) { - selected_rotation = (selected_rotation - 1) & 3; - } else { - selected_rotation = (selected_rotation + 1) & 3; - } - } - } } break; case SDL_EVENT_MOUSE_WHEEL: { @@ -1786,12 +1808,7 @@ static void process_event_editor(SDL_Event event) { for (Sint32 y = start_y; y <= end_y; y++) { for (Sint32 x = start_x; x <= end_x; x++) { - if (selected_rotation == -1) { - Sint32 rotation = SDL_rand(4); - current_map.tiles[x + current_map.size.x * y] = ((rotation & 3) << 16) | selected_tile; - } else { - current_map.tiles[x + current_map.size.x * y] = ((selected_rotation & 3) << 16) | selected_tile; - } + current_map.tiles[x + current_map.size.x * y] = selected_tile; } } @@ -1982,44 +1999,13 @@ static void update_state_editor() { if (i != 0) SameLineOrWrap(ImVec2(32, 32)); - if (SelectableTile("##tile", selected_tile == i, i, ImVec2(32, 32), SDL_max(selected_rotation, 0))) { + if (SelectableTile("##tile", selected_tile == i, i, ImVec2(32, 32))) { selected_tile_kind = -1; selected_tile = i; } ImGui::PopID(); } - - if (selected_tile != -1) { - ImGui::Text("Rotation:"); - - if (SelectableTile("##None", selected_rotation == 0, selected_tile, ImVec2(32, 32), 0)) - selected_rotation = 0; - - - SameLineOrWrap(ImVec2(32, 32)); - if (SelectableTile("##90", selected_rotation == 1, selected_tile, ImVec2(32, 32), 1)) - selected_rotation = 1; - - SameLineOrWrap(ImVec2(32, 32)); - if (SelectableTile("##180", selected_rotation == 2, selected_tile, ImVec2(32, 32), 2)) - selected_rotation = 2; - - SameLineOrWrap(ImVec2(32, 32)); - if (SelectableTile("##270", selected_rotation == 3, selected_tile, ImVec2(32, 32), 3)) - selected_rotation = 3; - - if (ImGui::Selectable("Random", selected_rotation == -1)) - selected_rotation = -1; - } - - if (selected_tile != -1 && ImGui::IsWindowFocused() && ImGui::IsKeyPressed(ImGuiKey_R, false)) { - if (ImGui::IsKeyDown(ImGuiKey_LeftShift)) { - selected_rotation = (selected_rotation - 1) & 3; - } else { - selected_rotation = (selected_rotation + 1) & 3; - } - } } ImGui::End(); } else { diff --git a/src/shaders/world.wgsl b/src/shaders/world.wgsl index 27f8cf5..439944c 100644 --- a/src/shaders/world.wgsl +++ b/src/shaders/world.wgsl @@ -8,7 +8,7 @@ struct VertexShaderInput { // Per Instance @builtin(instance_index) instance_index: u32, - @location(2) tile_info: u32, + @location(2) tile: u32, }; struct VertexShaderOutput { @@ -36,21 +36,11 @@ struct Per_Frame_Data { @vertex fn main_vertex(input: VertexShaderInput) -> VertexShaderOutput { var output: VertexShaderOutput; - let tile_type = extractBits(input.tile_info, 0, 16); - let rotation = extractBits(input.tile_info, 16, 2); - let tile_pos = vec2(f32(input.instance_index % per_frame.map_width), f32(input.instance_index / per_frame.map_width)) - vec2(0.5, 0.5); - output.tile = tile_type; + output.tile = input.tile; output.pos = vec4(tile_pos + input.pos.xy, 0, 1) * view_projection_matrix; - - switch (rotation) { - case 0: { output.uv = vec2( input.uv.x, input.uv.y); } - case 1: { output.uv = vec2(1.0 - input.uv.y, input.uv.x); } - case 2: { output.uv = vec2(1.0 - input.uv.x, 1.0 - input.uv.y); } - case 3: { output.uv = vec2( input.uv.y, 1.0 - input.uv.x); } - default: {} - } + output.uv = input.uv; return output; }