diff --git a/CMakeLists.txt b/CMakeLists.txt index 54f3051..53eebbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,7 @@ endfunction() add_shader(character) add_shader(character_shadow) add_shader(world) -add_shader(tree) +add_shader(placeable) add_shader(grid) add_custom_target(shaders-spv DEPENDS ${SHADERS_SPV}) diff --git a/src/main.cpp b/src/main.cpp index 4abe282..c2f1a09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,9 +33,9 @@ using namespace glm; #define NEAR_PLANE (0.01f) -#define TILE_SIZE (32) -#define TILE_ATLAS_SIZE (512) -#define TREE_ATLAS_SIZE (256) +#define TILE_SIZE (32) +#define TILE_ATLAS_SIZE (512) +#define PLACEABLE_ATLAS_SIZE (256) static SDL_Window *window; static R_Texture framebuffer; @@ -44,17 +44,18 @@ static R_Texture player_texture; static R_Texture character_shadow_texture; static R_Texture tile_textures_atlas; static R_Texture tile_textures_atlas_imgui; -static R_Texture tree_textures_atlas; -static R_Texture tree_textures_atlas_imgui; +static R_Texture placeable_textures_atlas; +static R_Texture placeable_textures_atlas_imgui; static R_Buffer view_projection_matrix_buffer; static R_Buffer per_frame_buffer; static R_Buffer tint_color_buffer; static R_Buffer player_instance_buffer; -static R_Buffer trees_instance_buffer; +static R_Buffer placeable_instance_buffer; static R_Buffer tile_uvs_buffer; -static R_Buffer tree_uvs_buffer; +static R_Buffer placeable_uvs_buffer; +static R_Buffer placeable_sizes_and_offsets_buffer; static i32vec2 window_size = { 1280, 720 }; @@ -96,7 +97,7 @@ static float editor_camera_distance = 30.0f; static bool show_demo_window; static bool show_tile_picker; -static bool show_tree_editor; +static bool show_placeable_editor; static bool show_world_editor; static bool show_settings; @@ -186,22 +187,22 @@ struct Instance { static Instance player_instance = {{ 0.0f, 0.0f }}; -struct Tree { +struct Placeable { u32vec2 pos; - Uint32 kind; + Uint32 kind; }; struct Map { i32vec2 size; Uint16 *tiles; - Uint32 num_trees; - Tree *trees; + Uint32 num_placeables; + Placeable *placeables; char name[64]; R_Texture texture; - R_Buffer trees_buffer; + R_Buffer placeables_buffer; }; static Uint32 num_loaded_maps; @@ -415,18 +416,22 @@ static TileInfo tile_infos[] = { static vec4 tile_uvs[SDL_arraysize(tile_infos)]; -struct TreeInfo { +struct PlaceableInfo { Uint16 serialization_id; const char *asset_path; + vec2 visual_offset; }; -static TreeInfo tree_infos[] = { - { 0, "decorations/tree_standard_tile_angle.png" }, +static PlaceableInfo placeable_infos[] = { + { 0, "decorations/tree_standard_tile_angle.png", vec2(0, 0.25) }, + { 1, "decorations/Stone.png", vec2(0, 0) }, + { 2, "decorations/stone_grass.png", vec2(0, 0) }, }; -static vec4 tree_uvs[SDL_arraysize(tree_infos)]; +static vec4 placeable_uvs [SDL_arraysize(placeable_infos)]; +static vec4 placeable_sizes_and_offsets[SDL_arraysize(placeable_infos)]; -static Sint32 selected_tree = -1; +static Sint32 selected_placeable = -1; static Sint32 selected_tile_kind = -1; static Sint32 selected_tile = -1; @@ -524,26 +529,26 @@ static bool save_map(Map *map) { } } - if (!SDL_WriteU32LE(file, map->num_trees)) { - log_error("Failed to write num_trees to map file."); + if (!SDL_WriteU32LE(file, map->num_placeables)) { + log_error("Failed to write num_placeable to map file."); return false; } - for (int i = 0; i < map->num_trees; i++) { - Uint16 id = tree_infos[map->trees[i].kind].serialization_id; + for (int i = 0; i < map->num_placeables; i++) { + Uint16 id = placeable_infos[map->placeables[i].kind].serialization_id; if (!SDL_WriteU16LE(file, id)) { - log_error("Failed to write tree kind to map file."); + log_error("Failed to write placeables kind to map file."); return false; } - if (!SDL_WriteU32LE(file, map->trees[i].pos.x)) { - log_error("Failed to write tree pos.x to map file."); + if (!SDL_WriteU32LE(file, map->placeables[i].pos.x)) { + log_error("Failed to write placeables pos.x to map file."); return false; } - if (!SDL_WriteU32LE(file, map->trees[i].pos.y)) { - log_error("Failed to write tree pos.y to map file."); + if (!SDL_WriteU32LE(file, map->placeables[i].pos.y)) { + log_error("Failed to write placeables pos.y to map file."); return false; } } @@ -624,43 +629,43 @@ static bool load_map(const char *name, Map *result) { } if (version >= 3) { - if (!SDL_ReadU32LE(file, &result->num_trees)) { - log_error("Failed to read num_trees from map file."); + if (!SDL_ReadU32LE(file, &result->num_placeables)) { + log_error("Failed to read num_placeables from map file."); free(result->tiles); return false; } - result->trees = (Tree *)SDL_malloc(result->num_trees * sizeof(Tree)); + result->placeables = (Placeable *)SDL_malloc(result->num_placeables * sizeof(Placeable)); - for (int i = 0; i < result->num_trees; i++) { + for (int i = 0; i < result->num_placeables; i++) { Uint16 serialization_id = 0; if (!SDL_ReadU16LE(file, &serialization_id)) { free(result->tiles); - free(result->trees); + free(result->placeables); return false; } Uint16 info_index = 0; - for (int i = 0; i < SDL_arraysize(tree_infos); i++) { - if (tree_infos[i].serialization_id == serialization_id) { + for (int i = 0; i < SDL_arraysize(placeable_infos); i++) { + if (placeable_infos[i].serialization_id == serialization_id) { info_index = i; break; } } - result->trees[i].kind = info_index; + result->placeables[i].kind = info_index; - if (!SDL_ReadU32LE(file, &result->trees[i].pos.x)) { + if (!SDL_ReadU32LE(file, &result->placeables[i].pos.x)) { free(result->tiles); - free(result->trees); - log_error("Failed to read tree pos.x from map file."); + free(result->placeables); + log_error("Failed to read placeable pos.x from map file."); return false; } - if (!SDL_ReadU32LE(file, &result->trees[i].pos.y)) { + if (!SDL_ReadU32LE(file, &result->placeables[i].pos.y)) { free(result->tiles); - free(result->trees); - log_error("Failed to read tree pos.y from map file."); + free(result->placeables); + log_error("Failed to read placeable pos.y from map file."); return false; } } @@ -671,8 +676,8 @@ static bool load_map(const char *name, Map *result) { result->texture = renderer_texture_create(R_TEXTURE_FORMAT_R16_UINT, R_TEXTURE_USAGE_STORAGE, false, result->size.x, result->size.y, result->tiles, "map_texture"); - if (result->num_trees) { - result->trees_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, result->num_trees * sizeof(*result->trees), result->trees, "trees_buffer"); + if (result->num_placeables) { + result->placeables_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, result->num_placeables * sizeof(*result->placeables), result->placeables, "placeables_buffer"); } SDL_Log("Loaded map file."); @@ -928,64 +933,70 @@ static bool recreate_tile_textures() { return true; } -static bool recreate_tree_textures() { - smol_atlas_t *tree_atlas = sma_atlas_create(TREE_ATLAS_SIZE, TREE_ATLAS_SIZE); - smol_atlas_item_t **tree_atlas_items = (smol_atlas_item_t **)SDL_calloc(SDL_arraysize(tree_infos), sizeof(smol_atlas_item_t *)); +static bool recreate_placeable_textures() { + smol_atlas_t *placeable_atlas = sma_atlas_create(PLACEABLE_ATLAS_SIZE, PLACEABLE_ATLAS_SIZE); + smol_atlas_item_t **placeable_atlas_items = (smol_atlas_item_t **)SDL_calloc(SDL_arraysize(placeable_infos), sizeof(smol_atlas_item_t *)); - defer(sma_atlas_destroy(tree_atlas)); - defer(SDL_free(tree_atlas_items)); + defer(sma_atlas_destroy(placeable_atlas)); + defer(SDL_free(placeable_atlas_items)); - for (Uint32 i = 0; i < SDL_arraysize(tree_infos); i++) { + for (Uint32 i = 0; i < SDL_arraysize(placeable_infos); i++) { char path[256] = ASSETS_PATH; - SDL_strlcat(path, tree_infos[i].asset_path, SDL_arraysize(path)); + SDL_strlcat(path, placeable_infos[i].asset_path, SDL_arraysize(path)); int width = 0, height = 0; if (!stbi_info(path, &width, &height, NULL)) return false; - tree_atlas_items[i] = sma_item_add(tree_atlas, width, height); - if (!tree_atlas_items[i]) + placeable_atlas_items[i] = sma_item_add(placeable_atlas, width, height); + if (!placeable_atlas_items[i]) return false; } - tree_textures_atlas = renderer_texture_create(R_TEXTURE_FORMAT_RGBA8_UNORM_SRGB, R_TEXTURE_USAGE_SAMPLED, false, TREE_ATLAS_SIZE, TREE_ATLAS_SIZE, NULL, "tree_atlas_texture"); - if (!tree_textures_atlas) { + placeable_textures_atlas = renderer_texture_create(R_TEXTURE_FORMAT_RGBA8_UNORM_SRGB, R_TEXTURE_USAGE_SAMPLED, false, PLACEABLE_ATLAS_SIZE, PLACEABLE_ATLAS_SIZE, NULL, "placeable_atlas_texture"); + if (!placeable_textures_atlas) { log_error("Failed to create texture."); return false; } - tree_textures_atlas_imgui = renderer_texture_create(R_TEXTURE_FORMAT_RGBA8_UNORM, R_TEXTURE_USAGE_SAMPLED, false, TREE_ATLAS_SIZE, TREE_ATLAS_SIZE, NULL, "tree_atlas_texture imgui"); - if (!tree_textures_atlas_imgui) { + placeable_textures_atlas_imgui = renderer_texture_create(R_TEXTURE_FORMAT_RGBA8_UNORM, R_TEXTURE_USAGE_SAMPLED, false, PLACEABLE_ATLAS_SIZE, PLACEABLE_ATLAS_SIZE, NULL, "placeable_atlas_texture imgui"); + if (!placeable_textures_atlas_imgui) { log_error("Failed to create texture."); return false; } - for (Uint32 i = 0; i < SDL_arraysize(tree_infos); i++) { + for (Uint32 i = 0; i < SDL_arraysize(placeable_infos); i++) { char path[256] = ASSETS_PATH; - SDL_strlcat(path, tree_infos[i].asset_path, SDL_arraysize(path)); + SDL_strlcat(path, placeable_infos[i].asset_path, SDL_arraysize(path)); int width = 0, height = 0; stbi_uc *data = stbi_load(path, &width, &height, NULL, 4); if (!data) { log_error("Failed to load texture (\"%s\"). Exiting.", path); - renderer_texture_destroy(tree_textures_atlas); - tree_textures_atlas = NULL; - renderer_texture_destroy(tree_textures_atlas_imgui); - tree_textures_atlas_imgui = NULL; + renderer_texture_destroy(placeable_textures_atlas); + placeable_textures_atlas = NULL; + renderer_texture_destroy(placeable_textures_atlas_imgui); + placeable_textures_atlas_imgui = NULL; return false; } - tree_uvs[i].x = sma_item_x(tree_atlas_items[i]); - tree_uvs[i].y = sma_item_y(tree_atlas_items[i]); - tree_uvs[i].z = sma_item_x(tree_atlas_items[i]) + sma_item_width (tree_atlas_items[i]); - tree_uvs[i].w = sma_item_y(tree_atlas_items[i]) + sma_item_height(tree_atlas_items[i]); + placeable_uvs[i].x = sma_item_x(placeable_atlas_items[i]); + placeable_uvs[i].y = sma_item_y(placeable_atlas_items[i]); + placeable_uvs[i].z = sma_item_x(placeable_atlas_items[i]) + sma_item_width (placeable_atlas_items[i]); + placeable_uvs[i].w = sma_item_y(placeable_atlas_items[i]) + sma_item_height(placeable_atlas_items[i]); - renderer_texture_update(tree_textures_atlas, sma_item_x(tree_atlas_items[i]), sma_item_y(tree_atlas_items[i]), sma_item_width(tree_atlas_items[i]), sma_item_height(tree_atlas_items[i]), data, sma_item_width(tree_atlas_items[i]) * 4); - renderer_texture_update(tree_textures_atlas_imgui, sma_item_x(tree_atlas_items[i]), sma_item_y(tree_atlas_items[i]), sma_item_width(tree_atlas_items[i]), sma_item_height(tree_atlas_items[i]), data, sma_item_width(tree_atlas_items[i]) * 4); + placeable_sizes_and_offsets[i].x = (float)width / 32.0f; + placeable_sizes_and_offsets[i].y = (float)height / 32.0f; + placeable_sizes_and_offsets[i].z = placeable_infos[i].visual_offset.x; + placeable_sizes_and_offsets[i].w = placeable_infos[i].visual_offset.y; + + renderer_texture_update(placeable_textures_atlas, sma_item_x(placeable_atlas_items[i]), sma_item_y(placeable_atlas_items[i]), sma_item_width(placeable_atlas_items[i]), sma_item_height(placeable_atlas_items[i]), data, sma_item_width(placeable_atlas_items[i]) * 4); + renderer_texture_update(placeable_textures_atlas_imgui, sma_item_x(placeable_atlas_items[i]), sma_item_y(placeable_atlas_items[i]), sma_item_width(placeable_atlas_items[i]), sma_item_height(placeable_atlas_items[i]), data, sma_item_width(placeable_atlas_items[i]) * 4); stbi_image_free(data); } - tree_uvs_buffer = renderer_buffer_create(R_BUFFER_USAGE_STORAGE, sizeof(tree_uvs), tree_uvs, "tree_uvs_buffer"); + placeable_uvs_buffer = renderer_buffer_create(R_BUFFER_USAGE_STORAGE, sizeof(placeable_uvs), placeable_uvs, "placeable_uvs_buffer"); + placeable_sizes_and_offsets_buffer = renderer_buffer_create(R_BUFFER_USAGE_STORAGE, sizeof(placeable_sizes_and_offsets), placeable_sizes_and_offsets, "placeable_sizes_and_offsets_buffer"); return true; } @@ -1117,8 +1128,8 @@ static bool init_resources() { return false; } - if (!recreate_tree_textures()) { - log_error("Failed to create tree textures."); + if (!recreate_placeable_textures()) { + log_error("Failed to create placeable textures."); return false; } @@ -1189,46 +1200,46 @@ static void process_event_editor(SDL_Event event) { } if (event.button.button == SDL_BUTTON_LEFT) { - if (selected_tree != -1 && 0 <= tile_pos.x && tile_pos.x < current_map->size.x -1 && 0 <= tile_pos.y && tile_pos.y < current_map->size.y - 1) { - Sint32 found_tree = -1; - for (Sint32 i = 0; i < current_map->num_trees; i++) { - if ((current_map->trees[i].pos.x == entity_pos.x) && (current_map->trees[i].pos.y == entity_pos.y)) { - found_tree = i; + if (selected_placeable != -1 && 0 <= tile_pos.x && tile_pos.x < current_map->size.x -1 && 0 <= tile_pos.y && tile_pos.y < current_map->size.y - 1) { + Sint32 found_placeable = -1; + for (Sint32 i = 0; i < current_map->num_placeables; i++) { + if ((current_map->placeables[i].pos.x == entity_pos.x) && (current_map->placeables[i].pos.y == entity_pos.y)) { + found_placeable = i; break; } } - if (found_tree != -1) { - Tree tmp = current_map->trees[found_tree]; - SDL_memmove(¤t_map->trees[found_tree], ¤t_map->trees[found_tree + 1], (current_map->num_trees - (found_tree + 1)) * sizeof(*current_map->trees)); - current_map->trees[current_map->num_trees - 1] = tmp; + if (found_placeable != -1) { + Placeable tmp = current_map->placeables[found_placeable]; + SDL_memmove(¤t_map->placeables[found_placeable], ¤t_map->placeables[found_placeable + 1], (current_map->num_placeables - (found_placeable + 1)) * sizeof(*current_map->placeables)); + current_map->placeables[current_map->num_placeables - 1] = tmp; } else { - current_map->trees = (Tree *)SDL_realloc(current_map->trees, (current_map->num_trees + 1) * sizeof(*current_map->trees)); - current_map->trees[current_map->num_trees] = { + current_map->placeables = (Placeable *)SDL_realloc(current_map->placeables, (current_map->num_placeables + 1) * sizeof(*current_map->placeables)); + current_map->placeables[current_map->num_placeables] = { .pos = entity_pos, - .kind = (Uint32)selected_tree, + .kind = (Uint32)selected_placeable, }; - current_map->num_trees++; + current_map->num_placeables++; } - std::stable_sort(¤t_map->trees[0], ¤t_map->trees[current_map->num_trees], [](const Tree &a, const Tree &b){ return a.pos.y > b.pos.y; }); + std::stable_sort(¤t_map->placeables[0], ¤t_map->placeables[current_map->num_placeables], [](const Placeable &a, const Placeable &b){ return a.pos.y > b.pos.y; }); - if (current_map->trees_buffer) renderer_buffer_destroy(current_map->trees_buffer); - current_map->trees_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, current_map->num_trees * sizeof(*current_map->trees), current_map->trees, "trees_buffer"); + if (current_map->placeables_buffer) renderer_buffer_destroy(current_map->placeables_buffer); + current_map->placeables_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, current_map->num_placeables * sizeof(*current_map->placeables), current_map->placeables, "placeables_buffer"); } - if (show_tree_editor && selected_tree == -1) { - for (Sint32 i = 0; i < current_map->num_trees; i++) { - if ((current_map->trees[i].pos.x == entity_pos.x) && (current_map->trees[i].pos.y == entity_pos.y)) { - SDL_memmove(¤t_map->trees[i], ¤t_map->trees[i + 1], (current_map->num_trees - (i + 1)) * sizeof(*current_map->trees)); - current_map->num_trees--; + if (show_placeable_editor && selected_placeable == -1) { + for (Sint32 i = 0; i < current_map->num_placeables; i++) { + if ((current_map->placeables[i].pos.x == entity_pos.x) && (current_map->placeables[i].pos.y == entity_pos.y)) { + SDL_memmove(¤t_map->placeables[i], ¤t_map->placeables[i + 1], (current_map->num_placeables - (i + 1)) * sizeof(*current_map->placeables)); + current_map->num_placeables--; break; } } - if (current_map->trees_buffer) renderer_buffer_destroy(current_map->trees_buffer); - if (current_map->num_trees) current_map->trees_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, current_map->num_trees * sizeof(*current_map->trees), current_map->trees, "trees_buffer"); + if (current_map->placeables_buffer) renderer_buffer_destroy(current_map->placeables_buffer); + if (current_map->num_placeables) current_map->placeables_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, current_map->num_placeables * sizeof(*current_map->placeables), current_map->placeables, "placeables_buffer"); } if (selected_tile_kind != -1) { @@ -1345,7 +1356,7 @@ static void update_state_editor() { if (ImGui::BeginMenu("File")) { if (ImGui::MenuItem("Reload")) { recreate_tile_textures(); - recreate_tree_textures(); + recreate_placeable_textures(); } if (ImGui::MenuItem("Save")) { @@ -1366,7 +1377,7 @@ static void update_state_editor() { if (ImGui::BeginMenu("Edit")) { ImGui::MenuItem("Tile Picker", NULL, &show_tile_picker); - ImGui::MenuItem("Trees", NULL, &show_tree_editor); + ImGui::MenuItem("Placeables", NULL, &show_placeable_editor); ImGui::MenuItem("Worlds", NULL, &show_world_editor); ImGui::EndMenu(); } @@ -1382,7 +1393,7 @@ static void update_state_editor() { ImGuiID left_dock = ImGui::DockBuilderSplitNode(main_viewport_dock, ImGuiDir_Left, 0.2f, NULL, NULL); ImGui::DockBuilderDockWindow("Tile Picker", left_dock); - ImGui::DockBuilderDockWindow("Trees", left_dock); + ImGui::DockBuilderDockWindow("Placeables", left_dock); ImGui::DockBuilderDockWindow("Worlds", left_dock); ImGui::DockBuilderFinish(main_viewport_dock); } @@ -1502,26 +1513,28 @@ static void update_state_editor() { selected_tile_kind = -1; } - if (show_tree_editor) { - if (ImGui::Begin("Trees", &show_tree_editor, ImGuiWindowFlags_NoFocusOnAppearing)) { - if (SelectableImage("##tree", tree_textures_atlas_imgui, ImVec2(64, 64), vec2(0, 0), vec2(0, 0), selected_tree == -1)) - selected_tree = -1; + if (show_placeable_editor) { + if (ImGui::Begin("Placeables", &show_placeable_editor, ImGuiWindowFlags_NoFocusOnAppearing)) { + if (SelectableImage("##placeable", placeable_textures_atlas_imgui, ImVec2(64, 64), vec2(0, 0), vec2(0, 0), selected_placeable == -1)) + selected_placeable = -1; - for (int i = 0; i < SDL_arraysize(tree_infos); i++) { + for (int i = 0; i < SDL_arraysize(placeable_infos); i++) { ImGui::PushID(i); - if (i != 0) - SameLineOrWrap(ImVec2(64, 1)); + vec2 size = placeable_sizes_and_offsets[i].xy() * 32.0f; - if (SelectableImage("##tree", tree_textures_atlas_imgui, ImVec2(tree_uvs[i].z, tree_uvs[i].w), tree_uvs[i].xy() / (float)TREE_ATLAS_SIZE, tree_uvs[i].zw() / (float)TREE_ATLAS_SIZE, selected_tree == i)) - selected_tree = i; + if (i != 0) + SameLineOrWrap(ImVec2(size.x, 1)); + + if (SelectableImage("##placeable", placeable_textures_atlas_imgui, ImVec2(size.x, size.y), placeable_uvs[i].xy() / (float)PLACEABLE_ATLAS_SIZE, placeable_uvs[i].zw() / (float)PLACEABLE_ATLAS_SIZE, selected_placeable == i)) + selected_placeable = i; ImGui::PopID(); } } ImGui::End(); } else { - selected_tree = -1; + selected_placeable = -1; } auto add_world_modal = ImGui::GetID("Add World"); @@ -1680,16 +1693,18 @@ static void render_editor() { }); } - if (current_map->num_trees) { - ZoneScopedN("Draw Trees"); - renderer_frame_set_shader(R_SHADER_TREE); - renderer_frame_draw(NULL, NULL, current_map->trees_buffer, 6, current_map->num_trees, &(R_Draw_Resources){ - .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, + if (current_map->num_placeables) { + ZoneScopedN("Draw Placeables"); + renderer_frame_set_shader(R_SHADER_PLACEABLE); + renderer_frame_draw(NULL, NULL, current_map->placeables_buffer, 6, current_map->num_placeables, &(R_Draw_Resources){ + .vertex_storage_buffers = (R_Buffer[]){ placeable_sizes_and_offsets_buffer }, + .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, - .num_vertex_uniform_buffers = 2, + .num_vertex_storage_buffers = 1, + .num_vertex_uniform_buffers = 2, - .fragment_sampled_textures = (R_Texture[]){ tree_textures_atlas }, - .fragment_storage_buffers = (R_Buffer[]){ tree_uvs_buffer }, + .fragment_sampled_textures = (R_Texture[]){ placeable_textures_atlas }, + .fragment_storage_buffers = (R_Buffer[]){ placeable_uvs_buffer }, .fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer }, .num_fragment_sampled_textures = 1, @@ -1897,16 +1912,18 @@ static void render_game() { }); } - if (current_map->num_trees) { - ZoneScopedN("Draw Trees"); - renderer_frame_set_shader(R_SHADER_TREE); - renderer_frame_draw(NULL, NULL, current_map->trees_buffer, 6, current_map->num_trees, &(R_Draw_Resources){ - .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, + if (current_map->num_placeables) { + ZoneScopedN("Draw Placeables"); + renderer_frame_set_shader(R_SHADER_PLACEABLE); + renderer_frame_draw(NULL, NULL, current_map->placeables_buffer, 6, current_map->num_placeables, &(R_Draw_Resources){ + .vertex_storage_buffers = (R_Buffer[]){ placeable_sizes_and_offsets_buffer }, + .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, - .num_vertex_uniform_buffers = 2, + .num_vertex_storage_buffers = 1, + .num_vertex_uniform_buffers = 2, - .fragment_sampled_textures = (R_Texture[]){ tree_textures_atlas }, - .fragment_storage_buffers = (R_Buffer[]){ tree_uvs_buffer }, + .fragment_sampled_textures = (R_Texture[]){ placeable_textures_atlas }, + .fragment_storage_buffers = (R_Buffer[]){ placeable_uvs_buffer }, .fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer }, .num_fragment_sampled_textures = 1, diff --git a/src/renderer.h b/src/renderer.h index fff0e64..4cf308e 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -11,7 +11,7 @@ typedef enum : Uint32 { R_SHADER_CHARACTER, R_SHADER_CHARACTER_SHADOW, R_SHADER_WORLD, - R_SHADER_TREE, + R_SHADER_PLACEABLE, R_SHADER_GRID, R_SHADER_COUNT, } R_Shader; diff --git a/src/renderer_sdlgpu.c b/src/renderer_sdlgpu.c index 9c4de41..cc4f032 100644 --- a/src/renderer_sdlgpu.c +++ b/src/renderer_sdlgpu.c @@ -803,9 +803,9 @@ bool renderer_init(SDL_Window *window_) { SDL_ReleaseGPUShader(device, fragment_shader); } - { // Tree + { // Placeable const Uint8 shader_source[] = { - #embed "shaders/spirv/tree.spv" + #embed "shaders/spirv/placeable.spv" }; SDL_GPUShader *vertex_shader = SDL_CreateGPUShader(device, &(SDL_GPUShaderCreateInfo){ @@ -818,7 +818,7 @@ bool renderer_init(SDL_Window *window_) { .num_samplers = 0, .num_storage_textures = 0, - .num_storage_buffers = 0, + .num_storage_buffers = 1, .num_uniform_buffers = 2, }); @@ -837,9 +837,9 @@ bool renderer_init(SDL_Window *window_) { }); SDL_PropertiesID properties = SDL_CreateProperties(); - SDL_SetStringProperty(properties, SDL_PROP_GPU_BUFFER_CREATE_NAME_STRING, "R_SHADER tree"); + SDL_SetStringProperty(properties, SDL_PROP_GPU_BUFFER_CREATE_NAME_STRING, "R_SHADER placeable"); - shaders[R_SHADER_TREE] = SDL_CreateGPUGraphicsPipeline(device, &(SDL_GPUGraphicsPipelineCreateInfo){ + shaders[R_SHADER_PLACEABLE] = SDL_CreateGPUGraphicsPipeline(device, &(SDL_GPUGraphicsPipelineCreateInfo){ .vertex_shader = vertex_shader, .fragment_shader = fragment_shader, diff --git a/src/renderer_wgpu.c b/src/renderer_wgpu.c index c754276..8e6f5d7 100644 --- a/src/renderer_wgpu.c +++ b/src/renderer_wgpu.c @@ -971,9 +971,9 @@ bool renderer_init(SDL_Window *window_) { wgpuShaderModuleRelease(shader); } - { // Tree + { // Placeable const char shader_source[] = { - #embed "shaders/wgsl/tree.wgsl" + #embed "shaders/wgsl/placeable.wgsl" }; WGPUShaderModule shader = wgpuDeviceCreateShaderModule(device, &(WGPUShaderModuleDescriptor){ @@ -981,19 +981,21 @@ bool renderer_init(SDL_Window *window_) { .chain = { .next = NULL, .sType = WGPUSType_ShaderSourceWGSL }, .code = { .data = shader_source, .length = SDL_arraysize(shader_source) }, }, - .label = { .data = "tree shader", .length = WGPU_STRLEN } + .label = { .data = "placeable shader", .length = WGPU_STRLEN } }); - shaders[R_SHADER_TREE] = wgpuDeviceCreateRenderPipeline(device, &(WGPURenderPipelineDescriptor){ - .label = { .data = "tree render_pipeline", .length = WGPU_STRLEN }, + shaders[R_SHADER_PLACEABLE] = wgpuDeviceCreateRenderPipeline(device, &(WGPURenderPipelineDescriptor){ + .label = { .data = "placeable render_pipeline", .length = WGPU_STRLEN }, .layout = wgpuDeviceCreatePipelineLayout(device, &(WGPUPipelineLayoutDescriptor){ - .label = { .data = "tree pipeline_layout", .length = WGPU_STRLEN }, + .label = { .data = "placeable pipeline_layout", .length = WGPU_STRLEN }, .bindGroupLayoutCount = 4, .bindGroupLayouts = (WGPUBindGroupLayout[]){ wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){ - .entryCount = 0, - .entries = (WGPUBindGroupLayoutEntry[]){}, + .entryCount = 1, + .entries = (WGPUBindGroupLayoutEntry[]){ + { .binding = 0, .visibility = WGPUShaderStage_Vertex, .buffer = { .type = WGPUBufferBindingType_ReadOnlyStorage } }, + }, }), wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){ .entryCount = 2, diff --git a/src/shaders/spirv/placeable.spv b/src/shaders/spirv/placeable.spv new file mode 100644 index 0000000..9dd6a1b Binary files /dev/null and b/src/shaders/spirv/placeable.spv differ diff --git a/src/shaders/spirv/tree.spv b/src/shaders/spirv/tree.spv deleted file mode 100644 index 95a09ae..0000000 Binary files a/src/shaders/spirv/tree.spv and /dev/null differ diff --git a/src/shaders/src/tree.slang b/src/shaders/src/placeable.slang similarity index 69% rename from src/shaders/src/tree.slang rename to src/shaders/src/placeable.slang index 514f54a..65845a1 100644 --- a/src/shaders/src/tree.slang +++ b/src/shaders/src/placeable.slang @@ -23,7 +23,7 @@ struct FragmentShaderOutput { float4 color : SV_Target; }; -static const float2 offset = float2(0, 0.25); +[vk::binding(0, 0)] StructuredBuffer placeable_sizes_and_offsets; [shader("vertex")] VertexShaderOutput main_vertex(VertexShaderInput input) { @@ -33,16 +33,16 @@ VertexShaderOutput main_vertex(VertexShaderInput input) { var vertex_uv = float2(0, 0); switch (input.vertex_index) { - case 0: { vertex_pos = float2(-1.0, 1.0); vertex_uv = float2(0, 0); } break; - case 1: { vertex_pos = float2(-1.0, -1.0); vertex_uv = float2(0, 1); } break; - case 2: { vertex_pos = float2( 1.0, -1.0); vertex_uv = float2(1, 1); } break; - case 3: { vertex_pos = float2(-1.0, 1.0); vertex_uv = float2(0, 0); } break; - case 4: { vertex_pos = float2( 1.0, -1.0); vertex_uv = float2(1, 1); } break; - case 5: { vertex_pos = float2( 1.0, 1.0); vertex_uv = float2(1, 0); } break; + case 0: { vertex_pos = float2(-0.5, 0.5); vertex_uv = float2(0, 0); } break; + case 1: { vertex_pos = float2(-0.5, -0.5); vertex_uv = float2(0, 1); } break; + case 2: { vertex_pos = float2( 0.5, -0.5); vertex_uv = float2(1, 1); } break; + case 3: { vertex_pos = float2(-0.5, 0.5); vertex_uv = float2(0, 0); } break; + case 4: { vertex_pos = float2( 0.5, -0.5); vertex_uv = float2(1, 1); } break; + case 5: { vertex_pos = float2( 0.5, 0.5); vertex_uv = float2(1, 0); } break; default: {} } - vertex_pos += offset; + vertex_pos = vertex_pos * placeable_sizes_and_offsets[input.kind].xy + placeable_sizes_and_offsets[input.kind].zw; output.pos = mul(float4(input.pos + vertex_pos, 0, 1), view_projection_matrix); output.uv = vertex_uv; @@ -52,8 +52,8 @@ VertexShaderOutput main_vertex(VertexShaderInput input) { } struct Block2 { - CombinedTextureSampler tree_atlas; - StructuredBuffer tree_uvs; + CombinedTextureSampler placeable_atlas; + StructuredBuffer placeable_uvs; }; struct Block3 { @@ -61,13 +61,13 @@ struct Block3 { }; [vk::binding(0, 2)] ParameterBlock block2; -[vk::binding(0, 3)]ParameterBlock block3; +[vk::binding(0, 3)] ParameterBlock block3; [shader("pixel")] FragmentShaderOutput main_fragment(VertexShaderOutput input) { var output: FragmentShaderOutput; - output.color = pixel_art_sample(block2.tree_atlas, input.uv, block2.tree_uvs[input.kind]); + output.color = pixel_art_sample(block2.placeable_atlas, input.uv, block2.placeable_uvs[input.kind]); output.color = float4(output.color.rgb * block3.tint.rgb, output.color.a); return output; diff --git a/src/shaders/wgsl/tree.wgsl b/src/shaders/wgsl/placeable.wgsl similarity index 60% rename from src/shaders/wgsl/tree.wgsl rename to src/shaders/wgsl/placeable.wgsl index e5e9d08..443a5b6 100644 --- a/src/shaders/wgsl/tree.wgsl +++ b/src/shaders/wgsl/placeable.wgsl @@ -1,14 +1,16 @@ +@binding(0) @group(0) var placeable_sizes_and_offsets_0 : array>; + struct _MatrixStorage_float4x4_ColMajorstd140_0 { @align(16) data_0 : array, i32(4)>, }; @binding(0) @group(1) var view_projection_matrix_0 : _MatrixStorage_float4x4_ColMajorstd140_0; -@binding(0) @group(2) var block2_tree_atlas_texture_0 : texture_2d; +@binding(0) @group(2) var block2_placeable_atlas_texture_0 : texture_2d; -@binding(1) @group(2) var block2_tree_atlas_sampler_0 : sampler; +@binding(1) @group(2) var block2_placeable_atlas_sampler_0 : sampler; -@binding(2) @group(2) var block2_tree_uvs_0 : array>; +@binding(2) @group(2) var block2_placeable_uvs_0 : array>; @binding(0) @group(3) var block3_tint_0 : vec3; struct VertexShaderOutput_0 @@ -29,53 +31,51 @@ fn main_vertex( _S1 : vertexInput_0, @builtin(vertex_index) vertex_index_0 : u32 { var output_0 : VertexShaderOutput_0; const _S2 : vec2 = vec2(0.0f, 0.0f); - var vertex_uv_0 : vec2; var vertex_pos_0 : vec2; + var vertex_uv_0 : vec2; switch(vertex_index_0) { case u32(0): { - const _S3 : vec2 = vec2(-1.0f, 1.0f); + vertex_pos_0 = vec2(-0.5f, 0.5f); vertex_uv_0 = _S2; - vertex_pos_0 = _S3; } case u32(1): { - const _S4 : vec2 = vec2(-1.0f, -1.0f); - vertex_uv_0 = vec2(0.0f, 1.0f); - vertex_pos_0 = _S4; + const _S3 : vec2 = vec2(0.0f, 1.0f); + vertex_pos_0 = vec2(-0.5f, -0.5f); + vertex_uv_0 = _S3; } case u32(2): { - const _S5 : vec2 = vec2(1.0f, -1.0f); - vertex_uv_0 = vec2(1.0f, 1.0f); - vertex_pos_0 = _S5; + const _S4 : vec2 = vec2(1.0f, 1.0f); + vertex_pos_0 = vec2(0.5f, -0.5f); + vertex_uv_0 = _S4; } case u32(3): { - const _S6 : vec2 = vec2(-1.0f, 1.0f); + vertex_pos_0 = vec2(-0.5f, 0.5f); vertex_uv_0 = _S2; - vertex_pos_0 = _S6; } case u32(4): { - const _S7 : vec2 = vec2(1.0f, -1.0f); - vertex_uv_0 = vec2(1.0f, 1.0f); - vertex_pos_0 = _S7; + const _S5 : vec2 = vec2(1.0f, 1.0f); + vertex_pos_0 = vec2(0.5f, -0.5f); + vertex_uv_0 = _S5; } case u32(5): { - const _S8 : vec2 = vec2(1.0f, 1.0f); - vertex_uv_0 = vec2(1.0f, 0.0f); - vertex_pos_0 = _S8; + const _S6 : vec2 = vec2(1.0f, 0.0f); + vertex_pos_0 = vec2(0.5f, 0.5f); + vertex_uv_0 = _S6; } default : { - vertex_uv_0 = _S2; vertex_pos_0 = _S2; + vertex_uv_0 = _S2; } } - output_0.pos_0 = (((mat4x4(view_projection_matrix_0.data_0[i32(0)][i32(0)], view_projection_matrix_0.data_0[i32(1)][i32(0)], view_projection_matrix_0.data_0[i32(2)][i32(0)], view_projection_matrix_0.data_0[i32(3)][i32(0)], view_projection_matrix_0.data_0[i32(0)][i32(1)], view_projection_matrix_0.data_0[i32(1)][i32(1)], view_projection_matrix_0.data_0[i32(2)][i32(1)], view_projection_matrix_0.data_0[i32(3)][i32(1)], view_projection_matrix_0.data_0[i32(0)][i32(2)], view_projection_matrix_0.data_0[i32(1)][i32(2)], view_projection_matrix_0.data_0[i32(2)][i32(2)], view_projection_matrix_0.data_0[i32(3)][i32(2)], view_projection_matrix_0.data_0[i32(0)][i32(3)], view_projection_matrix_0.data_0[i32(1)][i32(3)], view_projection_matrix_0.data_0[i32(2)][i32(3)], view_projection_matrix_0.data_0[i32(3)][i32(3)])) * (vec4(vec2(_S1.pos_1) + (vertex_pos_0 + vec2(0.0f, 0.25f)), 0.0f, 1.0f)))); + output_0.pos_0 = (((mat4x4(view_projection_matrix_0.data_0[i32(0)][i32(0)], view_projection_matrix_0.data_0[i32(1)][i32(0)], view_projection_matrix_0.data_0[i32(2)][i32(0)], view_projection_matrix_0.data_0[i32(3)][i32(0)], view_projection_matrix_0.data_0[i32(0)][i32(1)], view_projection_matrix_0.data_0[i32(1)][i32(1)], view_projection_matrix_0.data_0[i32(2)][i32(1)], view_projection_matrix_0.data_0[i32(3)][i32(1)], view_projection_matrix_0.data_0[i32(0)][i32(2)], view_projection_matrix_0.data_0[i32(1)][i32(2)], view_projection_matrix_0.data_0[i32(2)][i32(2)], view_projection_matrix_0.data_0[i32(3)][i32(2)], view_projection_matrix_0.data_0[i32(0)][i32(3)], view_projection_matrix_0.data_0[i32(1)][i32(3)], view_projection_matrix_0.data_0[i32(2)][i32(3)], view_projection_matrix_0.data_0[i32(3)][i32(3)])) * (vec4(vec2(_S1.pos_1) + (vertex_pos_0 * placeable_sizes_and_offsets_0[_S1.kind_1].xy + placeable_sizes_and_offsets_0[_S1.kind_1].zw), 0.0f, 1.0f)))); output_0.uv_0 = vertex_uv_0; output_0.kind_0 = _S1.kind_1; return output_0; @@ -89,16 +89,16 @@ fn CombinedTextureSampler_Sample_0( this_texture_0 : texture_2d, this_samp fn pixel_art_sample_0( input_texture_texture_0 : texture_2d, input_texture_sampler_0 : sampler, input_uv_0 : vec2, tree_uv_0 : vec4) -> vec4 { var dimensions_0 : vec2; - var _S9 : f32 = dimensions_0[i32(0)]; - var _S10 : f32 = dimensions_0[i32(1)]; - {var dim = textureDimensions((input_texture_texture_0));((_S9)) = f32(dim.x);((_S10)) = f32(dim.y);}; - dimensions_0[i32(0)] = _S9; - dimensions_0[i32(1)] = _S10; - var _S11 : vec2 = tree_uv_0.xy; - var _S12 : vec2 = tree_uv_0.zw; - var _S13 : vec2 = mix(_S11, _S12, input_uv_0); - var _S14 : vec2 = vec2(0.5f); - return CombinedTextureSampler_Sample_0(input_texture_texture_0, input_texture_sampler_0, clamp((floor(_S13) + saturate(fract(_S13) / (fwidth((_S13)))) - _S14) / dimensions_0, (_S11 + _S14) / dimensions_0, (_S12 - _S14) / dimensions_0)); + var _S7 : f32 = dimensions_0[i32(0)]; + var _S8 : f32 = dimensions_0[i32(1)]; + {var dim = textureDimensions((input_texture_texture_0));((_S7)) = f32(dim.x);((_S8)) = f32(dim.y);}; + dimensions_0[i32(0)] = _S7; + dimensions_0[i32(1)] = _S8; + var _S9 : vec2 = tree_uv_0.xy; + var _S10 : vec2 = tree_uv_0.zw; + var _S11 : vec2 = mix(_S9, _S10, input_uv_0); + var _S12 : vec2 = vec2(0.5f); + return CombinedTextureSampler_Sample_0(input_texture_texture_0, input_texture_sampler_0, clamp((floor(_S11) + saturate(fract(_S11) / (fwidth((_S11)))) - _S12) / dimensions_0, (_S9 + _S12) / dimensions_0, (_S10 - _S12) / dimensions_0)); } struct FragmentShaderOutput_0 @@ -113,11 +113,11 @@ struct pixelInput_0 }; @fragment -fn main_fragment( _S15 : pixelInput_0, @builtin(position) pos_2 : vec4) -> FragmentShaderOutput_0 +fn main_fragment( _S13 : pixelInput_0, @builtin(position) pos_2 : vec4) -> FragmentShaderOutput_0 { var output_1 : FragmentShaderOutput_0; - var _S16 : vec4 = pixel_art_sample_0(block2_tree_atlas_texture_0, block2_tree_atlas_sampler_0, _S15.uv_1, block2_tree_uvs_0[_S15.kind_2]); - output_1.color_0 = vec4(_S16.xyz * block3_tint_0.xyz, _S16.w); + var _S14 : vec4 = pixel_art_sample_0(block2_placeable_atlas_texture_0, block2_placeable_atlas_sampler_0, _S13.uv_1, block2_placeable_uvs_0[_S13.kind_2]); + output_1.color_0 = vec4(_S14.xyz * block3_tint_0.xyz, _S14.w); return output_1; }