summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--main.cpp36
-rw-r--r--tile-shader.cpp34
-rw-r--r--tile-shader.hpp20
3 files changed, 68 insertions, 22 deletions
diff --git a/main.cpp b/main.cpp
index 47092362..b5a3f6ca 100644
--- a/main.cpp
+++ b/main.cpp
@@ -60,12 +60,13 @@ struct app final : Platform::Application
GL::Mesh _mesh, _mesh2;
tile_shader _shader;
- std::shared_ptr<tile_atlas> atlas =
+ std::shared_ptr<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> atlas2 =
+ 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/metal2.tga", {2, 2});
std::uint64_t time_ticks = 0, time_freq = SDL_GetPerformanceFrequency();
@@ -108,9 +109,9 @@ app::app(const Arguments& arguments):
for (unsigned j = 0; j < chunk::N; j++) // TODO draw walls in correct order
for (unsigned i = 0; i < chunk::N; i++)
{
- auto positions = atlas->floor_quad({(float)(X*i), (float)(Y*j), 0}, {X, Y});
- auto texcoords = atlas->texcoords_for_id(k % atlas->size());
- auto indices_ = atlas->indices(k);
+ auto positions = floor1->floor_quad({(float)(X*i), (float)(Y*j), 0}, {X, Y});
+ auto texcoords = floor1->texcoords_for_id(k % floor1->size());
+ auto indices_ = floor1->indices(k);
for (unsigned x = 0; x < 4; x++)
vertices.push_back({ positions[x], texcoords[x] });
@@ -131,17 +132,17 @@ app::app(const Arguments& arguments):
{
Vector3 center{chunk::N/2.f*TILE_SIZE[0], chunk::N/2.f*TILE_SIZE[1], 0};
tile_atlas::vertex_array_type walls[] = {
- atlas2->wall_quad_W(center, Vector3(X, Y, Z)),
- atlas2->wall_quad_N(center, Vector3(X, Y, Z)),
- atlas2->wall_quad_E(center, Vector3(X, Y, Z)),
- atlas2->wall_quad_S(center, Vector3(X, Y, Z)),
+ wall1->wall_quad_W(center, Vector3(X, Y, Z)),
+ wall1->wall_quad_N(center, Vector3(X, Y, Z)),
+ wall1->wall_quad_E(center, Vector3(X, Y, Z)),
+ wall1->wall_quad_S(center, Vector3(X, Y, Z)),
};
int k = 0;
for (const auto& positions : walls)
{
- auto texcoords = atlas2->texcoords_for_id(k % atlas2->size());
- auto indices_ = atlas2->indices(k);
+ auto texcoords = wall1->texcoords_for_id(k % wall1->size());
+ auto indices_ = wall1->indices(k);
for (unsigned x = 0; x < 4; x++)
vertices.push_back({ positions[x], texcoords[x] });
for (auto x : indices_)
@@ -184,15 +185,16 @@ void app::drawEvent() {
}
}
+ _shader.clear_samplers();
+
+ auto floor1_sampler = _shader.bind_sampler(floor1);
+ auto wall_sampler = _shader.bind_sampler(wall1);
+
#if 1
- _shader
- .bindTexture(atlas->texture())
- .draw(_mesh);
+ _shader.draw(_mesh);
#endif
#if 1
- _shader
- .bindTexture(atlas2->texture())
- .draw(_mesh2);
+ _shader.draw(_mesh2);
#endif
swapBuffers();
diff --git a/tile-shader.cpp b/tile-shader.cpp
index d00a1ed9..b04054b4 100644
--- a/tile-shader.cpp
+++ b/tile-shader.cpp
@@ -1,6 +1,6 @@
#include "tile-shader.hpp"
#include "loader.hpp"
-
+#include <algorithm>
#include <Corrade/Containers/Reference.h>
#include <Corrade/Utility/Resource.h>
#include <Magnum/GL/Context.h>
@@ -26,11 +26,13 @@ tile_shader::tile_shader()
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
setUniform(ScaleUniform, Vector2{640, 480});
+
+ samplers.reserve(MAX_SAMPLERS);
}
-tile_shader& tile_shader::bindTexture(GL::Texture2D& texture)
+tile_shader& tile_shader::bind_texture(GL::Texture2D& texture, int id)
{
- texture.bind(TextureUnit);
+ texture.bind(id);
return *this;
}
@@ -54,4 +56,30 @@ Vector2 tile_shader::project(Vector3 pt)
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 34348814..ed771969 100644
--- a/tile-shader.hpp
+++ b/tile-shader.hpp
@@ -1,16 +1,25 @@
#pragma once
+#include "tile-atlas.hpp"
+#include <vector>
+#include <utility>
#include <Magnum/GL/AbstractShaderProgram.h>
#include <Magnum/GL/Texture.h>
#include <Magnum/Math/Color.h>
#include <Magnum/Math/Vector2.h>
#include <Magnum/Math/Matrix4.h>
+struct tile_atlas;
+
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;
explicit tile_shader();
@@ -21,11 +30,18 @@ struct tile_shader : GL::AbstractShaderProgram
static Vector2 project(Vector3 pt);
- tile_shader& bindTexture(GL::Texture2D& texture);
+ [[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_;
- enum { TextureUnit = 0 };
+
+ static constexpr int MAX_SAMPLERS = 16;
+
+ enum { SamplerIdAttribute = 1, };
enum { ScaleUniform = 0, OffsetUniform = 3, };
};