Compare commits

...

3 Commits

Author SHA1 Message Date
Sven Balzer ecd6571785 rename Tree to placeable and dynamically load size
buildbot/windows Build done.
buildbot/linux Build done.
add stone variants as placeables
2026-08-06 19:45:47 +02:00
Sven Balzer ff82f59fdf add world list editor
buildbot/windows Build done.
buildbot/linux Build done.
change default tree ti tree_standard_tile_angle.png
2026-08-06 18:20:04 +02:00
Sven Balzer 963ccc4ec8 change rendering offsets for character, character shadow and trees
buildbot/windows Build done.
buildbot/linux Build done.
change default camera tilt
2026-08-05 21:50:13 +02:00
17 changed files with 365 additions and 240 deletions
+1 -1
View File
@@ -108,7 +108,7 @@ endfunction()
add_shader(character) add_shader(character)
add_shader(character_shadow) add_shader(character_shadow)
add_shader(world) add_shader(world)
add_shader(tree) add_shader(placeable)
add_shader(grid) add_shader(grid)
add_custom_target(shaders-spv DEPENDS ${SHADERS_SPV}) add_custom_target(shaders-spv DEPENDS ${SHADERS_SPV})
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

+16
View File
@@ -0,0 +1,16 @@
#ifndef WORLDS_H
#define WORLDS_H
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
static const char *world_names[] = {
"map",
};
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // WORLDS_H
+273 -166
View File
@@ -20,6 +20,8 @@
#include "stb_image.h" #include "stb_image.h"
#include "change_directory.h" #include "change_directory.h"
#include "../assets/maps/worlds.h"
#pragma clang diagnostic ignored "-Waddress-of-temporary" #pragma clang diagnostic ignored "-Waddress-of-temporary"
using namespace glm; using namespace glm;
@@ -33,7 +35,7 @@ using namespace glm;
#define TILE_SIZE (32) #define TILE_SIZE (32)
#define TILE_ATLAS_SIZE (512) #define TILE_ATLAS_SIZE (512)
#define TREE_ATLAS_SIZE (256) #define PLACEABLE_ATLAS_SIZE (256)
static SDL_Window *window; static SDL_Window *window;
static R_Texture framebuffer; static R_Texture framebuffer;
@@ -42,17 +44,18 @@ static R_Texture player_texture;
static R_Texture character_shadow_texture; static R_Texture character_shadow_texture;
static R_Texture tile_textures_atlas; static R_Texture tile_textures_atlas;
static R_Texture tile_textures_atlas_imgui; static R_Texture tile_textures_atlas_imgui;
static R_Texture tree_textures_atlas; static R_Texture placeable_textures_atlas;
static R_Texture tree_textures_atlas_imgui; static R_Texture placeable_textures_atlas_imgui;
static R_Buffer view_projection_matrix_buffer; static R_Buffer view_projection_matrix_buffer;
static R_Buffer per_frame_buffer; static R_Buffer per_frame_buffer;
static R_Buffer tint_color_buffer; static R_Buffer tint_color_buffer;
static R_Buffer player_instance_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 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 }; static i32vec2 window_size = { 1280, 720 };
@@ -68,7 +71,7 @@ static float volume_sfx = 50.0f;
static bool Running = true; static bool Running = true;
static float camera_fovy_degrees = 31.0f; static float camera_fovy_degrees = 31.0f;
static float camera_tilt = 25.5f; static float camera_tilt = 10.0f;
static float camera_distance = 13.5f; static float camera_distance = 13.5f;
static mat4x4 view_matrix; static mat4x4 view_matrix;
@@ -94,7 +97,8 @@ static float editor_camera_distance = 30.0f;
static bool show_demo_window; static bool show_demo_window;
static bool show_tile_picker; static bool show_tile_picker;
static bool show_tree_editor; static bool show_placeable_editor;
static bool show_world_editor;
static bool show_settings; static bool show_settings;
static float character_speed = 4.0f; static float character_speed = 4.0f;
@@ -183,7 +187,7 @@ struct Instance {
static Instance player_instance = {{ 0.0f, 0.0f }}; static Instance player_instance = {{ 0.0f, 0.0f }};
struct Tree { struct Placeable {
u32vec2 pos; u32vec2 pos;
Uint32 kind; Uint32 kind;
}; };
@@ -192,16 +196,18 @@ struct Map {
i32vec2 size; i32vec2 size;
Uint16 *tiles; Uint16 *tiles;
Uint32 num_trees; Uint32 num_placeables;
Tree *trees; Placeable *placeables;
char name[64]; char name[64];
R_Texture texture; R_Texture texture;
R_Buffer trees_buffer; R_Buffer placeables_buffer;
}; };
static Map current_map; static Uint32 num_loaded_maps;
static Map *loaded_maps;
static Map *current_map;
struct alignas(16) PerFrame { struct alignas(16) PerFrame {
i32vec2 drag_start; i32vec2 drag_start;
@@ -410,18 +416,22 @@ static TileInfo tile_infos[] = {
static vec4 tile_uvs[SDL_arraysize(tile_infos)]; static vec4 tile_uvs[SDL_arraysize(tile_infos)];
struct TreeInfo { struct PlaceableInfo {
Uint16 serialization_id; Uint16 serialization_id;
const char *asset_path; const char *asset_path;
vec2 visual_offset;
}; };
static TreeInfo tree_infos[] = { static PlaceableInfo placeable_infos[] = {
{ 0, "decorations/tree_standard_tile.png" }, { 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_kind = -1;
static Sint32 selected_tile = -1; static Sint32 selected_tile = -1;
@@ -455,11 +465,37 @@ static R_Texture create_texture(const char *path) {
return result; return result;
} }
static bool save_worlds_list() {
const char *path = ASSETS_PATH "maps/worlds.h";
SDL_IOStream *file = SDL_IOFromFile(path, "wb");
if (!file) {
log_error("Failed to open world list file for writing.");
return false;
}
defer(SDL_CloseIO(file));
SDL_IOprintf(file, "#ifndef WORLDS_H\n#define WORLDS_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n\nstatic const char *world_names[] = {\n");
for (int i = 0; i < num_loaded_maps; i++) {
SDL_IOprintf(file, " \"%.*s\",\n", (int)SDL_arraysize(loaded_maps[i].name), loaded_maps[i].name);
}
SDL_IOprintf(file, "};\n\n#ifdef __cplusplus\n}\n#endif // __cplusplus\n\n#endif // WORLDS_H\n");
if(!SDL_FlushIO(file)) {
log_error("Failed to flush data to world list file.");
return false;
};
return true;
}
#define MAP_FILE_VERSION (3u) #define MAP_FILE_VERSION (3u)
static bool save_map(Map map) { static bool save_map(Map *map) {
char path[256] = ASSETS_PATH "maps/"; char path[256] = ASSETS_PATH "maps/";
SDL_strlcat(path, map.name, SDL_arraysize(path)); SDL_strlcat(path, map->name, SDL_arraysize(path));
SDL_strlcat(path, ".sv", SDL_arraysize(path)); SDL_strlcat(path, ".sv", SDL_arraysize(path));
SDL_IOStream *file = SDL_IOFromFile(path, "wb"); SDL_IOStream *file = SDL_IOFromFile(path, "wb");
@@ -474,18 +510,18 @@ static bool save_map(Map map) {
return false; return false;
} }
if (!SDL_WriteS32LE(file, map.size.x)) { if (!SDL_WriteS32LE(file, map->size.x)) {
log_error("Failed to write width to map file."); log_error("Failed to write width to map file.");
return false; return false;
} }
if (!SDL_WriteS32LE(file, map.size.y)) { if (!SDL_WriteS32LE(file, map->size.y)) {
log_error("Failed to write height to map file."); log_error("Failed to write height to map file.");
return false; return false;
} }
for (int i = 0; i < map.size.x * map.size.y; i++) { for (int i = 0; i < map->size.x * map->size.y; i++) {
Uint16 id = tile_infos[map.tiles[i]].serialization_id; Uint16 id = tile_infos[map->tiles[i]].serialization_id;
if (!SDL_WriteU16LE(file, id)) { if (!SDL_WriteU16LE(file, id)) {
log_error("Failed to write tile to map file."); log_error("Failed to write tile to map file.");
@@ -493,26 +529,26 @@ static bool save_map(Map map) {
} }
} }
if (!SDL_WriteU32LE(file, map.num_trees)) { if (!SDL_WriteU32LE(file, map->num_placeables)) {
log_error("Failed to write num_trees to map file."); log_error("Failed to write num_placeable to map file.");
return false; return false;
} }
for (int i = 0; i < map.num_trees; i++) { for (int i = 0; i < map->num_placeables; i++) {
Uint16 id = tree_infos[map.trees[i].kind].serialization_id; Uint16 id = placeable_infos[map->placeables[i].kind].serialization_id;
if (!SDL_WriteU16LE(file, 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; return false;
} }
if (!SDL_WriteU32LE(file, map.trees[i].pos.x)) { if (!SDL_WriteU32LE(file, map->placeables[i].pos.x)) {
log_error("Failed to write tree pos.x to map file."); log_error("Failed to write placeables pos.x to map file.");
return false; return false;
} }
if (!SDL_WriteU32LE(file, map.trees[i].pos.y)) { if (!SDL_WriteU32LE(file, map->placeables[i].pos.y)) {
log_error("Failed to write tree pos.y to map file."); log_error("Failed to write placeables pos.y to map file.");
return false; return false;
} }
} }
@@ -593,43 +629,43 @@ static bool load_map(const char *name, Map *result) {
} }
if (version >= 3) { if (version >= 3) {
if (!SDL_ReadU32LE(file, &result->num_trees)) { if (!SDL_ReadU32LE(file, &result->num_placeables)) {
log_error("Failed to read num_trees from map file."); log_error("Failed to read num_placeables from map file.");
free(result->tiles); free(result->tiles);
return false; 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; Uint16 serialization_id = 0;
if (!SDL_ReadU16LE(file, &serialization_id)) { if (!SDL_ReadU16LE(file, &serialization_id)) {
free(result->tiles); free(result->tiles);
free(result->trees); free(result->placeables);
return false; return false;
} }
Uint16 info_index = 0; Uint16 info_index = 0;
for (int i = 0; i < SDL_arraysize(tree_infos); i++) { for (int i = 0; i < SDL_arraysize(placeable_infos); i++) {
if (tree_infos[i].serialization_id == serialization_id) { if (placeable_infos[i].serialization_id == serialization_id) {
info_index = i; info_index = i;
break; 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->tiles);
free(result->trees); free(result->placeables);
log_error("Failed to read tree pos.x from map file."); log_error("Failed to read placeable pos.x from map file.");
return false; 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->tiles);
free(result->trees); free(result->placeables);
log_error("Failed to read tree pos.y from map file."); log_error("Failed to read placeable pos.y from map file.");
return false; return false;
} }
} }
@@ -640,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"); 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) { if (result->num_placeables) {
result->trees_buffer = renderer_buffer_create(R_BUFFER_USAGE_VERTEX, result->num_trees * sizeof(*result->trees), result->trees, "trees_buffer"); 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."); SDL_Log("Loaded map file.");
@@ -897,64 +933,70 @@ static bool recreate_tile_textures() {
return true; return true;
} }
static bool recreate_tree_textures() { static bool recreate_placeable_textures() {
smol_atlas_t *tree_atlas = sma_atlas_create(TREE_ATLAS_SIZE, TREE_ATLAS_SIZE); smol_atlas_t *placeable_atlas = sma_atlas_create(PLACEABLE_ATLAS_SIZE, PLACEABLE_ATLAS_SIZE);
smol_atlas_item_t **tree_atlas_items = (smol_atlas_item_t **)SDL_calloc(SDL_arraysize(tree_infos), sizeof(smol_atlas_item_t *)); 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(sma_atlas_destroy(placeable_atlas));
defer(SDL_free(tree_atlas_items)); 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; 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; int width = 0, height = 0;
if (!stbi_info(path, &width, &height, NULL)) if (!stbi_info(path, &width, &height, NULL))
return false; return false;
tree_atlas_items[i] = sma_item_add(tree_atlas, width, height); placeable_atlas_items[i] = sma_item_add(placeable_atlas, width, height);
if (!tree_atlas_items[i]) if (!placeable_atlas_items[i])
return false; 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"); 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 (!tree_textures_atlas) { if (!placeable_textures_atlas) {
log_error("Failed to create texture."); log_error("Failed to create texture.");
return false; 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"); 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 (!tree_textures_atlas_imgui) { if (!placeable_textures_atlas_imgui) {
log_error("Failed to create texture."); log_error("Failed to create texture.");
return false; 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; 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; int width = 0, height = 0;
stbi_uc *data = stbi_load(path, &width, &height, NULL, 4); stbi_uc *data = stbi_load(path, &width, &height, NULL, 4);
if (!data) { if (!data) {
log_error("Failed to load texture (\"%s\"). Exiting.", path); log_error("Failed to load texture (\"%s\"). Exiting.", path);
renderer_texture_destroy(tree_textures_atlas); renderer_texture_destroy(placeable_textures_atlas);
tree_textures_atlas = NULL; placeable_textures_atlas = NULL;
renderer_texture_destroy(tree_textures_atlas_imgui); renderer_texture_destroy(placeable_textures_atlas_imgui);
tree_textures_atlas_imgui = NULL; placeable_textures_atlas_imgui = NULL;
return false; return false;
} }
tree_uvs[i].x = sma_item_x(tree_atlas_items[i]); placeable_uvs[i].x = sma_item_x(placeable_atlas_items[i]);
tree_uvs[i].y = sma_item_y(tree_atlas_items[i]); placeable_uvs[i].y = sma_item_y(placeable_atlas_items[i]);
tree_uvs[i].z = sma_item_x(tree_atlas_items[i]) + sma_item_width (tree_atlas_items[i]); placeable_uvs[i].z = sma_item_x(placeable_atlas_items[i]) + sma_item_width (placeable_atlas_items[i]);
tree_uvs[i].w = sma_item_y(tree_atlas_items[i]) + sma_item_height(tree_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); placeable_sizes_and_offsets[i].x = (float)width / 32.0f;
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].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); 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; return true;
} }
@@ -978,10 +1020,10 @@ static bool imgui_time_picker(const char *label, int time[3]) {
} }
static Uint32 get_corner_info(Sint32 tile_pos_x, Sint32 tile_pos_y) { 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) 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; return 0;
return tile_infos[current_map.tiles[tile_pos_y * current_map.size.x + tile_pos_x]].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) { static Uint32 find_matching_tile(Uint32 corner_info) {
@@ -1008,19 +1050,19 @@ static void change_map_tile(Sint32 pos_x, Sint32 pos_y, TileKind kind) {
corner_infos[i] = corner_infos[i] ^ ((corner_infos[i] ^ ((kind << 24) | (kind << 16) | (kind << 8) | kind)) & replace_mask); corner_infos[i] = corner_infos[i] ^ ((corner_infos[i] ^ ((kind << 24) | (kind << 16) | (kind << 8) | kind)) & replace_mask);
} }
if (0 <= pos_x + 0 && pos_x + 0 < current_map.size.x && 0 <= pos_y + 1 && pos_y + 1 < current_map.size.y) if (0 <= pos_x + 0 && pos_x + 0 < current_map->size.x && 0 <= pos_y + 1 && pos_y + 1 < current_map->size.y)
current_map.tiles[(pos_y + 1) * current_map.size.x + pos_x + 0] = find_matching_tile(corner_infos[0]); current_map->tiles[(pos_y + 1) * current_map->size.x + pos_x + 0] = find_matching_tile(corner_infos[0]);
if (0 <= pos_x + 1 && pos_x + 1 < current_map.size.x && 0 <= pos_y + 1 && pos_y + 1 < current_map.size.y) if (0 <= pos_x + 1 && pos_x + 1 < current_map->size.x && 0 <= pos_y + 1 && pos_y + 1 < current_map->size.y)
current_map.tiles[(pos_y + 1) * current_map.size.x + pos_x + 1] = find_matching_tile(corner_infos[1]); current_map->tiles[(pos_y + 1) * current_map->size.x + pos_x + 1] = find_matching_tile(corner_infos[1]);
if (0 <= pos_x + 1 && pos_x + 1 < current_map.size.x && 0 <= pos_y + 0 && pos_y + 0 < current_map.size.y) if (0 <= pos_x + 1 && pos_x + 1 < 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 + 1] = find_matching_tile(corner_infos[2]); current_map->tiles[(pos_y + 0) * current_map->size.x + pos_x + 1] = find_matching_tile(corner_infos[2]);
if (0 <= pos_x + 0 && pos_x + 0 < current_map.size.x && 0 <= pos_y + 0 && pos_y + 0 < current_map.size.y) 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]); current_map->tiles[(pos_y + 0) * current_map->size.x + pos_x + 0] = find_matching_tile(corner_infos[3]);
renderer_texture_update(current_map.texture, 0, 0, current_map.size.x, current_map.size.y, current_map.tiles, current_map.size.x * sizeof(Uint16)); renderer_texture_update(current_map->texture, 0, 0, current_map->size.x, current_map->size.y, current_map->tiles, current_map->size.x * sizeof(Uint16));
} }
static void SameLineOrWrap(const ImVec2& size) { static void SameLineOrWrap(const ImVec2& size) {
@@ -1086,8 +1128,8 @@ static bool init_resources() {
return false; return false;
} }
if (!recreate_tree_textures()) { if (!recreate_placeable_textures()) {
log_error("Failed to create tree textures."); log_error("Failed to create placeable textures.");
return false; return false;
} }
@@ -1158,87 +1200,87 @@ static void process_event_editor(SDL_Event event) {
} }
if (event.button.button == SDL_BUTTON_LEFT) { 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) { 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_tree = -1; Sint32 found_placeable = -1;
for (Sint32 i = 0; i < current_map.num_trees; i++) { for (Sint32 i = 0; i < current_map->num_placeables; i++) {
if ((current_map.trees[i].pos.x == entity_pos.x) && (current_map.trees[i].pos.y == entity_pos.y)) { if ((current_map->placeables[i].pos.x == entity_pos.x) && (current_map->placeables[i].pos.y == entity_pos.y)) {
found_tree = i; found_placeable = i;
break; break;
} }
} }
if (found_tree != -1) { if (found_placeable != -1) {
Tree tmp = current_map.trees[found_tree]; Placeable tmp = current_map->placeables[found_placeable];
SDL_memmove(&current_map.trees[found_tree], &current_map.trees[found_tree + 1], (current_map.num_trees - (found_tree + 1)) * sizeof(*current_map.trees)); SDL_memmove(&current_map->placeables[found_placeable], &current_map->placeables[found_placeable + 1], (current_map->num_placeables - (found_placeable + 1)) * sizeof(*current_map->placeables));
current_map.trees[current_map.num_trees - 1] = tmp; current_map->placeables[current_map->num_placeables - 1] = tmp;
} else { } else {
current_map.trees = (Tree *)SDL_realloc(current_map.trees, (current_map.num_trees + 1) * sizeof(*current_map.trees)); current_map->placeables = (Placeable *)SDL_realloc(current_map->placeables, (current_map->num_placeables + 1) * sizeof(*current_map->placeables));
current_map.trees[current_map.num_trees] = { current_map->placeables[current_map->num_placeables] = {
.pos = entity_pos, .pos = entity_pos,
.kind = (Uint32)selected_tree, .kind = (Uint32)selected_placeable,
}; };
current_map.num_trees++; current_map->num_placeables++;
} }
std::stable_sort(&current_map.trees[0], &current_map.trees[current_map.num_trees], [](const Tree &a, const Tree &b){ return a.pos.y > b.pos.y; }); std::stable_sort(&current_map->placeables[0], &current_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); if (current_map->placeables_buffer) renderer_buffer_destroy(current_map->placeables_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"); 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) { if (show_placeable_editor && selected_placeable == -1) {
for (Sint32 i = 0; i < current_map.num_trees; i++) { for (Sint32 i = 0; i < current_map->num_placeables; i++) {
if ((current_map.trees[i].pos.x == entity_pos.x) && (current_map.trees[i].pos.y == entity_pos.y)) { if ((current_map->placeables[i].pos.x == entity_pos.x) && (current_map->placeables[i].pos.y == entity_pos.y)) {
SDL_memmove(&current_map.trees[i], &current_map.trees[i + 1], (current_map.num_trees - (i + 1)) * sizeof(*current_map.trees)); SDL_memmove(&current_map->placeables[i], &current_map->placeables[i + 1], (current_map->num_placeables - (i + 1)) * sizeof(*current_map->placeables));
current_map.num_trees--; current_map->num_placeables--;
break; break;
} }
} }
if (current_map.trees_buffer) renderer_buffer_destroy(current_map.trees_buffer); if (current_map->placeables_buffer) renderer_buffer_destroy(current_map->placeables_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->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) { if (selected_tile_kind != -1) {
change_map_tile(tile_pos.x, tile_pos.y, (TileKind)selected_tile_kind); change_map_tile(tile_pos.x, tile_pos.y, (TileKind)selected_tile_kind);
if (-1 <= tile_pos.x && tile_pos.x < current_map.size.x && -1 <= tile_pos.y && tile_pos.y < current_map.size.y) { if (-1 <= tile_pos.x && tile_pos.x < current_map->size.x && -1 <= tile_pos.y && tile_pos.y < current_map->size.y) {
dragging_tile_change = true; dragging_tile_change = true;
} }
} }
if (0 <= tile_pos.x && tile_pos.x < current_map.size.x && 0 <= tile_pos.y && tile_pos.y < current_map.size.y) { if (0 <= tile_pos.x && tile_pos.x < current_map->size.x && 0 <= tile_pos.y && tile_pos.y < current_map->size.y) {
dragging_tile_change = true; dragging_tile_change = true;
} }
SDL_Keymod modifiers = SDL_GetModState(); SDL_Keymod modifiers = SDL_GetModState();
if (modifiers & SDL_KMOD_SHIFT && tile_pos.x <= -1) { if (modifiers & SDL_KMOD_SHIFT && tile_pos.x <= -1) {
if(modifiers & SDL_KMOD_CTRL) if(modifiers & SDL_KMOD_CTRL)
change_map_size(&current_map, 'W', -1); change_map_size(current_map, 'W', -1);
else else
change_map_size(&current_map, 'W', 1); change_map_size(current_map, 'W', 1);
} }
if (modifiers & SDL_KMOD_SHIFT && tile_pos.x == current_map.size.x) { if (modifiers & SDL_KMOD_SHIFT && tile_pos.x == current_map->size.x) {
if (modifiers & SDL_KMOD_CTRL) if (modifiers & SDL_KMOD_CTRL)
change_map_size(&current_map, 'E', -1); change_map_size(current_map, 'E', -1);
else else
change_map_size(&current_map, 'E', 1); change_map_size(current_map, 'E', 1);
} }
if (modifiers & SDL_KMOD_SHIFT && tile_pos.y <= -1) { if (modifiers & SDL_KMOD_SHIFT && tile_pos.y <= -1) {
if (modifiers & SDL_KMOD_CTRL) if (modifiers & SDL_KMOD_CTRL)
change_map_size(&current_map, 'N', -1); change_map_size(current_map, 'N', -1);
else else
change_map_size(&current_map, 'N', 1); change_map_size(current_map, 'N', 1);
} }
if (modifiers & SDL_KMOD_SHIFT && tile_pos.y == current_map.size.y) { if (modifiers & SDL_KMOD_SHIFT && tile_pos.y == current_map->size.y) {
if (modifiers & SDL_KMOD_CTRL) if (modifiers & SDL_KMOD_CTRL)
change_map_size(&current_map, 'S', -1); change_map_size(current_map, 'S', -1);
else else
change_map_size(&current_map, 'S', 1); change_map_size(current_map, 'S', 1);
} }
} }
} break; } break;
@@ -1256,8 +1298,8 @@ static void process_event_editor(SDL_Event event) {
vec2 floor_intersection = get_floor_intersection_of_mouse(vec2(event.button.x, event.button.y)); vec2 floor_intersection = get_floor_intersection_of_mouse(vec2(event.button.x, event.button.y));
i32vec2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection); i32vec2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
Sint32 tile_x = clamp(0, tile_pos.x, current_map.size.x - 1); Sint32 tile_x = clamp(0, tile_pos.x, current_map->size.x - 1);
Sint32 tile_y = clamp(0, tile_pos.y, current_map.size.y - 1); Sint32 tile_y = clamp(0, tile_pos.y, current_map->size.y - 1);
i32vec2 drag_start = grid_tile_pos_from_floor_intersection(drag_start_pos); i32vec2 drag_start = grid_tile_pos_from_floor_intersection(drag_start_pos);
@@ -1269,11 +1311,11 @@ static void process_event_editor(SDL_Event event) {
for (Sint32 y = start_y; y <= end_y; y++) { for (Sint32 y = start_y; y <= end_y; y++) {
for (Sint32 x = start_x; x <= end_x; x++) { for (Sint32 x = start_x; x <= end_x; x++) {
current_map.tiles[x + current_map.size.x * y] = selected_tile; current_map->tiles[x + current_map->size.x * y] = selected_tile;
} }
} }
renderer_texture_update(current_map.texture, 0, 0, current_map.size.x, current_map.size.y, current_map.tiles, current_map.size.x * sizeof(Uint16)); renderer_texture_update(current_map->texture, 0, 0, current_map->size.x, current_map->size.y, current_map->tiles, current_map->size.x * sizeof(Uint16));
} }
dragging_tile_change = false; dragging_tile_change = false;
@@ -1308,12 +1350,13 @@ static void update_state_editor() {
ImGui::NewFrame(); ImGui::NewFrame();
const ImGuiViewport *viewport = ImGui::GetMainViewport(); const ImGuiViewport *viewport = ImGui::GetMainViewport();
ImGuiStyle &style = ImGui::GetStyle();
if (ImGui::BeginMainMenuBar()) { if (ImGui::BeginMainMenuBar()) {
if (ImGui::BeginMenu("File")) { if (ImGui::BeginMenu("File")) {
if (ImGui::MenuItem("Reload")) { if (ImGui::MenuItem("Reload")) {
recreate_tile_textures(); recreate_tile_textures();
recreate_tree_textures(); recreate_placeable_textures();
} }
if (ImGui::MenuItem("Save")) { if (ImGui::MenuItem("Save")) {
@@ -1334,7 +1377,8 @@ static void update_state_editor() {
if (ImGui::BeginMenu("Edit")) { if (ImGui::BeginMenu("Edit")) {
ImGui::MenuItem("Tile Picker", NULL, &show_tile_picker); 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(); ImGui::EndMenu();
} }
@@ -1349,7 +1393,8 @@ static void update_state_editor() {
ImGuiID left_dock = ImGui::DockBuilderSplitNode(main_viewport_dock, ImGuiDir_Left, 0.2f, NULL, NULL); ImGuiID left_dock = ImGui::DockBuilderSplitNode(main_viewport_dock, ImGuiDir_Left, 0.2f, NULL, NULL);
ImGui::DockBuilderDockWindow("Tile Picker", left_dock); 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); ImGui::DockBuilderFinish(main_viewport_dock);
} }
ImGui::DockSpaceOverViewport(main_viewport_dock, ImGui::GetMainViewport(), ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode); ImGui::DockSpaceOverViewport(main_viewport_dock, ImGui::GetMainViewport(), ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_NoDockingOverCentralNode);
@@ -1468,27 +1513,80 @@ static void update_state_editor() {
selected_tile_kind = -1; selected_tile_kind = -1;
} }
if (show_tree_editor) { if (show_placeable_editor) {
if (ImGui::Begin("Trees", &show_tree_editor, ImGuiWindowFlags_NoFocusOnAppearing)) { if (ImGui::Begin("Placeables", &show_placeable_editor, ImGuiWindowFlags_NoFocusOnAppearing)) {
ImGuiStyle &style = ImGui::GetStyle(); if (SelectableImage("##placeable", placeable_textures_atlas_imgui, ImVec2(64, 64), vec2(0, 0), vec2(0, 0), selected_placeable == -1))
if (SelectableImage("##tree", tree_textures_atlas_imgui, ImVec2(64, 64), vec2(0, 0), vec2(0, 0), selected_tree == -1)) selected_placeable = -1;
selected_tree = -1;
for (int i = 0; i < SDL_arraysize(tree_infos); i++) { for (int i = 0; i < SDL_arraysize(placeable_infos); i++) {
ImGui::PushID(i); ImGui::PushID(i);
if (i != 0) vec2 size = placeable_sizes_and_offsets[i].xy() * 32.0f;
SameLineOrWrap(ImVec2(64, 1));
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)) if (i != 0)
selected_tree = i; 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::PopID();
} }
} }
ImGui::End(); ImGui::End();
} else { } else {
selected_tree = -1; selected_placeable = -1;
}
auto add_world_modal = ImGui::GetID("Add World");
ImGui::SetNextWindowSize(ImVec2(200, 0), ImGuiCond_Appearing);
if (ImGui::BeginPopupModal("Add World")) {
static Map new_map = {};
ImGui::SetNextItemWidth(-1);
ImGui::InputTextWithHint("##Name", "Name", new_map.name, SDL_arraysize(new_map.name));
float button_width = (ImGui::GetContentRegionAvail().x - style.ItemSpacing.x) * 0.5f;
if (ImGui::Button("Cancel", ImVec2(button_width, 0))) ImGui::CloseCurrentPopup();
ImGui::SameLine();
if (ImGui::Button("Add", ImVec2(button_width, 0))) {
new_map.size = vec2(2, 2);
new_map.tiles = (Uint16 *)SDL_calloc(new_map.size.x * new_map.size.y, sizeof(*new_map.tiles));
new_map.texture = renderer_texture_create(R_TEXTURE_FORMAT_R16_UINT, R_TEXTURE_USAGE_STORAGE, false, new_map.size.x, new_map.size.y, new_map.tiles, "map_texture");
size_t current_map_index = current_map - loaded_maps;
loaded_maps = (Map *)SDL_realloc(loaded_maps, (num_loaded_maps + 1) * sizeof(new_map));
loaded_maps[num_loaded_maps++] = new_map;
current_map = &loaded_maps[current_map_index];
save_map(&new_map);
save_worlds_list();
new_map = {};
ImGui::CloseCurrentPopup();
}
ImGui::EndPopup();
}
if (show_world_editor) {
if (ImGui::Begin("Worlds", &show_world_editor, ImGuiWindowFlags_NoFocusOnAppearing)) {
if(ImGui::BeginListBox("##Worlds", ImVec2(-1, 0))) {
for (int i = 0; i < num_loaded_maps; i++) {
if (ImGui::Selectable(loaded_maps[i].name, current_map == &loaded_maps[i])) {
current_map = &loaded_maps[i];
}
}
ImGui::EndListBox();
if (ImGui::Button("Add World", ImVec2(-1, 0))) {
ImGui::OpenPopup(add_world_modal);
}
}
}
ImGui::End();
} }
ImGui::SetNextWindowPos({ viewport->WorkPos.x + viewport->WorkSize.x - 10.0f, viewport->WorkPos.y + 10.0f }, ImGuiCond_Always, { 1.0f, 0.0f }); ImGui::SetNextWindowPos({ viewport->WorkPos.x + viewport->WorkSize.x - 10.0f, viewport->WorkPos.y + 10.0f }, ImGuiCond_Always, { 1.0f, 0.0f });
@@ -1530,9 +1628,9 @@ static void render_editor() {
vec2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos); vec2 floor_intersection = get_floor_intersection_of_mouse(mouse_pos);
i32vec2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection); i32vec2 tile_pos = grid_tile_pos_from_floor_intersection(floor_intersection);
per_frame.map_width = current_map.size.x; per_frame.map_width = current_map->size.x;
per_frame.grid_width = selected_tile != -1 ? current_map.size.x : current_map.size.x + 1; per_frame.grid_width = selected_tile != -1 ? current_map->size.x : current_map->size.x + 1;
per_frame.grid_height = selected_tile != -1 ? current_map.size.y : current_map.size.y + 1; per_frame.grid_height = selected_tile != -1 ? current_map->size.y : current_map->size.y + 1;
per_frame.grid_offset = selected_tile != -1 ? vec2(-0.5f, -0.5f) : vec2(-1.0f, -1.0f); per_frame.grid_offset = selected_tile != -1 ? vec2(-0.5f, -0.5f) : vec2(-1.0f, -1.0f);
per_frame.mouse = tile_pos; per_frame.mouse = tile_pos;
@@ -1578,8 +1676,8 @@ static void render_editor() {
{ {
ZoneScopedN("Draw Map"); ZoneScopedN("Draw Map");
renderer_frame_set_shader(R_SHADER_WORLD); renderer_frame_set_shader(R_SHADER_WORLD);
renderer_frame_draw(NULL, NULL, NULL, 6, current_map.size.y * current_map.size.x, &(R_Draw_Resources){ renderer_frame_draw(NULL, NULL, NULL, 6, current_map->size.y * current_map->size.x, &(R_Draw_Resources){
.vertex_storage_textures = (R_Texture[]){ current_map.texture }, .vertex_storage_textures = (R_Texture[]){ current_map->texture },
.vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer },
.num_vertex_storage_textures = 1, .num_vertex_storage_textures = 1,
@@ -1595,16 +1693,18 @@ static void render_editor() {
}); });
} }
if (current_map.num_trees) { if (current_map->num_placeables) {
ZoneScopedN("Draw Trees"); ZoneScopedN("Draw Placeables");
renderer_frame_set_shader(R_SHADER_TREE); renderer_frame_set_shader(R_SHADER_PLACEABLE);
renderer_frame_draw(NULL, NULL, current_map.trees_buffer, 6, current_map.num_trees, &(R_Draw_Resources){ 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 }, .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer },
.num_vertex_storage_buffers = 1,
.num_vertex_uniform_buffers = 2, .num_vertex_uniform_buffers = 2,
.fragment_sampled_textures = (R_Texture[]){ tree_textures_atlas }, .fragment_sampled_textures = (R_Texture[]){ placeable_textures_atlas },
.fragment_storage_buffers = (R_Buffer[]){ tree_uvs_buffer }, .fragment_storage_buffers = (R_Buffer[]){ placeable_uvs_buffer },
.fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer }, .fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer },
.num_fragment_sampled_textures = 1, .num_fragment_sampled_textures = 1,
@@ -1711,10 +1811,10 @@ static void update_state_game() {
bool is_movement_key_pressed = keyboard_state[SDL_SCANCODE_W] || keyboard_state[SDL_SCANCODE_A] || keyboard_state[SDL_SCANCODE_S] || keyboard_state[SDL_SCANCODE_D] || keyboard_state[SDL_SCANCODE_UP] || keyboard_state[SDL_SCANCODE_LEFT] || keyboard_state[SDL_SCANCODE_DOWN] || keyboard_state[SDL_SCANCODE_RIGHT]; bool is_movement_key_pressed = keyboard_state[SDL_SCANCODE_W] || keyboard_state[SDL_SCANCODE_A] || keyboard_state[SDL_SCANCODE_S] || keyboard_state[SDL_SCANCODE_D] || keyboard_state[SDL_SCANCODE_UP] || keyboard_state[SDL_SCANCODE_LEFT] || keyboard_state[SDL_SCANCODE_DOWN] || keyboard_state[SDL_SCANCODE_RIGHT];
if (!player.is_moving && (queued_movement || is_movement_key_pressed)) { if (!player.is_moving && (queued_movement || is_movement_key_pressed)) {
switch (queued_movement_direction) { switch (queued_movement_direction) {
case DIR_UP: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, 1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break; case DIR_UP: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, 1), current_map->size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_LEFT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2(-1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break; case DIR_LEFT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2(-1, 0), current_map->size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_DOWN: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, -1), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break; case DIR_DOWN: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 0, -1), current_map->size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
case DIR_RIGHT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 1, 0), current_map.size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break; case DIR_RIGHT: { player.direction = queued_movement_direction; player.target_position = clamp(ivec2(0, 0), player.position + ivec2( 1, 0), current_map->size - ivec2(2, 2)); if (player.target_position != player.position) player.is_moving = true; } break;
} }
} }
queued_movement = false; queued_movement = false;
@@ -1759,7 +1859,7 @@ static void render_game() {
mat4x4 view_projection_matrix = view_matrix * projection_matrix; mat4x4 view_projection_matrix = view_matrix * projection_matrix;
renderer_buffer_update(view_projection_matrix_buffer, 0, sizeof(view_projection_matrix), &view_projection_matrix); renderer_buffer_update(view_projection_matrix_buffer, 0, sizeof(view_projection_matrix), &view_projection_matrix);
per_frame.map_width = current_map.size.x; per_frame.map_width = current_map->size.x;
renderer_buffer_update(per_frame_buffer, 0, sizeof(per_frame), &per_frame); renderer_buffer_update(per_frame_buffer, 0, sizeof(per_frame), &per_frame);
} }
@@ -1795,8 +1895,8 @@ static void render_game() {
{ {
ZoneScopedN("Draw Map"); ZoneScopedN("Draw Map");
renderer_frame_set_shader(R_SHADER_WORLD); renderer_frame_set_shader(R_SHADER_WORLD);
renderer_frame_draw(NULL, NULL, NULL, 6, current_map.size.y * current_map.size.x, &(R_Draw_Resources){ renderer_frame_draw(NULL, NULL, NULL, 6, current_map->size.y * current_map->size.x, &(R_Draw_Resources){
.vertex_storage_textures = (R_Texture[]){ current_map.texture }, .vertex_storage_textures = (R_Texture[]){ current_map->texture },
.vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer }, .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer },
.num_vertex_storage_textures = 1, .num_vertex_storage_textures = 1,
@@ -1812,16 +1912,18 @@ static void render_game() {
}); });
} }
if (current_map.num_trees) { if (current_map->num_placeables) {
ZoneScopedN("Draw Trees"); ZoneScopedN("Draw Placeables");
renderer_frame_set_shader(R_SHADER_TREE); renderer_frame_set_shader(R_SHADER_PLACEABLE);
renderer_frame_draw(NULL, NULL, current_map.trees_buffer, 6, current_map.num_trees, &(R_Draw_Resources){ 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 }, .vertex_uniform_buffers = (R_Buffer[]){ view_projection_matrix_buffer, per_frame_buffer },
.num_vertex_storage_buffers = 1,
.num_vertex_uniform_buffers = 2, .num_vertex_uniform_buffers = 2,
.fragment_sampled_textures = (R_Texture[]){ tree_textures_atlas }, .fragment_sampled_textures = (R_Texture[]){ placeable_textures_atlas },
.fragment_storage_buffers = (R_Buffer[]){ tree_uvs_buffer }, .fragment_storage_buffers = (R_Buffer[]){ placeable_uvs_buffer },
.fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer }, .fragment_uniform_buffers = (R_Buffer[]){ tint_color_buffer },
.num_fragment_sampled_textures = 1, .num_fragment_sampled_textures = 1,
@@ -2048,10 +2150,15 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
if (!load_map("map", &current_map)) { loaded_maps = (Map *)SDL_calloc(SDL_arraysize(world_names), sizeof(*loaded_maps));
log_error("Failed to load initial map. Exiting."); for (int i = 0; i < SDL_arraysize(world_names); i++) {
if (!load_map(world_names[i], &loaded_maps[i])) {
log_error("Failed to load map '%s'. Exiting.", world_names[i]);
return 1; return 1;
} }
}
num_loaded_maps = SDL_arraysize(world_names);
current_map = &loaded_maps[0];
mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL); mixer = MIX_CreateMixerDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, NULL);
if (!mixer) { if (!mixer) {
+1 -1
View File
@@ -11,7 +11,7 @@ typedef enum : Uint32 {
R_SHADER_CHARACTER, R_SHADER_CHARACTER,
R_SHADER_CHARACTER_SHADOW, R_SHADER_CHARACTER_SHADOW,
R_SHADER_WORLD, R_SHADER_WORLD,
R_SHADER_TREE, R_SHADER_PLACEABLE,
R_SHADER_GRID, R_SHADER_GRID,
R_SHADER_COUNT, R_SHADER_COUNT,
} R_Shader; } R_Shader;
+5 -5
View File
@@ -803,9 +803,9 @@ bool renderer_init(SDL_Window *window_) {
SDL_ReleaseGPUShader(device, fragment_shader); SDL_ReleaseGPUShader(device, fragment_shader);
} }
{ // Tree { // Placeable
const Uint8 shader_source[] = { const Uint8 shader_source[] = {
#embed "shaders/spirv/tree.spv" #embed "shaders/spirv/placeable.spv"
}; };
SDL_GPUShader *vertex_shader = SDL_CreateGPUShader(device, &(SDL_GPUShaderCreateInfo){ SDL_GPUShader *vertex_shader = SDL_CreateGPUShader(device, &(SDL_GPUShaderCreateInfo){
@@ -818,7 +818,7 @@ bool renderer_init(SDL_Window *window_) {
.num_samplers = 0, .num_samplers = 0,
.num_storage_textures = 0, .num_storage_textures = 0,
.num_storage_buffers = 0, .num_storage_buffers = 1,
.num_uniform_buffers = 2, .num_uniform_buffers = 2,
}); });
@@ -837,9 +837,9 @@ bool renderer_init(SDL_Window *window_) {
}); });
SDL_PropertiesID properties = SDL_CreateProperties(); 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, .vertex_shader = vertex_shader,
.fragment_shader = fragment_shader, .fragment_shader = fragment_shader,
+10 -8
View File
@@ -971,9 +971,9 @@ bool renderer_init(SDL_Window *window_) {
wgpuShaderModuleRelease(shader); wgpuShaderModuleRelease(shader);
} }
{ // Tree { // Placeable
const char shader_source[] = { const char shader_source[] = {
#embed "shaders/wgsl/tree.wgsl" #embed "shaders/wgsl/placeable.wgsl"
}; };
WGPUShaderModule shader = wgpuDeviceCreateShaderModule(device, &(WGPUShaderModuleDescriptor){ WGPUShaderModule shader = wgpuDeviceCreateShaderModule(device, &(WGPUShaderModuleDescriptor){
@@ -981,19 +981,21 @@ bool renderer_init(SDL_Window *window_) {
.chain = { .next = NULL, .sType = WGPUSType_ShaderSourceWGSL }, .chain = { .next = NULL, .sType = WGPUSType_ShaderSourceWGSL },
.code = { .data = shader_source, .length = SDL_arraysize(shader_source) }, .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){ shaders[R_SHADER_PLACEABLE] = wgpuDeviceCreateRenderPipeline(device, &(WGPURenderPipelineDescriptor){
.label = { .data = "tree render_pipeline", .length = WGPU_STRLEN }, .label = { .data = "placeable render_pipeline", .length = WGPU_STRLEN },
.layout = wgpuDeviceCreatePipelineLayout(device, &(WGPUPipelineLayoutDescriptor){ .layout = wgpuDeviceCreatePipelineLayout(device, &(WGPUPipelineLayoutDescriptor){
.label = { .data = "tree pipeline_layout", .length = WGPU_STRLEN }, .label = { .data = "placeable pipeline_layout", .length = WGPU_STRLEN },
.bindGroupLayoutCount = 4, .bindGroupLayoutCount = 4,
.bindGroupLayouts = (WGPUBindGroupLayout[]){ .bindGroupLayouts = (WGPUBindGroupLayout[]){
wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){ wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){
.entryCount = 0, .entryCount = 1,
.entries = (WGPUBindGroupLayoutEntry[]){}, .entries = (WGPUBindGroupLayoutEntry[]){
{ .binding = 0, .visibility = WGPUShaderStage_Vertex, .buffer = { .type = WGPUBufferBindingType_ReadOnlyStorage } },
},
}), }),
wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){ wgpuDeviceCreateBindGroupLayout(device, &(WGPUBindGroupLayoutDescriptor){
.entryCount = 2, .entryCount = 2,
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -37,7 +37,7 @@ VertexShaderOutput main_vertex(VertexShaderInput input) {
default: {} default: {}
} }
output.pos = mul(float4(input.world_pos + vertex_pos, 0, 1), view_projection_matrix); output.pos = mul(float4(input.world_pos + vertex_pos + float2(0, 0.35), 0, 1), view_projection_matrix);
uint sprite_x = bitfieldExtract(input.sprite_selection, 16, 16); uint sprite_x = bitfieldExtract(input.sprite_selection, 16, 16);
uint sprite_y = bitfieldExtract(input.sprite_selection, 0, 16); uint sprite_y = bitfieldExtract(input.sprite_selection, 0, 16);
+1 -1
View File
@@ -38,7 +38,7 @@ VertexShaderOutput main_vertex(VertexShaderInput input) {
vertex_pos *= 0.5; vertex_pos *= 0.5;
output.pos = mul(float4(input.world_pos + vertex_pos + float2(0, -0.35), 0, 1), view_projection_matrix); output.pos = mul(float4(input.world_pos + vertex_pos, 0, 1), view_projection_matrix);
output.uv = vertex_uv; output.uv = vertex_uv;
return output; return output;
@@ -23,7 +23,7 @@ struct FragmentShaderOutput {
float4 color : SV_Target; float4 color : SV_Target;
}; };
static const float2 offset = float2(0, 0.5); [vk::binding(0, 0)] StructuredBuffer<float4> placeable_sizes_and_offsets;
[shader("vertex")] [shader("vertex")]
VertexShaderOutput main_vertex(VertexShaderInput input) { VertexShaderOutput main_vertex(VertexShaderInput input) {
@@ -33,16 +33,16 @@ VertexShaderOutput main_vertex(VertexShaderInput input) {
var vertex_uv = float2(0, 0); var vertex_uv = float2(0, 0);
switch (input.vertex_index) { switch (input.vertex_index) {
case 0: { vertex_pos = float2(-1.0, 1.0); vertex_uv = float2(0, 0); } break; case 0: { vertex_pos = float2(-0.5, 0.5); vertex_uv = float2(0, 0); } break;
case 1: { vertex_pos = float2(-1.0, -1.0); vertex_uv = float2(0, 1); } break; case 1: { vertex_pos = float2(-0.5, -0.5); vertex_uv = float2(0, 1); } break;
case 2: { vertex_pos = float2( 1.0, -1.0); vertex_uv = float2(1, 1); } break; case 2: { vertex_pos = float2( 0.5, -0.5); vertex_uv = float2(1, 1); } break;
case 3: { vertex_pos = float2(-1.0, 1.0); vertex_uv = float2(0, 0); } break; case 3: { vertex_pos = float2(-0.5, 0.5); vertex_uv = float2(0, 0); } break;
case 4: { vertex_pos = float2( 1.0, -1.0); vertex_uv = float2(1, 1); } break; case 4: { vertex_pos = float2( 0.5, -0.5); vertex_uv = float2(1, 1); } break;
case 5: { vertex_pos = float2( 1.0, 1.0); vertex_uv = float2(1, 0); } break; case 5: { vertex_pos = float2( 0.5, 0.5); vertex_uv = float2(1, 0); } break;
default: {} 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.pos = mul(float4(input.pos + vertex_pos, 0, 1), view_projection_matrix);
output.uv = vertex_uv; output.uv = vertex_uv;
@@ -52,8 +52,8 @@ VertexShaderOutput main_vertex(VertexShaderInput input) {
} }
struct Block2 { struct Block2 {
CombinedTextureSampler tree_atlas; CombinedTextureSampler placeable_atlas;
StructuredBuffer<float4> tree_uvs; StructuredBuffer<float4> placeable_uvs;
}; };
struct Block3 { struct Block3 {
@@ -67,7 +67,7 @@ struct Block3 {
FragmentShaderOutput main_fragment(VertexShaderOutput input) { FragmentShaderOutput main_fragment(VertexShaderOutput input) {
var output: FragmentShaderOutput; 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); output.color = float4(output.color.rgb * block3.tint.rgb, output.color.a);
return output; return output;
+1 -1
View File
@@ -70,7 +70,7 @@ fn main_vertex( _S1 : vertexInput_0, @builtin(vertex_index) vertex_index_0 : u32
vertex_uv_0 = _S2; vertex_uv_0 = _S2;
} }
} }
output_0.pos_0 = (((mat4x4<f32>(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<f32>(_S1.world_pos_0 + vertex_pos_0, 0.0f, 1.0f)))); output_0.pos_0 = (((mat4x4<f32>(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<f32>(_S1.world_pos_0 + vertex_pos_0 + vec2<f32>(0.0f, 0.34999999403953552f), 0.0f, 1.0f))));
output_0.uv_0 = (vec2<f32>(f32((u32(_S1.sprite_selection_0>>(u32(16)))&((((u32(1)<<u32(16))-u32(1)))))), f32((u32(_S1.sprite_selection_0>>(u32(0)))&((((u32(1)<<u32(16))-u32(1))))))) + vertex_uv_0) * vec2<f32>(0.25f); output_0.uv_0 = (vec2<f32>(f32((u32(_S1.sprite_selection_0>>(u32(16)))&((((u32(1)<<u32(16))-u32(1)))))), f32((u32(_S1.sprite_selection_0>>(u32(0)))&((((u32(1)<<u32(16))-u32(1))))))) + vertex_uv_0) * vec2<f32>(0.25f);
return output_0; return output_0;
} }
+1 -1
View File
@@ -71,7 +71,7 @@ fn main_vertex( _S1 : vertexInput_0, @builtin(vertex_index) vertex_index_0 : u32
vertex_pos_0 = _S2; vertex_pos_0 = _S2;
} }
} }
output_0.pos_0 = (((mat4x4<f32>(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<f32>(_S1.world_pos_0 + vertex_pos_0 * vec2<f32>(0.5f) + vec2<f32>(0.0f, -0.34999999403953552f), 0.0f, 1.0f)))); output_0.pos_0 = (((mat4x4<f32>(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<f32>(_S1.world_pos_0 + vertex_pos_0 * vec2<f32>(0.5f), 0.0f, 1.0f))));
output_0.uv_0 = vertex_uv_0; output_0.uv_0 = vertex_uv_0;
return output_0; return output_0;
} }
@@ -1,14 +1,16 @@
@binding(0) @group(0) var<storage, read> placeable_sizes_and_offsets_0 : array<vec4<f32>>;
struct _MatrixStorage_float4x4_ColMajorstd140_0 struct _MatrixStorage_float4x4_ColMajorstd140_0
{ {
@align(16) data_0 : array<vec4<f32>, i32(4)>, @align(16) data_0 : array<vec4<f32>, i32(4)>,
}; };
@binding(0) @group(1) var<uniform> view_projection_matrix_0 : _MatrixStorage_float4x4_ColMajorstd140_0; @binding(0) @group(1) var<uniform> view_projection_matrix_0 : _MatrixStorage_float4x4_ColMajorstd140_0;
@binding(0) @group(2) var block2_tree_atlas_texture_0 : texture_2d<f32>; @binding(0) @group(2) var block2_placeable_atlas_texture_0 : texture_2d<f32>;
@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<storage, read> block2_tree_uvs_0 : array<vec4<f32>>; @binding(2) @group(2) var<storage, read> block2_placeable_uvs_0 : array<vec4<f32>>;
@binding(0) @group(3) var<uniform> block3_tint_0 : vec3<f32>; @binding(0) @group(3) var<uniform> block3_tint_0 : vec3<f32>;
struct VertexShaderOutput_0 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; var output_0 : VertexShaderOutput_0;
const _S2 : vec2<f32> = vec2<f32>(0.0f, 0.0f); const _S2 : vec2<f32> = vec2<f32>(0.0f, 0.0f);
var vertex_uv_0 : vec2<f32>;
var vertex_pos_0 : vec2<f32>; var vertex_pos_0 : vec2<f32>;
var vertex_uv_0 : vec2<f32>;
switch(vertex_index_0) switch(vertex_index_0)
{ {
case u32(0): case u32(0):
{ {
const _S3 : vec2<f32> = vec2<f32>(-1.0f, 1.0f); vertex_pos_0 = vec2<f32>(-0.5f, 0.5f);
vertex_uv_0 = _S2; vertex_uv_0 = _S2;
vertex_pos_0 = _S3;
} }
case u32(1): case u32(1):
{ {
const _S4 : vec2<f32> = vec2<f32>(-1.0f, -1.0f); const _S3 : vec2<f32> = vec2<f32>(0.0f, 1.0f);
vertex_uv_0 = vec2<f32>(0.0f, 1.0f); vertex_pos_0 = vec2<f32>(-0.5f, -0.5f);
vertex_pos_0 = _S4; vertex_uv_0 = _S3;
} }
case u32(2): case u32(2):
{ {
const _S5 : vec2<f32> = vec2<f32>(1.0f, -1.0f); const _S4 : vec2<f32> = vec2<f32>(1.0f, 1.0f);
vertex_uv_0 = vec2<f32>(1.0f, 1.0f); vertex_pos_0 = vec2<f32>(0.5f, -0.5f);
vertex_pos_0 = _S5; vertex_uv_0 = _S4;
} }
case u32(3): case u32(3):
{ {
const _S6 : vec2<f32> = vec2<f32>(-1.0f, 1.0f); vertex_pos_0 = vec2<f32>(-0.5f, 0.5f);
vertex_uv_0 = _S2; vertex_uv_0 = _S2;
vertex_pos_0 = _S6;
} }
case u32(4): case u32(4):
{ {
const _S7 : vec2<f32> = vec2<f32>(1.0f, -1.0f); const _S5 : vec2<f32> = vec2<f32>(1.0f, 1.0f);
vertex_uv_0 = vec2<f32>(1.0f, 1.0f); vertex_pos_0 = vec2<f32>(0.5f, -0.5f);
vertex_pos_0 = _S7; vertex_uv_0 = _S5;
} }
case u32(5): case u32(5):
{ {
const _S8 : vec2<f32> = vec2<f32>(1.0f, 1.0f); const _S6 : vec2<f32> = vec2<f32>(1.0f, 0.0f);
vertex_uv_0 = vec2<f32>(1.0f, 0.0f); vertex_pos_0 = vec2<f32>(0.5f, 0.5f);
vertex_pos_0 = _S8; vertex_uv_0 = _S6;
} }
default : default :
{ {
vertex_uv_0 = _S2;
vertex_pos_0 = _S2; vertex_pos_0 = _S2;
vertex_uv_0 = _S2;
} }
} }
output_0.pos_0 = (((mat4x4<f32>(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<f32>(vec2<f32>(_S1.pos_1) + (vertex_pos_0 + vec2<f32>(0.0f, 0.5f)), 0.0f, 1.0f)))); output_0.pos_0 = (((mat4x4<f32>(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<f32>(vec2<f32>(_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.uv_0 = vertex_uv_0;
output_0.kind_0 = _S1.kind_1; output_0.kind_0 = _S1.kind_1;
return output_0; return output_0;
@@ -89,16 +89,16 @@ fn CombinedTextureSampler_Sample_0( this_texture_0 : texture_2d<f32>, this_samp
fn pixel_art_sample_0( input_texture_texture_0 : texture_2d<f32>, input_texture_sampler_0 : sampler, input_uv_0 : vec2<f32>, tree_uv_0 : vec4<f32>) -> vec4<f32> fn pixel_art_sample_0( input_texture_texture_0 : texture_2d<f32>, input_texture_sampler_0 : sampler, input_uv_0 : vec2<f32>, tree_uv_0 : vec4<f32>) -> vec4<f32>
{ {
var dimensions_0 : vec2<f32>; var dimensions_0 : vec2<f32>;
var _S9 : f32 = dimensions_0[i32(0)]; var _S7 : f32 = dimensions_0[i32(0)];
var _S10 : f32 = dimensions_0[i32(1)]; var _S8 : f32 = dimensions_0[i32(1)];
{var dim = textureDimensions((input_texture_texture_0));((_S9)) = f32(dim.x);((_S10)) = f32(dim.y);}; {var dim = textureDimensions((input_texture_texture_0));((_S7)) = f32(dim.x);((_S8)) = f32(dim.y);};
dimensions_0[i32(0)] = _S9; dimensions_0[i32(0)] = _S7;
dimensions_0[i32(1)] = _S10; dimensions_0[i32(1)] = _S8;
var _S11 : vec2<f32> = tree_uv_0.xy; var _S9 : vec2<f32> = tree_uv_0.xy;
var _S12 : vec2<f32> = tree_uv_0.zw; var _S10 : vec2<f32> = tree_uv_0.zw;
var _S13 : vec2<f32> = mix(_S11, _S12, input_uv_0); var _S11 : vec2<f32> = mix(_S9, _S10, input_uv_0);
var _S14 : vec2<f32> = vec2<f32>(0.5f); var _S12 : vec2<f32> = vec2<f32>(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)); 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 struct FragmentShaderOutput_0
@@ -113,11 +113,11 @@ struct pixelInput_0
}; };
@fragment @fragment
fn main_fragment( _S15 : pixelInput_0, @builtin(position) pos_2 : vec4<f32>) -> FragmentShaderOutput_0 fn main_fragment( _S13 : pixelInput_0, @builtin(position) pos_2 : vec4<f32>) -> FragmentShaderOutput_0
{ {
var output_1 : FragmentShaderOutput_0; var output_1 : FragmentShaderOutput_0;
var _S16 : vec4<f32> = pixel_art_sample_0(block2_tree_atlas_texture_0, block2_tree_atlas_sampler_0, _S15.uv_1, block2_tree_uvs_0[_S15.kind_2]); var _S14 : vec4<f32> = 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<f32>(_S16.xyz * block3_tint_0.xyz, _S16.w); output_1.color_0 = vec4<f32>(_S14.xyz * block3_tint_0.xyz, _S14.w);
return output_1; return output_1;
} }