summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--chunk.cpp48
-rw-r--r--chunk.hpp45
-rw-r--r--main.cpp105
-rw-r--r--shaders/tile-shader.frag10
-rw-r--r--shaders/tile-shader.vert17
-rw-r--r--tile-atlas.cpp13
-rw-r--r--tile-atlas.hpp16
-rw-r--r--tile-shader.hpp1
8 files changed, 128 insertions, 127 deletions
diff --git a/chunk.cpp b/chunk.cpp
index 08009d0e..221f8132 100644
--- a/chunk.cpp
+++ b/chunk.cpp
@@ -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
diff --git a/chunk.hpp b/chunk.hpp
index af2e5b13..a768c093 100644
--- a/chunk.hpp
+++ b/chunk.hpp
@@ -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
diff --git a/main.cpp b/main.cpp
index efddc1a4..9551d0f1 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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();