diff options
-rw-r--r-- | chunk.cpp | 48 | ||||
-rw-r--r-- | chunk.hpp | 45 | ||||
-rw-r--r-- | main.cpp | 105 | ||||
-rw-r--r-- | shaders/tile-shader.frag | 10 | ||||
-rw-r--r-- | shaders/tile-shader.vert | 17 | ||||
-rw-r--r-- | tile-atlas.cpp | 13 | ||||
-rw-r--r-- | tile-atlas.hpp | 16 | ||||
-rw-r--r-- | tile-shader.hpp | 1 |
8 files changed, 128 insertions, 127 deletions
@@ -2,52 +2,4 @@ namespace Magnum::Examples { -chunk_sampler_array::chunk_sampler_array() -{ - samplers.reserve(MAX_SAMPLERS); - samplers.push_back(nullptr); -} - -void chunk_sampler_array::ensure_sampler(std::size_t tile_id, const shared_sampler& x) -{ - CORRADE_INTERNAL_ASSERT(x != nullptr); - CORRADE_INTERNAL_ASSERT(tile_id < TILE_COUNT); - if (std::size_t id = sampler_map[tile_id]; id != 0) - { - const shared_sampler& old_sampler = samplers[id]; - if (x == old_sampler) - return; - } - CORRADE_INTERNAL_ASSERT(samplers.size() < MAX_SAMPLERS); - const auto id = (std::uint8_t)samplers.size(); - samplers.push_back(x); - sampler_map[tile_id] = id; -} - -void chunk_sampler_array::clear() -{ - Magnum::GL::AbstractTexture::unbindImages(0, samplers.size()); - samplers.clear(); - samplers.push_back(nullptr); - sampler_map = {}; -} - -void chunk_sampler_array::bind() -{ - Magnum::GL::AbstractTexture::unbindImages(0, MAX_SAMPLERS); - for (std::size_t i = 1; i < samplers.size(); i++) - samplers[i]->texture().bind((int)i); -} - -std::shared_ptr<tile_atlas> chunk_sampler_array::operator[](std::size_t tile_id) const -{ - CORRADE_INTERNAL_ASSERT(tile_id < TILE_COUNT); - std::size_t sampler_id = sampler_map[tile_id]; - CORRADE_INTERNAL_ASSERT(sampler_id != 0); - CORRADE_INTERNAL_ASSERT(sampler_id < samplers.size()); - const auto& sampler = samplers[sampler_id]; - CORRADE_INTERNAL_ASSERT(sampler != nullptr); - return sampler; -} - } // namespace Magnum::Examples @@ -5,8 +5,8 @@ namespace Magnum::Examples { -static constexpr std::size_t TILE_MAX_DIM = 16; -static constexpr std::size_t TILE_COUNT = TILE_MAX_DIM*TILE_MAX_DIM; +constexpr inline std::size_t TILE_MAX_DIM = 16; +constexpr inline std::size_t TILE_COUNT = TILE_MAX_DIM*TILE_MAX_DIM; struct local_coords final { std::uint8_t x = 0, y = 0; @@ -25,22 +25,6 @@ struct chunk_coords final { static_assert(max_bits*4/3/8 == sizeof(decltype(chunk_coords::x))); }; -struct chunk_sampler_array final { - using shared_sampler = std::shared_ptr<tile_atlas>; - static constexpr inline int MAX_SAMPLERS = 32; - - std::vector<std::shared_ptr<tile_atlas>> samplers; - std::array<UnsignedInt, TILE_COUNT> sampler_map = {}; - - chunk_sampler_array(); - void ensure_sampler(std::size_t tile_id, const shared_sampler& x); - std::shared_ptr<tile_atlas> operator[](std::size_t tile_id) const; - void clear(); - void bind(); - - static_assert(MAX_SAMPLERS <= 0xff); -}; - struct global_coords final { std::uint32_t x = 0, y = 0; constexpr global_coords() noexcept = default; @@ -53,8 +37,8 @@ static_assert(std::is_same_v<decltype(global_coords::x), decltype(global_coords: struct chunk final { - using index_type = decltype(local_coords::x); - using tile_index_array_type = std::array<index_type, TILE_COUNT>; + //using index_type = std::common_type_t<decltype(local_coords::x), decltype(local_coords::y)>; + //using tile_index_array_type = std::array<index_type, TILE_COUNT>; //static constexpr inline local_coords center = { (index_type)(N/2), (index_type)(N/2) }; constexpr tile& operator[](local_coords xy); @@ -62,19 +46,20 @@ struct chunk final constexpr tile& operator[](std::size_t i); constexpr const tile& operator[](std::size_t i) const; + // TODO use local_coords template<typename F> - requires std::invocable<F, tile&, int, int> + requires std::invocable<F, tile&, local_coords, std::size_t> constexpr inline void foreach_tile(F&& fun) { foreach_tile_<F, chunk&>(std::forward<F>(fun)); } template<typename F> - requires std::invocable<F, const tile&, int, int> + requires std::invocable<F, const tile&, local_coords, std::size_t> constexpr inline void foreach_tile(F&& fun) const { foreach_tile_<F, const chunk&>(std::forward<F>(fun)); } private: - template<typename F, typename Self> constexpr void foreach_tile_(F&& fun); + template<typename F, typename Self> + constexpr void foreach_tile_(F&& fun); std::array<tile, TILE_COUNT> tiles = {}; - chunk_sampler_array samplers; }; constexpr tile& chunk::operator[](std::size_t i) { @@ -101,12 +86,12 @@ template<typename F, typename Self> constexpr void chunk::foreach_tile_(F&& fun) { constexpr auto N = TILE_MAX_DIM; - for (unsigned j = 0; j < N; j++) - for (unsigned i = 0; i < N; i++) - { - unsigned idx = j*N + i; - fun(const_cast<Self>(*this).tiles[idx], i, j); - } + std::size_t k = 0; + for (std::size_t j = 0; j < N; j++) + for (std::size_t i = 0; i < N; i++, k++) + fun(const_cast<Self>(*this).tiles[k], + local_coords{(std::uint8_t)i, (std::uint8_t)j}, + k); } constexpr std::size_t chunk_coords::to_index() const noexcept @@ -39,9 +39,58 @@ struct enum_bitset : std::bitset<(std::size_t)enum_type::MAX> { } }; +class tile_mesh final +{ + static constexpr std::size_t index_count = std::tuple_size_v<decltype(tile_atlas{}.indices(0))>; + static constexpr std::array<UnsignedShort, index_count> _indices = + tile_atlas::indices(0); + + struct vertex_data final { + Vector3 position; + Vector2 texcoords; + }; + std::array<vertex_data, 4> _vertex_data = {}; + GL::Buffer _vertex_buffer{_vertex_data, Magnum::GL::BufferUsage::DynamicDraw}, + _index_buffer{_indices, Magnum::GL::BufferUsage::StaticDraw}; + GL::Mesh _mesh; + +public: + tile_mesh(); + tile_mesh(tile_mesh&&) = delete; + tile_mesh(const tile_mesh&) = delete; + + void draw_quad(tile_shader& shader, tile_image& img, const std::array<Vector3, 4>& positions); + void draw_floor_quad(tile_shader& shader, tile_image& img, Vector3 center); +}; + +tile_mesh::tile_mesh() +{ + _mesh.setCount((int)index_count) + .addVertexBuffer(_vertex_buffer, 0, + tile_shader::Position{}, tile_shader::TextureCoordinates{}) + .setIndexBuffer(_index_buffer, 0, GL::MeshIndexType::UnsignedShort); +} + +void tile_mesh::draw_quad(tile_shader& shader, tile_image& img, const std::array<Vector3, 4>& positions) +{ + auto texcoords = img.atlas->texcoords_for_id(img.variant); + //auto positions = img.atlas->floor_quad(position, { TILE_SIZE[0], TILE_SIZE[1] }); + for (std::size_t i = 0; i < 4; i++) + _vertex_data[i] = {positions[i], texcoords[i]}; + img.atlas->texture().bind(0); + _vertex_buffer.setData(_vertex_data, Magnum::GL::BufferUsage::DynamicDraw); + shader.draw(_mesh); +} + +void tile_mesh::draw_floor_quad(tile_shader& shader, tile_image& img, Vector3 center) +{ + draw_quad(shader, img, img.atlas->floor_quad(center, { TILE_SIZE[0], TILE_SIZE[1] })); +} + struct app final : Platform::Application { using dpi_policy = Platform::Implementation::Sdl2DpiScalingPolicy; + using shared_tile_atlas = std::shared_ptr<tile_atlas>; explicit app(const Arguments& arguments); virtual ~app(); @@ -52,34 +101,59 @@ struct app final : Platform::Application void keyPressEvent(KeyEvent& event) override; void keyReleaseEvent(KeyEvent& event) override; void do_key(KeyEvent::Key k, KeyEvent::Modifiers m, bool pressed, bool repeated); + void draw_chunk(chunk& c); enum class key : int { camera_up, camera_left, camera_right, camera_down, camera_reset, quit, MAX }; + chunk make_test_chunk(); - GL::Mesh _mesh, _mesh2; tile_shader _shader; - std::shared_ptr<tile_atlas> floor1 = + shared_tile_atlas floor1 = //loader.tile_atlas("../share/game/images/tiles.tga", {8,4}); //loader.tile_atlas("../share/game/images/tiles2.tga", {8,5}); - loader.tile_atlas("../share/game/images/metal1.tga", {2, 2}); //loader.tile_atlas("../share/game/images/floor1.tga", {4, 4}); - std::shared_ptr<tile_atlas> floor2 = loader.tile_atlas("../share/game/images/floor1.tga", {4, 4}); - std::shared_ptr<tile_atlas> wall1 = + loader.tile_atlas("../share/game/images/metal1.tga", {2, 2}); + shared_tile_atlas floor2 = + loader.tile_atlas("../share/game/images/floor1.tga", {4, 4}); + shared_tile_atlas wall1 = loader.tile_atlas("../share/game/images/metal2.tga", {2, 2}); + chunk _chunk = make_test_chunk(); + tile_mesh _tile_mesh; std::uint64_t time_ticks = 0, time_freq = SDL_GetPerformanceFrequency(); Vector2 camera_offset; enum_bitset<key> keys; - chunk c; float get_dt(); }; using namespace Math::Literals; +chunk app::make_test_chunk() +{ + chunk c; + c.foreach_tile([&, this](tile& x, local_coords, std::size_t k) { + //const auto& atlas = (pt.y*TILE_MAX_DIM+pt.x+1) % 2 == 0 ? floor1 : floor2; + const auto& atlas = floor1; + x.ground_image = { atlas, (std::uint8_t)(k % atlas->size()) }; + }); + return c; +} + +void app::draw_chunk(chunk& c) +{ + constexpr auto N = TILE_MAX_DIM; + constexpr float X = TILE_SIZE[0], Y = TILE_SIZE[1]; + + for (std::size_t j = 0, k = 0; j < N; j++) + for (std::size_t i = 0; i < N; i++, k++) + _tile_mesh.draw_floor_quad(_shader, c[k].ground_image, + {(float)(X*i), (float)(Y*j), 0}); +} + app::app(const Arguments& arguments): Platform::Application{ arguments, @@ -90,11 +164,7 @@ app::app(const Arguments& arguments): //.setSampleCount(4) } { - struct QuadVertex { - Vector3 position; - Vector2 textureCoordinates; - }; - +#if 0 std::vector<QuadVertex> vertices; vertices.reserve(1024); std::vector<UnsignedShort> indices; indices.reserve(1024); @@ -125,6 +195,7 @@ app::app(const Arguments& arguments): _mesh.setCount((int)indices.size()) .addVertexBuffer(GL::Buffer{vertices}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}) + .addVertexBuffer(GL::Buffer{c.sampler_array()}, 0, tile_shader::TextureID{}) .setIndexBuffer(GL::Buffer{indices}, 0, GL::MeshIndexType::UnsignedShort); } @@ -160,6 +231,7 @@ app::app(const Arguments& arguments): .addVertexBuffer(GL::Buffer{vertices}, 0, tile_shader::Position{}, tile_shader::TextureCoordinates{}) .setIndexBuffer(GL::Buffer{indices}, 0, GL::MeshIndexType::UnsignedShort); +#endif (void)get_dt(); } @@ -188,16 +260,11 @@ void app::drawEvent() { } } - _shader.clear_samplers(); - - auto floor1_sampler = _shader.bind_sampler(floor1); - auto wall_sampler = _shader.bind_sampler(wall1); + //auto floor1_sampler = _shader.bind_sampler(floor1); + //auto wall_sampler = _shader.bind_sampler(wall1); #if 1 - _shader.draw(_mesh); -#endif -#if 1 - _shader.draw(_mesh2); + draw_chunk(_chunk); #endif swapBuffers(); diff --git a/shaders/tile-shader.frag b/shaders/tile-shader.frag index 8a31a1e1..0f487386 100644 --- a/shaders/tile-shader.frag +++ b/shaders/tile-shader.frag @@ -1,14 +1,12 @@ -#version 450 precision highp float; -const int MAX_SAMPLERS = 16; -layout (location = 0) uniform sampler2D samplers[MAX_SAMPLERS]; +uniform sampler2D samplers[32]; -layout (location = 0) in vec2 texcoord; -layout (location = 1) flat in uint sampler_id; +in vec2 out_texcoords; +flat in uint frag_sampler_id; out vec4 fragmentColor; void main() { - fragmentColor.rgb = texture(samplers[sampler_id], texcoord).rgb; + fragmentColor.rgb = texture(samplers[frag_sampler_id], out_texcoords).rgb; fragmentColor.a = 1; } diff --git a/shaders/tile-shader.vert b/shaders/tile-shader.vert index 6c12f1e2..17ead0d9 100644 --- a/shaders/tile-shader.vert +++ b/shaders/tile-shader.vert @@ -1,19 +1,18 @@ -#version 450 precision highp float; layout (location = 0) uniform vec2 scale; layout (location = 1) uniform vec2 offset; +uniform sampler2D samplers[32]; -layout(location = 0) in vec4 position; -layout(location = 1) in vec2 texcoord; -layout(location = 2) flat in uint sampler_id; - -layout (location = 0) out vec2 out_texcoord; -layout (location = 1) flat out uint out_sampler_id; +in vec4 position; +in vec2 texcoords; +in uint sampler_id; +out vec2 out_texcoords; +flat out uint frag_sampler_id; void main() { - interpolatedTextureCoordinates = texcoord; - out_sampler_id = sampler_id; + out_texcoords = texcoords; + frag_sampler_id = sampler_id; float cx = 2/scale.x, cy = 2/scale.y; float x = position.y, y = position.x, z = position.z; diff --git a/tile-atlas.cpp b/tile-atlas.cpp index 67d5df7f..bc2db18e 100644 --- a/tile-atlas.cpp +++ b/tile-atlas.cpp @@ -22,8 +22,9 @@ tile_atlas::tile_atlas(const ImageView2D& image, Vector2i dims) : .setSubImage(0, {}, image); } -std::array<Vector2, 4> tile_atlas::texcoords_for_id(int id_) const +std::array<Vector2, 4> tile_atlas::texcoords_for_id(std::size_t id2) const { + auto id_ = (int)id2; CORRADE_INTERNAL_ASSERT(id_ >= 0 && id_ < dims_.product()); Vector2i id = { id_ % dims_[0], id_ / dims_[0] }; auto p0 = Vector2(id * tile_size_) / Vector2(size_); @@ -94,14 +95,4 @@ vertex_array_type tile_atlas::wall_quad_N(Vector3 center, Vector3 size) }}; } -std::array<UnsignedShort, 6> tile_atlas::indices(int N) -{ - CORRADE_INTERNAL_ASSERT(N >= 0); - using u16 = UnsignedShort; - return { /* 3--1 1 */ - (u16)(0+N*4), (u16)(1+N*4), (u16)(2+N*4), /* | / /| */ - (u16)(2+N*4), (u16)(1+N*4), (u16)(3+N*4), /* |/ / | */ - }; /* 2 2--0 */ -} - } // namespace Magnum::Examples diff --git a/tile-atlas.hpp b/tile-atlas.hpp index 855214b8..f03afa71 100644 --- a/tile-atlas.hpp +++ b/tile-atlas.hpp @@ -10,17 +10,18 @@ struct tile_atlas final using vertex_array_type = std::array<Vector3, 4>; tile_atlas(const ImageView2D& img, Vector2i dims); - std::array<Vector2, 4> texcoords_for_id(int id) const; + std::array<Vector2, 4> texcoords_for_id(std::size_t id) const; static vertex_array_type floor_quad(Vector3 center, Vector2 size); static vertex_array_type wall_quad_S(Vector3 center, Vector3 size); static vertex_array_type wall_quad_E(Vector3 center, Vector3 size); static vertex_array_type wall_quad_N(Vector3 center, Vector3 size); static vertex_array_type wall_quad_W(Vector3 center, Vector3 size); - static std::array<UnsignedShort, 6> indices(int N); + static constexpr std::array<UnsignedShort, 6> indices(std::size_t N); GL::Texture2D& texture() { return tex_; } - constexpr int size() const { return dims_.product(); } + constexpr std::size_t size() const { return (std::size_t)dims_.product(); } constexpr Vector2i tile_size() const { return tile_size_; } + tile_atlas() = default; tile_atlas(const tile_atlas&) = delete; tile_atlas& operator=(const tile_atlas&) = delete; private: @@ -28,4 +29,13 @@ private: Vector2i size_, dims_, tile_size_; }; +constexpr std::array<UnsignedShort, 6> tile_atlas::indices(std::size_t N) +{ + using u16 = UnsignedShort; + return { /* 3--1 1 */ + (u16)(0+N*4), (u16)(1+N*4), (u16)(2+N*4), /* | / /| */ + (u16)(2+N*4), (u16)(1+N*4), (u16)(3+N*4), /* |/ / | */ + }; /* 2 2--0 */ +} + } // namespace Magnum::Examples diff --git a/tile-shader.hpp b/tile-shader.hpp index bf0813ff..1c2faabf 100644 --- a/tile-shader.hpp +++ b/tile-shader.hpp @@ -16,7 +16,6 @@ struct tile_shader : GL::AbstractShaderProgram { typedef GL::Attribute<0, Vector3> Position; typedef GL::Attribute<1, Vector2> TextureCoordinates; - typedef GL::Attribute<2, int> TextureID; explicit tile_shader(); |