diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-10 09:19:32 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-12-10 09:19:32 +0100 |
commit | 60c80cdca2108d05a0cd0cac8fcfc3658c4e3915 (patch) | |
tree | eb415d0cf95b79919bae5e919d1f19626786524b | |
parent | 3464b29a50c1718a298b7e48c5e9c0dd509f1bb1 (diff) |
w
-rw-r--r-- | shaders/shader.hpp | 7 | ||||
-rw-r--r-- | src/chunk-walls.cpp | 93 | ||||
-rw-r--r-- | src/chunk.cpp | 6 | ||||
-rw-r--r-- | src/chunk.hpp | 8 | ||||
-rw-r--r-- | src/wall-atlas.cpp | 28 | ||||
-rw-r--r-- | src/wall-atlas.hpp | 2 |
6 files changed, 100 insertions, 44 deletions
diff --git a/shaders/shader.hpp b/shaders/shader.hpp index c50f4681..d66cccb0 100644 --- a/shaders/shader.hpp +++ b/shaders/shader.hpp @@ -40,11 +40,12 @@ struct tile_shader final : private GL::AbstractShaderProgram template<typename T, typename... Xs> decltype(auto) draw(GL::AbstractTexture& tex, T&& mesh, Xs&&... xs); static constexpr Vector2s max_screen_tiles = {8, 8}; - static constexpr float character_depth_offset = 1 + 1./64; - static constexpr float scenery_depth_offset = 1 + 1./64; + static constexpr float character_depth_offset = 1 + 2./64; + static constexpr float scenery_depth_offset = 1 + 2./64; static constexpr float ground_depth_offset = 0; static constexpr float wall_depth_offset = 1; - static constexpr float z_depth_offset = 1 + 2./64; + static constexpr float wall_overlay_depth_offset = 1 + 1./64; + static constexpr float z_depth_offset = 1 + 4./64; static constexpr float depth_tile_size = 1.f/(TILE_MAX_DIM * 2 * max_screen_tiles.product()); static constexpr float foreshortening_factor = 0.578125f; diff --git a/src/chunk-walls.cpp b/src/chunk-walls.cpp index 1fe7685f..3d3aa2bb 100644 --- a/src/chunk-walls.cpp +++ b/src/chunk-walls.cpp @@ -35,12 +35,13 @@ using namespace floormat::Quads; using Wall::Group_; using Wall::Direction_; -template<Group_ G, bool IsWest> constexpr std::array<Vector3, 4> make_vertex_data(float depth); +template<Group_ G, bool IsWest> constexpr quad get_quad(float depth); +constexpr quad get_quad(Direction_ D, Group_ G, float depth); // ----------------------- // corner left -template<> quad constexpr make_vertex_data<Group_::corner_L, false>(float) +template<> quad constexpr get_quad<Group_::corner_L, false>(float) { constexpr float x_offset = (float)(unsigned)X; return {{ @@ -52,7 +53,7 @@ template<> quad constexpr make_vertex_data<Group_::corner_L, false>(float) } // corner right -template<> quad constexpr make_vertex_data<Group_::corner_R, true>(float) +template<> quad constexpr get_quad<Group_::corner_R, true>(float) { constexpr float y_offset = TILE_SIZE.y() - (float)(unsigned)Y; return {{ @@ -64,7 +65,7 @@ template<> quad constexpr make_vertex_data<Group_::corner_R, true>(float) } // wall north -template<> quad constexpr make_vertex_data<Group_::wall, false>(float) +template<> quad constexpr get_quad<Group_::wall, false>(float) { return {{ { X, -Y, Z }, @@ -75,7 +76,7 @@ template<> quad constexpr make_vertex_data<Group_::wall, false>(float) } // wall west -template<> quad constexpr make_vertex_data<Group_::wall, true>(float) +template<> quad constexpr get_quad<Group_::wall, true>(float) { return {{ {-X, -Y, Z }, @@ -86,7 +87,7 @@ template<> quad constexpr make_vertex_data<Group_::wall, true>(float) } // side north -template<> quad constexpr make_vertex_data<Group_::side, false>(float depth) +template<> quad constexpr get_quad<Group_::side, false>(float depth) { auto left = Vector2{X, -Y }, right = Vector2{left.x(), left.y() - depth }; @@ -99,7 +100,7 @@ template<> quad constexpr make_vertex_data<Group_::side, false>(float depth) } // side west -template<> quad constexpr make_vertex_data<Group_::side, true>(float depth) +template<> quad constexpr get_quad<Group_::side, true>(float depth) { auto right = Vector2{ -X, Y }; auto left = Vector2{ right.x() - depth, right.y() }; @@ -112,7 +113,7 @@ template<> quad constexpr make_vertex_data<Group_::side, true>(float depth) } // top north -template<> quad constexpr make_vertex_data<Group_::top, false>(float depth) +template<> quad constexpr get_quad<Group_::top, false>(float depth) { auto top_right = Vector2{X, Y - depth }, bottom_right = Vector2{top_right.x(), Y }, @@ -127,7 +128,7 @@ template<> quad constexpr make_vertex_data<Group_::top, false>(float depth) } // top west -template<> quad constexpr make_vertex_data<Group_::top, true>(float depth) +template<> quad constexpr get_quad<Group_::top, true>(float depth) { auto top_right = Vector2{-X, -Y }, top_left = Vector2{top_right.x() - depth, top_right.y() }, @@ -143,7 +144,7 @@ template<> quad constexpr make_vertex_data<Group_::top, true>(float depth) } #define FM_WALL_MAKE_CASE(name) \ - case name: return make_vertex_data<name, IsWest>(depth) + case name: return get_quad<name, IsWest>(depth) #define FM_WALL_MAKE_CASES() \ do { \ @@ -159,7 +160,7 @@ template<> quad constexpr make_vertex_data<Group_::top, true>(float depth) } \ } while (false) -quad get_vertex_data(Direction_ D, Group_ G, float depth) +constexpr quad get_quad(Direction_ D, Group_ G, float depth) { CORRADE_ASSUME(G < Group_::COUNT); CORRADE_ASSUME(D < Direction_::COUNT); @@ -179,13 +180,15 @@ quad get_vertex_data(Direction_ D, Group_ G, float depth) } } } +#undef FM_WALL_MAKE_CASES +#undef FM_WALL_MAKE_CASE // ----------------------- Array<Quads::indexes> make_indexes_() { - auto array = Array<Quads::indexes>{NoInit, chunk::max_wall_mesh_size}; - for (auto i = 0uz; i < chunk::max_wall_mesh_size; i++) + auto array = Array<Quads::indexes>{NoInit, chunk::max_wall_quad_count }; + for (auto i = 0uz; i < chunk::max_wall_quad_count; i++) array[i] = quad_indexes(i); return array; } @@ -193,38 +196,67 @@ Array<Quads::indexes> make_indexes_() ArrayView<const Quads::indexes> make_indexes(size_t max) { static const auto indexes = make_indexes_(); - fm_assert(max < chunk::max_wall_mesh_size); + fm_assert(max < chunk::max_wall_quad_count); return indexes.prefix(max); } +constexpr auto depth_offset_for_group(Group_ G) +{ + CORRADE_ASSUME(G < Group_::COUNT); + switch (G) + { + default: + return tile_shader::wall_depth_offset; + case Wall::Group_::corner_L: + case Wall::Group_::corner_R: + return tile_shader::wall_overlay_depth_offset; + } +} + } // namespace -GL::Mesh chunk::make_wall_mesh(size_t count) +GL::Mesh chunk::make_wall_mesh() { fm_debug_assert(_walls); - fm_debug_assert(count > 0); //std::array<std::array<vertex, 4>, TILE_COUNT*2> vertexes; //vertex vertexes[TILE_COUNT*2][4]; - uint32_t i = 0, N = 0; + uint32_t N = 0; - static auto vertexes = Array<vertex>{NoInit, max_wall_mesh_size}; + static auto vertexes = Array<std::array<vertex, 4>>{NoInit, max_wall_quad_count }; - for (auto k = 0uz; k < count; k++) + for (uint32_t k = 0; k < 2*TILE_COUNT; k++) { - const auto i = _walls->mesh_indexes[k]; - const auto& atlas = _walls->atlases[i]; + const auto& atlas = _walls->atlases[k]; fm_assert(atlas != nullptr); - const auto variant = _walls->variants[i]; - const local_coords pos{i / 2u}; + const auto variant = _walls->variants[k]; + const local_coords pos{k / 2u}; const auto center = Vector3(pos) * TILE_SIZE; - const auto& dir = atlas->calc_direction(i & 1 ? Wall::Direction_::W : Wall::Direction_::N); - for (auto [_, member, group] : Wall::Direction::groups) + const auto D = k & 1 ? Wall::Direction_::W : Wall::Direction_::N; + const auto& dir = atlas->calc_direction(D); + for (auto [_, member, G] : Wall::Direction::groups) { - const auto& G = dir.*member; - if (!G.is_defined) + CORRADE_ASSUME(G < Group_::COUNT); + const auto& group = dir.*member; + if (!group.is_defined) continue; - + const auto depth_offset = depth_offset_for_group(G); + auto quad = get_quad(D, G, atlas->info().depth); + for (auto& v : quad) + v += center; + + fm_debug_assert(N + quad.size() <= max_wall_quad_count); + const auto i = N++; + auto& v = vertexes[i]; + _walls->mesh_indexes[i] = (uint16_t)k; + const auto& frame = atlas->frames(group)[variant]; + const auto texcoords = Quads::texcoords_at(frame.offset, frame.size, atlas->image_size()); + const float depth = tile_shader::depth_value(pos, depth_offset); } + } + + for (auto k = 0uz; k < count; k++) + { + // ... //const auto quad = i & 1 ? wall_quad_W(center, TILE_SIZE) : wall_quad_N(center, TILE_SIZE); @@ -235,7 +267,7 @@ GL::Mesh chunk::make_wall_mesh(size_t count) v[j] = { quad[j], texcoords[j], depth, }; } - auto vertex_view = vertexes.prefix(N); + auto vertex_view = std::as_const(vertexes).prefix(N); auto index_view = make_indexes(N); //auto indexes = make_index_array<2>(count); @@ -246,6 +278,7 @@ GL::Mesh chunk::make_wall_mesh(size_t count) mesh.addVertexBuffer(GL::Buffer{vertex_view}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}, tile_shader::Depth{}) .setIndexBuffer(GL::Buffer{vert_index_view}, 0, GL::MeshIndexType::UnsignedShort) .setCount(int32_t(6 * count)); + fm_assert((size_t)mesh.count() == N*6); return mesh; } @@ -258,6 +291,7 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple return { wall_mesh, _walls->mesh_indexes, size_t(wall_mesh.count()/6) }; _walls_modified = false; +#if 0 size_t count = 0; for (auto i = 0uz; i < TILE_COUNT*2; i++) if (_walls->atlases[i]) @@ -270,6 +304,7 @@ auto chunk::ensure_wall_mesh() noexcept -> wall_mesh_tuple [this](uint16_t a, uint16_t b) { return _walls->atlases[a] < _walls->atlases[b]; }); +#endif wall_mesh = make_wall_mesh(count); return { wall_mesh, _walls->mesh_indexes, count }; diff --git a/src/chunk.cpp b/src/chunk.cpp index ca930777..2222b40a 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -23,10 +23,12 @@ bool is_log_quiet() bool chunk::empty(bool force) const noexcept { - if (!force && !_maybe_empty) + if (!force && !_maybe_empty) [[likely]] return false; for (auto i = 0uz; i < TILE_COUNT; i++) - if (!_objects.empty() || _ground && _ground->_ground_atlases[i] || _walls && _walls->empty()) + if (!_objects.empty() || + _ground && _ground->_ground_atlases[i] || + _walls && _walls->atlases[i]) return _maybe_empty = false; if (!_objects.empty()) return false; diff --git a/src/chunk.hpp b/src/chunk.hpp index b22ab5e9..d9daf436 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -118,7 +118,8 @@ struct chunk final const std::vector<std::shared_ptr<object>>& objects() const; // for drawing only - static constexpr size_t max_wall_mesh_size = TILE_COUNT*Wall::Direction_COUNT*Wall::Group_COUNT; + static constexpr size_t max_wall_quad_count = + TILE_COUNT*Wall::Direction_COUNT*Wall::Group_COUNT; private: struct ground_stuff @@ -133,8 +134,7 @@ private: { std::array<std::shared_ptr<wall_atlas>, 2*TILE_COUNT> atlases; std::array<variant_t, 2*TILE_COUNT> variants; - - std::array<uint16_t, max_wall_mesh_size> mesh_indexes; + std::array<uint16_t, max_wall_quad_count> mesh_indexes; }; Pointer<ground_stuff> _ground; @@ -169,7 +169,7 @@ private: void _remove_bbox(const bbox& x); void _add_bbox(const bbox& x); void _replace_bbox(const bbox& x0, const bbox& x, bool b0, bool b); - GL::Mesh make_wall_mesh(size_t count); + GL::Mesh make_wall_mesh(); template<size_t N> static std::array<std::array<UnsignedShort, 6>, N*TILE_COUNT> make_index_array(size_t max); }; diff --git a/src/wall-atlas.cpp b/src/wall-atlas.cpp index 3767949a..8fe19232 100644 --- a/src/wall-atlas.cpp +++ b/src/wall-atlas.cpp @@ -9,6 +9,19 @@ namespace floormat { +namespace { + +Vector2ui get_image_size(const ImageView2D& img) +{ + const Size<3> size = img.pixels().size(); + const auto width = size[1], height = size[0]; + fm_soft_assert(size[2] >= 3 && size[2] <= 4); + fm_soft_assert(width > 0 && height > 0); + return { (unsigned)width, (unsigned)height }; +} + +} // namespace + wall_atlas::wall_atlas() noexcept = default; wall_atlas::~wall_atlas() noexcept = default; @@ -42,23 +55,25 @@ wall_atlas::wall_atlas(wall_atlas_def def, String path, const ImageView2D& img) : _dir_array{std::move(def.direction_array)}, _frame_array{std::move(def.frames)}, _info{std::move(def.header)}, _path{std::move(path)}, + _image_size{get_image_size(img)}, _direction_map{def.direction_map} { { bool found = false; - for (auto [_, dir] : wall_atlas::directions) + for (auto [dir_name, dir] : wall_atlas::directions) { const auto* D = direction((size_t)dir); if (!D) continue; - for (auto [_, gmemb, gr] : Direction::groups) + for (auto [group_name, gmemb, gr] : Direction::groups) { - const auto& G = group(dir, gr); - if (!G->is_defined) + const auto& G = D->*gmemb; + if (!G.is_defined) continue; found = true; - if (G->count == 0) [[unlikely]] - fm_throw("wall_atlas '{}' defined group {}/{} has no frames!"_cf, _path, (int)dir, (int)gr); + if (G.count == 0) [[unlikely]] + fm_throw("wall_atlas '{}' defined group {}/{} has no frames!"_cf, + _path, dir_name, group_name); } } if (!found) [[unlikely]] @@ -157,6 +172,7 @@ auto wall_atlas::calc_direction(Direction_ dir) const -> const Direction& uint8_t wall_atlas::direction_count() const { return (uint8_t)_dir_array.size(); } auto wall_atlas::raw_frame_array() const -> ArrayView<const Frame> { return _frame_array; } GL::Texture2D& wall_atlas::texture() { fm_debug_assert(_texture.id()); return _texture; } +Vector2ui wall_atlas::image_size() const { return _image_size; } size_t wall_atlas::enum_to_index(enum rotation r) { diff --git a/src/wall-atlas.hpp b/src/wall-atlas.hpp index 7fb53125..515f60e1 100644 --- a/src/wall-atlas.hpp +++ b/src/wall-atlas.hpp @@ -113,6 +113,7 @@ class wall_atlas final std::vector<Frame> _frame_array; Info _info; String _path; + Vector2ui _image_size; GL::Texture2D _texture{NoCreate}; std::array<DirArrayIndex, Wall::Direction_COUNT> _direction_map; @@ -140,6 +141,7 @@ public: //StringView path() const { return _path; } GL::Texture2D& texture(); + Vector2ui image_size() const; static size_t enum_to_index(enum rotation x); static Vector2ui expected_size(unsigned depth, Group_ group); |