summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-10-01 19:35:43 +0200
committerStanislaw Halik <sthalik@misaki.pl>2022-10-01 19:35:43 +0200
commit9436414c5002e86e64f90be3f10933fdba63943e (patch)
tree96dde7340044d2088d6948dada1b0da0f34d4c43
parent85a8bd54726fe4edc70676b797ed90f519dbbf7d (diff)
a
-rw-r--r--chunk.cpp49
-rw-r--r--chunk.hpp162
-rw-r--r--main.cpp14
-rw-r--r--shaders/tile-shader.frag10
-rw-r--r--shaders/tile-shader.vert15
-rw-r--r--tile-shader.cpp44
-rw-r--r--tile-shader.hpp16
-rw-r--r--tile.hpp135
8 files changed, 247 insertions, 198 deletions
diff --git a/chunk.cpp b/chunk.cpp
new file mode 100644
index 00000000..87cbe0cf
--- /dev/null
+++ b/chunk.cpp
@@ -0,0 +1,49 @@
+#include "chunk.hpp"
+
+namespace Magnum::Examples {
+
+chunk_sampler_array::chunk_sampler_array()
+{
+ samplers.reserve(MAX_SAMPLERS);
+}
+
+void chunk_sampler_array::ensure_sampler(std::size_t tile_id, const shared_sampler& x)
+{
+ 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();
+ sampler_map = {};
+}
+
+void chunk_sampler_array::bind()
+{
+ Magnum::GL::AbstractTexture::unbindImages(0, MAX_SAMPLERS);
+ for (std::size_t i = 0; i < samplers.size(); i++)
+ samplers[i]->texture().bind((int)i + 1);
+}
+
+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] - 1;
+ 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
new file mode 100644
index 00000000..99ad1778
--- /dev/null
+++ b/chunk.hpp
@@ -0,0 +1,162 @@
+#pragma once
+#include "tile.hpp"
+#include <type_traits>
+#include <vector>
+
+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;
+
+struct local_coords final {
+ std::uint8_t x = 0, y = 0;
+ constexpr std::size_t to_index() const noexcept;
+};
+
+constexpr std::size_t local_coords::to_index() const noexcept {
+ return y*TILE_MAX_DIM + x;
+}
+
+struct chunk_coords final {
+ std::int16_t x = 0, y = 0;
+ constexpr std::size_t to_index() const noexcept;
+
+ static constexpr std::size_t max_bits = sizeof(chunk_coords::x)*8 * 3 / 4;
+ 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>;
+ using sampler_tuple = std::pair<shared_sampler, int>;
+
+ static constexpr inline int MAX_SAMPLERS = 16;
+ 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;
+ constexpr global_coords(decltype(x) x, decltype(y) y) noexcept : x{x}, y{y} {}
+ constexpr global_coords(chunk_coords c, local_coords tile) noexcept;
+};
+
+static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y)>);
+static_assert(std::is_same_v<decltype(global_coords::x), decltype(global_coords::y)>);
+
+struct chunk final
+{
+ using index_type = decltype(local_coords::x);
+ 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);
+ constexpr const tile& operator[](local_coords xy) const;
+ constexpr tile& operator[](std::size_t i);
+ constexpr const tile& operator[](std::size_t i) const;
+
+ template<typename F>
+ requires std::invocable<F, tile&, int, int>
+ 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>
+ 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);
+
+ std::array<tile, TILE_COUNT> tiles = {};
+ chunk_sampler_array samplers;
+};
+
+constexpr tile& chunk::operator[](std::size_t i) {
+ if (i >= TILE_COUNT)
+ throw OUT_OF_RANGE(i, 0, TILE_COUNT);
+ return tiles[i];
+}
+
+constexpr const tile& chunk::operator[](std::size_t i) const {
+ return const_cast<chunk&>(*this).operator[](i);
+}
+
+constexpr const tile& chunk::operator[](local_coords xy) const {
+ return const_cast<chunk&>(*this).operator[](xy);
+}
+
+constexpr tile& chunk::operator[](local_coords xy)
+{
+ auto idx = xy.to_index();
+ return operator[](idx);
+}
+
+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);
+ }
+}
+
+constexpr std::size_t chunk_coords::to_index() const noexcept
+{
+ using unsigned_type = std::make_unsigned_t<decltype(x)>;
+ using limits = std::numeric_limits<unsigned_type>;
+ constexpr auto N = limits::max() + std::size_t{1};
+ static_assert(sizeof(unsigned_type) <= sizeof(UnsignedInt)/2);
+ return (std::size_t)(unsigned_type)y * N + (std::size_t)(unsigned_type)x;
+}
+
+struct hash_chunk final {
+ constexpr std::size_t operator()(chunk_coords xy) const noexcept {
+ return hash<sizeof(std::size_t)*8>{}(xy.to_index());
+ }
+};
+
+struct world final
+{
+ static_assert(sizeof(chunk_coords::x) <= sizeof(std::size_t)/2);
+
+ explicit world() = default;
+ template<typename F> std::shared_ptr<chunk> ensure_chunk(chunk_coords xy, F&& fun);
+
+private:
+ std::unordered_map<chunk_coords, std::shared_ptr<chunk>, hash_chunk> chunks;
+};
+
+template<typename F>
+std::shared_ptr<chunk> world::ensure_chunk(chunk_coords xy, F&& fun)
+{
+ ASSERT(xy.x < 1 << chunk_coords::max_bits);
+ ASSERT(xy.y < 1 << chunk_coords::max_bits);
+
+ auto it = chunks.find(xy);
+ if (it != chunks.end())
+ return it->second;
+ else
+ {
+ std::shared_ptr<chunk> ptr{fun()};
+ ASSERT(ptr);
+ return chunks[xy] = std::move(ptr);
+ }
+}
+
+constexpr global_coords::global_coords(chunk_coords c, local_coords tile) noexcept :
+ x{tile.x + ((std::uint32_t)(std::make_unsigned_t<decltype(c.x)>)c.x << chunk_coords::max_bits)},
+ y{tile.y + ((std::uint32_t)(std::make_unsigned_t<decltype(c.y)>)c.y << chunk_coords::max_bits)}
+{
+}
+
+} // namespace Magnum::Examples
diff --git a/main.cpp b/main.cpp
index b5a3f6ca..89afe091 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,6 +3,7 @@
#include "tile-shader.hpp"
#include "defs.hpp"
#include "tile.hpp"
+#include "chunk.hpp"
#include <bitset>
@@ -72,6 +73,7 @@ struct app final : Platform::Application
std::uint64_t time_ticks = 0, time_freq = SDL_GetPerformanceFrequency();
Vector2 camera_offset;
enum_bitset<key> keys;
+ chunk c;
float get_dt();
static constexpr Vector3 TILE_SIZE = { 50, 50, 50 };
@@ -106,8 +108,9 @@ app::app(const Arguments& arguments):
vertices.clear();
indices.clear();
int k = 0;
- for (unsigned j = 0; j < chunk::N; j++) // TODO draw walls in correct order
- for (unsigned i = 0; i < chunk::N; i++)
+ constexpr auto N = TILE_MAX_DIM;
+ for (unsigned j = 0; j < N; j++) // TODO draw walls in correct order
+ for (unsigned i = 0; i < N; i++)
{
auto positions = floor1->floor_quad({(float)(X*i), (float)(Y*j), 0}, {X, Y});
auto texcoords = floor1->texcoords_for_id(k % floor1->size());
@@ -130,7 +133,8 @@ app::app(const Arguments& arguments):
indices.clear();
{
- Vector3 center{chunk::N/2.f*TILE_SIZE[0], chunk::N/2.f*TILE_SIZE[1], 0};
+ constexpr auto N = TILE_MAX_DIM;
+ Vector3 center{N/2.f*TILE_SIZE[0], N/2.f*TILE_SIZE[1], 0};
tile_atlas::vertex_array_type walls[] = {
wall1->wall_quad_W(center, Vector3(X, Y, Z)),
wall1->wall_quad_N(center, Vector3(X, Y, Z)),
@@ -221,7 +225,7 @@ void app::do_camera(float dt)
void app::reset_camera_offset()
{
- camera_offset = _shader.project({chunk::N*TILE_SIZE[0]/2.f, chunk::N*TILE_SIZE[1]/2.f, 0});
+ camera_offset = _shader.project({TILE_MAX_DIM*TILE_SIZE[0]/2.f, TILE_MAX_DIM*TILE_SIZE[1]/2.f, 0});
}
void app::update(float dt)
@@ -280,7 +284,7 @@ void app::keyReleaseEvent(Platform::Sdl2Application::KeyEvent& event)
} // namespace Magnum::Examples
-MAGNUM_APPLICATION_MAIN(Magnum::Examples::app);
+MAGNUM_APPLICATION_MAIN(Magnum::Examples::app)
#ifdef _MSC_VER
# include <cstdlib>
diff --git a/shaders/tile-shader.frag b/shaders/tile-shader.frag
index f75a0478..8a31a1e1 100644
--- a/shaders/tile-shader.frag
+++ b/shaders/tile-shader.frag
@@ -1,12 +1,14 @@
+#version 450
precision highp float;
-layout(location = 2) uniform sampler2D textureData;
-
-in vec2 interpolatedTextureCoordinates;
+const int MAX_SAMPLERS = 16;
+layout (location = 0) uniform sampler2D samplers[MAX_SAMPLERS];
+layout (location = 0) in vec2 texcoord;
+layout (location = 1) flat in uint sampler_id;
out vec4 fragmentColor;
void main() {
- fragmentColor.rgb = texture(textureData, interpolatedTextureCoordinates).rgb;
+ fragmentColor.rgb = texture(samplers[sampler_id], texcoord).rgb;
fragmentColor.a = 1;
}
diff --git a/shaders/tile-shader.vert b/shaders/tile-shader.vert
index 239f4b07..6c12f1e2 100644
--- a/shaders/tile-shader.vert
+++ b/shaders/tile-shader.vert
@@ -1,14 +1,19 @@
+#version 450
precision highp float;
+layout (location = 0) uniform vec2 scale;
+layout (location = 1) uniform vec2 offset;
+
layout(location = 0) in vec4 position;
-layout(location = 1) in vec2 textureCoordinates;
-layout(location = 0) uniform vec2 scale;
-layout(location = 3) uniform vec2 offset;
+layout(location = 1) in vec2 texcoord;
+layout(location = 2) flat in uint sampler_id;
-out vec2 interpolatedTextureCoordinates;
+layout (location = 0) out vec2 out_texcoord;
+layout (location = 1) flat out uint out_sampler_id;
void main() {
- interpolatedTextureCoordinates = textureCoordinates;
+ interpolatedTextureCoordinates = texcoord;
+ out_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-shader.cpp b/tile-shader.cpp
index b04054b4..64e23ed1 100644
--- a/tile-shader.cpp
+++ b/tile-shader.cpp
@@ -19,21 +19,19 @@ tile_shader::tile_shader()
vert.addSource(loader.shader("shaders/tile-shader.vert"));
frag.addSource(loader.shader("shaders/tile-shader.frag"));
+#ifdef __clang__
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
CORRADE_INTERNAL_ASSERT_OUTPUT(GL::Shader::compile({vert, frag}));
-
+#ifdef __clang__
+# pragma clang diagnostic pop
+#endif
attachShaders({vert, frag});
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
setUniform(ScaleUniform, Vector2{640, 480});
-
- samplers.reserve(MAX_SAMPLERS);
-}
-
-tile_shader& tile_shader::bind_texture(GL::Texture2D& texture, int id)
-{
- texture.bind(id);
- return *this;
}
tile_shader& tile_shader::set_scale(const Vector2& scale)
@@ -42,6 +40,7 @@ tile_shader& tile_shader::set_scale(const Vector2& scale)
setUniform(ScaleUniform, scale);
return *this;
}
+
tile_shader& tile_shader::set_camera_offset(Vector2 camera_offset)
{
CORRADE_INTERNAL_ASSERT(std::fabs(camera_offset[0]) <= std::scalbn(1.f, std::numeric_limits<float>::digits));
@@ -50,36 +49,11 @@ tile_shader& tile_shader::set_camera_offset(Vector2 camera_offset)
setUniform(OffsetUniform, camera_offset);
return *this;
}
+
Vector2 tile_shader::project(Vector3 pt)
{
float x = pt[1], y = pt[0], z = pt[2];
return { x-y, (x+y+z*2)*.75f };
}
-int tile_shader::bind_sampler(const tile_shader::shared_sampler& atlas)
-{
- CORRADE_INTERNAL_ASSERT(samplers.size() < MAX_SAMPLERS);
- auto sampler_comparator = [](const sampler_tuple& a, const sampler_tuple& b) {
- const auto& [ptr1, n1] = a;
- const auto& [ptr2, n2] = b;
- return ptr1.get() < ptr2.get();
- };
- auto it = std::lower_bound(samplers.begin(), samplers.end(),
- sampler_tuple{atlas, -1}, sampler_comparator);
- int idx;
- if (it == samplers.end()) {
- idx = (int)samplers.size();
- samplers.emplace_back(atlas, idx);
- } else
- idx = it->second;
- atlas->texture().bind(idx);
- return idx;
-}
-
-void tile_shader::clear_samplers()
-{
- Magnum::GL::AbstractTexture::unbindImages(0, samplers.size());
- samplers.clear();
-}
-
} // namespace Magnum::Examples
diff --git a/tile-shader.hpp b/tile-shader.hpp
index ed771969..bf0813ff 100644
--- a/tile-shader.hpp
+++ b/tile-shader.hpp
@@ -14,12 +14,9 @@ namespace Magnum::Examples {
struct tile_shader : GL::AbstractShaderProgram
{
- using shared_sampler = std::shared_ptr<tile_atlas>;
- using sampler_tuple = std::pair<shared_sampler, int>;
-
typedef GL::Attribute<0, Vector3> Position;
typedef GL::Attribute<1, Vector2> TextureCoordinates;
- typedef GL::Attribute<2, int> SamplerId;
+ typedef GL::Attribute<2, int> TextureID;
explicit tile_shader();
@@ -30,19 +27,10 @@ struct tile_shader : GL::AbstractShaderProgram
static Vector2 project(Vector3 pt);
- [[nodiscard]] int bind_sampler(const shared_sampler& atlas);
- void clear_samplers();
-
- tile_shader& bind_texture(GL::Texture2D& texture, int id);
-
private:
- std::vector<sampler_tuple> samplers;
Vector2 scale_, camera_offset_;
- static constexpr int MAX_SAMPLERS = 16;
-
- enum { SamplerIdAttribute = 1, };
- enum { ScaleUniform = 0, OffsetUniform = 3, };
+ enum { ScaleUniform = 0, OffsetUniform = 1, };
};
} // namespace Magnum::Examples
diff --git a/tile.hpp b/tile.hpp
index 19a0354e..2c23aa9a 100644
--- a/tile.hpp
+++ b/tile.hpp
@@ -34,140 +34,5 @@ struct tile final
//explicit operator bool() const noexcept { return !!ground_image_.atlas; }
};
-struct local_coords final {
- std::uint8_t x = 0, y = 0;
- constexpr std::size_t to_index() const noexcept;
-};
-
-struct chunk_coords final {
- std::int16_t x = 0, y = 0;
- constexpr std::size_t to_index() const noexcept;
-
- static constexpr std::size_t max_bits = sizeof(chunk_coords::x)*8 * 3 / 4;
- static_assert(max_bits*4/3/8 == sizeof(decltype(chunk_coords::x)));
-};
-
-struct global_coords final {
- std::uint32_t x = 0, y = 0;
- constexpr global_coords() noexcept = default;
- constexpr global_coords(decltype(x) x, decltype(y) y) noexcept : x{x}, y{y} {}
- constexpr global_coords(chunk_coords c, local_coords tile) noexcept;
-};
-
-static_assert(std::is_same_v<decltype(local_coords::x), decltype(local_coords::y)>);
-static_assert(std::is_same_v<decltype(chunk_coords::x), decltype(chunk_coords::y)>);
-static_assert(std::is_same_v<decltype(global_coords::x), decltype(global_coords::y)>);
-
-struct chunk final
-{
- static constexpr std::size_t N = 16;
- static constexpr std::size_t TILE_COUNT = N*N;
-
- using index_type = decltype(local_coords::x);
- 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);
- constexpr const tile& operator[](local_coords xy) const;
- constexpr tile& operator[](std::size_t i);
- constexpr const tile& operator[](std::size_t i) const;
-
- template<typename F>
- requires std::invocable<F, tile&, int, int>
- 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>
- 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);
-
- std::array<struct tile, TILE_COUNT> tiles = {};
-};
-
-constexpr std::size_t local_coords::to_index() const noexcept {
- return y*chunk::N + x;
-}
-
-constexpr tile& chunk::operator[](std::size_t i) {
- if (i >= TILE_COUNT)
- throw OUT_OF_RANGE(i, 0, TILE_COUNT);
- return tiles[i];
-}
-
-constexpr const tile& chunk::operator[](std::size_t i) const {
- return const_cast<chunk&>(*this).operator[](i);
-}
-
-constexpr const tile& chunk::operator[](local_coords xy) const {
- return const_cast<chunk&>(*this).operator[](xy);
-}
-
-constexpr tile& chunk::operator[](local_coords xy)
-{
- auto idx = xy.to_index();
- return operator[](idx);
-}
-
-template<typename F, typename Self>
-constexpr void chunk::foreach_tile_(F&& fun)
-{
- 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);
- }
-}
-
-constexpr std::size_t chunk_coords::to_index() const noexcept
-{
- using unsigned_type = std::make_unsigned_t<decltype(x)>;
- using limits = std::numeric_limits<unsigned_type>;
- constexpr auto N = limits::max() + std::size_t{1};
- static_assert(sizeof(unsigned_type) <= sizeof(UnsignedInt)/2);
- return (std::size_t)(unsigned_type)y * N + (std::size_t)(unsigned_type)x;
-}
-
-struct hash_chunk final {
- constexpr std::size_t operator()(chunk_coords xy) const noexcept {
- return hash<sizeof(std::size_t)*8>{}(xy.to_index());
- }
-};
-
-struct world final
-{
- static_assert(sizeof(chunk_coords::x) <= sizeof(std::size_t)/2);
-
- explicit world() = default;
- template<typename F> std::shared_ptr<chunk> ensure_chunk(chunk_coords xy, F&& fun);
-
-private:
- std::unordered_map<chunk_coords, std::shared_ptr<chunk>, hash_chunk> chunks;
-};
-
-template<typename F>
-std::shared_ptr<chunk> world::ensure_chunk(chunk_coords xy, F&& fun)
-{
- ASSERT(xy.x < 1 << chunk_coords::max_bits);
- ASSERT(xy.y < 1 << chunk_coords::max_bits);
-
- auto it = chunks.find(xy);
- if (it != chunks.end())
- return it->second;
- else
- {
- std::shared_ptr<chunk> ptr{fun()};
- ASSERT(ptr);
- return chunks[xy] = std::move(ptr);
- }
-}
-
-constexpr global_coords::global_coords(chunk_coords c, local_coords tile) noexcept :
- x{tile.x + ((std::uint32_t)(std::make_unsigned_t<decltype(c.x)>)c.x << chunk_coords::max_bits)},
- y{tile.y + ((std::uint32_t)(std::make_unsigned_t<decltype(c.y)>)c.y << chunk_coords::max_bits)}
-{
-}
} //namespace Magnum::Examples