Skip to content

Commit 2fdbf68

Browse files
committed
move ortho textures to an array
1 parent 6c5bbae commit 2fdbf68

10 files changed

+75
-51
lines changed

gl_engine/Texture.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ void gl_engine::Texture::allocate_array(unsigned int width, unsigned int height,
8989
internalformat = gl_engine::Texture::compressed_texture_format();
9090

9191
f->glTexStorage3D(GLenum(m_target), mip_level_count, internalformat, GLsizei(width), GLsizei(height), GLsizei(n_layers));
92+
m_width = width;
93+
m_height = height;
94+
m_n_layers = n_layers;
9295
}
9396

9497
void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture)
@@ -113,6 +116,10 @@ void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture)
113116

114117
void gl_engine::Texture::upload(const nucleus::utils::ColourTexture& texture, unsigned int array_index)
115118
{
119+
assert(texture.width() == m_width);
120+
assert(texture.height() == m_height);
121+
assert(array_index < m_n_layers);
122+
116123
auto* f = QOpenGLContext::currentContext()->extraFunctions();
117124
f->glBindTexture(GLenum(m_target), m_id);
118125
f->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

gl_engine/Texture.h

+3
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class Texture {
5656
Format m_format = Format::Invalid;
5757
Filter m_min_filter = Filter::Nearest;
5858
Filter m_mag_filter = Filter::Nearest;
59+
unsigned m_width = unsigned(-1);
60+
unsigned m_height = unsigned(-1);
61+
unsigned m_n_layers = unsigned(-1);
5962
};
6063

6164
} // namespace gl_engine

gl_engine/TileManager.cpp

+47-33
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,22 @@ void TileManager::init()
6161
{
6262
using nucleus::utils::terrain_mesh_index_generator::surface_quads_with_curtains;
6363
assert(QOpenGLContext::currentContext());
64-
for (auto i = 0; i < MAX_TILES_PER_TILESET; ++i) {
65-
const auto indices = surface_quads_with_curtains<uint16_t>(N_EDGE_VERTICES);
66-
auto index_buffer = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::IndexBuffer);
67-
index_buffer->create();
68-
index_buffer->bind();
69-
index_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
70-
index_buffer->allocate(indices.data(), bufferLengthInBytes(indices));
71-
index_buffer->release();
72-
m_index_buffers.emplace_back(std::move(index_buffer), indices.size());
73-
}
74-
auto* f = QOpenGLContext::currentContext()->extraFunctions();
75-
f->glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &m_max_anisotropy);
76-
}
77-
78-
const std::vector<TileSet>& TileManager::tiles() const
79-
{
80-
return m_gpu_tiles;
64+
const auto indices = surface_quads_with_curtains<uint16_t>(N_EDGE_VERTICES);
65+
auto index_buffer = std::make_unique<QOpenGLBuffer>(QOpenGLBuffer::IndexBuffer);
66+
index_buffer->create();
67+
index_buffer->bind();
68+
index_buffer->setUsagePattern(QOpenGLBuffer::StaticDraw);
69+
index_buffer->allocate(indices.data(), bufferLengthInBytes(indices));
70+
index_buffer->release();
71+
m_index_buffer.first = std::move(index_buffer);
72+
m_index_buffer.second = indices.size();
73+
74+
m_ortho_textures = std::make_unique<Texture>(Texture::Target::_2dArray, Texture::Format::CompressedRGBA8);
75+
m_ortho_textures->setParams(Texture::Filter::Linear, Texture::Filter::Linear);
76+
// TODO: might become larger than GL_MAX_ARRAY_TEXTURE_LAYERS
77+
m_ortho_textures->allocate_array(ORTHO_RESOLUTION, ORTHO_RESOLUTION, unsigned(m_loaded_tiles.size()));
78+
79+
// m_heightmap_textures = std::make_unique<Texture>(Texture::Target::_2dArray, Texture::Format::R16UI);
8180
}
8281

8382
bool compareTileSetPair(std::pair<float, const TileSet*> t1, std::pair<float, const TileSet*> t2)
@@ -95,12 +94,12 @@ void TileManager::draw(ShaderProgram* shader_program, const nucleus::camera::Def
9594
{
9695
QOpenGLExtraFunctions* f = QOpenGLContext::currentContext()->extraFunctions();
9796
shader_program->set_uniform("n_edge_vertices", N_EDGE_VERTICES);
98-
shader_program->set_uniform("texture_sampler", 2);
97+
shader_program->set_uniform("ortho_sampler", 2);
9998
shader_program->set_uniform("height_sampler", 1);
10099

101100
// Sort depending on distance to sort_position
102101
std::vector<std::pair<float, const TileSet*>> tile_list;
103-
for (const auto& tileset : tiles()) {
102+
for (const auto& tileset : m_gpu_tiles) {
104103
float dist = 0.0;
105104
if (!draw_tiles.contains(tileset.tiles.front().first))
106105
continue;
@@ -115,12 +114,13 @@ void TileManager::draw(ShaderProgram* shader_program, const nucleus::camera::Def
115114
}
116115
if (sort_tiles) std::sort(tile_list.begin(), tile_list.end(), compareTileSetPair);
117116

117+
m_ortho_textures->bind(2);
118118
for (const auto& tileset : tile_list) {
119119
tileset.second->vao->bind();
120120
shader_program->set_uniform_array("bounds", boundsArray(*tileset.second, camera.position()));
121-
shader_program->set_uniform("tileset_id", (int)((tileset.second->tiles[0].first.coords[0] + tileset.second->tiles[0].first.coords[1])));
121+
shader_program->set_uniform("tileset_id", int((tileset.second->tiles[0].first.coords[0] + tileset.second->tiles[0].first.coords[1])));
122122
shader_program->set_uniform("tileset_zoomlevel", tileset.second->tiles[0].first.zoom_level);
123-
tileset.second->ortho_texture->bind(2);
123+
shader_program->set_uniform("texture_layer", int(tileset.second->texture_layer));
124124
tileset.second->heightmap_texture->bind(1);
125125
f->glDrawElements(GL_TRIANGLE_STRIP, tileset.second->gl_element_count, tileset.second->gl_index_type, nullptr);
126126
}
@@ -131,14 +131,19 @@ void TileManager::remove_tile(const tile::Id& tile_id)
131131
{
132132
if (!QOpenGLContext::currentContext()) // can happen during shutdown.
133133
return;
134+
135+
const auto t = std::find(m_loaded_tiles.begin(), m_loaded_tiles.end(), tile_id);
136+
assert(t != m_loaded_tiles.end()); // removing a tile that's not here. likely there is a race.
137+
*t = tile::Id { unsigned(-1), {} };
138+
m_draw_list_generator.remove_tile(tile_id);
139+
134140
// clear slot
135141
// or remove from list and free resources
136142
const auto found_tile = std::find_if(m_gpu_tiles.begin(), m_gpu_tiles.end(), [&tile_id](const TileSet& tileset) {
137143
return tileset.tiles.front().first == tile_id;
138144
});
139145
if (found_tile != m_gpu_tiles.end())
140146
m_gpu_tiles.erase(found_tile);
141-
m_draw_list_generator.remove_tile(tile_id);
142147

143148
emit tiles_changed();
144149
}
@@ -150,6 +155,12 @@ void TileManager::set_aabb_decorator(const nucleus::tile_scheduler::utils::AabbD
150155
m_draw_list_generator.set_aabb_decorator(new_aabb_decorator);
151156
}
152157

158+
void TileManager::set_quad_limit(unsigned int new_limit)
159+
{
160+
m_loaded_tiles.resize(new_limit * 4);
161+
std::fill(m_loaded_tiles.begin(), m_loaded_tiles.end(), tile::Id { unsigned(-1), {} });
162+
}
163+
153164
void TileManager::add_tile(
154165
const tile::Id& id, tile::SrsAndHeightBounds bounds, const nucleus::utils::ColourTexture& ortho_texture, const nucleus::Raster<uint16_t>& height_map)
155166
{
@@ -166,20 +177,23 @@ void TileManager::add_tile(
166177
tileset.vao->bind();
167178

168179
{ // vao state
169-
m_index_buffers[0].first->bind();
170-
tileset.gl_element_count = int(m_index_buffers[0].second);
180+
m_index_buffer.first->bind();
181+
tileset.gl_element_count = int(m_index_buffer.second);
171182
tileset.gl_index_type = GL_UNSIGNED_SHORT;
172183
}
173184
tileset.vao->release();
174-
tileset.ortho_texture = std::make_unique<Texture>(Texture::Target::_2d,
175-
ortho_texture.format() == nucleus::utils::ColourTexture::Format::Uncompressed_RGBA ? Texture::Format::RGBA8 : Texture::Format::CompressedRGBA8);
176-
tileset.ortho_texture->setParams(Texture::Filter::Linear, Texture::Filter::Linear);
177-
tileset.ortho_texture->upload(ortho_texture);
178185

179186
tileset.heightmap_texture = std::make_unique<Texture>(Texture::Target::_2d, Texture::Format::R16UI);
180187
tileset.heightmap_texture->setParams(Texture::Filter::Nearest, Texture::Filter::Nearest);
181188
tileset.heightmap_texture->upload(height_map);
182189

190+
// find empty spot and upload texture
191+
const auto t = std::find(m_loaded_tiles.begin(), m_loaded_tiles.end(), tile::Id { unsigned(-1), {} });
192+
assert(t != m_loaded_tiles.end());
193+
*t = id;
194+
m_ortho_textures->upload(ortho_texture, unsigned(t - m_loaded_tiles.begin()));
195+
tileset.texture_layer = unsigned(t - m_loaded_tiles.begin());
196+
183197
// add to m_gpu_tiles
184198
m_gpu_tiles.push_back(std::move(tileset));
185199
m_draw_list_generator.add_tile(id);
@@ -194,6 +208,11 @@ void TileManager::set_permissible_screen_space_error(float new_permissible_scree
194208

195209
void TileManager::update_gpu_quads(const std::vector<nucleus::tile_scheduler::tile_types::GpuTileQuad>& new_quads, const std::vector<tile::Id>& deleted_quads)
196210
{
211+
for (const auto& quad : deleted_quads) {
212+
for (const auto& id : quad.children()) {
213+
remove_tile(id);
214+
}
215+
}
197216
for (const auto& quad : new_quads) {
198217
for (const auto& tile : quad.tiles) {
199218
// test for validity
@@ -203,9 +222,4 @@ void TileManager::update_gpu_quads(const std::vector<nucleus::tile_scheduler::ti
203222
add_tile(tile.id, tile.bounds, *tile.ortho, *tile.height);
204223
}
205224
}
206-
for (const auto& quad : deleted_quads) {
207-
for (const auto& id : quad.children()) {
208-
remove_tile(id);
209-
}
210-
}
211225
}

gl_engine/TileManager.h

+6-9
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class TileManager : public QObject {
4545
explicit TileManager(QObject* parent = nullptr);
4646
void init(); // needs OpenGL context
4747

48-
[[nodiscard]] const std::vector<TileSet>& tiles() const;
4948
void draw(ShaderProgram* shader_program, const nucleus::camera::Definition& camera, const nucleus::tile_scheduler::DrawListGenerator::TileSet draw_tiles, bool sort_tiles, glm::dvec3 sort_position) const;
5049

5150
const nucleus::tile_scheduler::DrawListGenerator::TileSet generate_tilelist(const nucleus::camera::Definition& camera) const;
@@ -60,6 +59,7 @@ public slots:
6059
void remove_tile(const tile::Id& tile_id);
6160
void initilise_attribute_locations(ShaderProgram* program);
6261
void set_aabb_decorator(const nucleus::tile_scheduler::utils::AabbDecoratorPtr& new_aabb_decorator);
62+
void set_quad_limit(unsigned new_limit);
6363

6464
private:
6565
void add_tile(const tile::Id& id, tile::SrsAndHeightBounds bounds, const nucleus::utils::ColourTexture& ortho, const nucleus::Raster<uint16_t>& heights);
@@ -68,16 +68,13 @@ public slots:
6868

6969
static constexpr auto N_EDGE_VERTICES = 65;
7070
static constexpr auto ORTHO_RESOLUTION = 256;
71-
static constexpr auto MAX_TILES_PER_TILESET = 1;
72-
float m_max_anisotropy = 0;
71+
72+
std::vector<tile::Id> m_loaded_tiles;
73+
std::pair<std::unique_ptr<QOpenGLBuffer>, size_t> m_index_buffer;
74+
std::unique_ptr<Texture> m_ortho_textures;
75+
std::unique_ptr<Texture> m_heightmap_textures;
7376

7477
std::vector<TileSet> m_gpu_tiles;
75-
// indexbuffers for 4^index tiles,
76-
// e.g., for single tile tile sets take index 0
77-
// for 4 tiles take index 1, for 16 2..
78-
// the size_t is the number of indices
79-
std::vector<std::pair<std::unique_ptr<QOpenGLBuffer>, size_t>> m_index_buffers;
80-
std::unique_ptr<QOpenGLBuffer> m_dummy_buffer;
8178
TileGLAttributeLocations m_attribute_locations;
8279
unsigned m_tiles_per_set = 1;
8380
nucleus::tile_scheduler::DrawListGenerator m_draw_list_generator;

gl_engine/TileSet.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ struct TileSet {
4646
[[nodiscard]] bool isValid() const { return tile_id.zoom_level < 100; }
4747
};
4848

49-
std::unique_ptr<Texture> ortho_texture;
5049
std::unique_ptr<Texture> heightmap_texture;
5150
std::unique_ptr<QOpenGLVertexArrayObject> vao;
5251
std::vector<std::pair<tile::Id, tile::SrsBounds>> tiles;
5352
int gl_element_count = -1;
5453
unsigned gl_index_type = 0;
54+
unsigned texture_layer = unsigned(-1);
5555
// texture
5656
};
5757
} // namespace gl_engine

gl_engine/Window.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,9 @@ void Window::updateCameraEvent()
422422
emit update_camera_requested();
423423
}
424424

425-
void Window::set_permissible_screen_space_error(float new_error)
426-
{
427-
if (m_tile_manager)
428-
m_tile_manager->set_permissible_screen_space_error(new_error);
429-
}
425+
void Window::set_permissible_screen_space_error(float new_error) { m_tile_manager->set_permissible_screen_space_error(new_error); }
426+
427+
void Window::set_quad_limit(unsigned int new_limit) { m_tile_manager->set_quad_limit(new_limit); }
430428

431429
void Window::update_camera(const nucleus::camera::Definition& new_definition)
432430
{

gl_engine/Window.h

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class Window : public nucleus::AbstractRenderWindow, public nucleus::camera::Abs
7575
void keyReleaseEvent(QKeyEvent*);
7676
void updateCameraEvent();
7777
void set_permissible_screen_space_error(float new_error) override;
78+
void set_quad_limit(unsigned new_limit) override;
7879

7980
public slots:
8081
void update_camera(const nucleus::camera::Definition& new_definition) override;

gl_engine/shaders/tile.frag

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
#include "camera_config.glsl"
2222
#include "encoder.glsl"
2323

24-
uniform sampler2D texture_sampler;
24+
uniform highp int texture_layer;
25+
uniform sampler2DArray ortho_sampler;
2526

2627
layout (location = 0) out lowp vec3 texout_albedo;
2728
layout (location = 1) out highp vec4 texout_position;
@@ -54,7 +55,8 @@ void main() {
5455
#endif
5556

5657
// Write Albedo (ortho picture) in gbuffer
57-
lowp vec3 fragColor = texture(texture_sampler, uv).rgb;
58+
highp float texture_layer_f = float(texture_layer);
59+
lowp vec3 fragColor = texture(ortho_sampler, vec3(uv, texture_layer_f)).rgb;
5860
fragColor = mix(fragColor, conf.material_color.rgb, conf.material_color.a);
5961
texout_albedo = fragColor;
6062

nucleus/AbstractRenderWindow.h

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class AbstractRenderWindow : public QObject {
5151
virtual void paint(QOpenGLFramebufferObject* framebuffer = nullptr) = 0;
5252
virtual void deinit_gpu() = 0;
5353
virtual void set_permissible_screen_space_error(float new_error) = 0;
54+
virtual void set_quad_limit(unsigned new_limit) = 0;
5455
[[nodiscard]] virtual camera::AbstractDepthTester* depth_tester() = 0;
5556
[[nodiscard]] virtual utils::ColourTexture::Format ortho_tile_compression_algorithm() const = 0;
5657

nucleus/Controller.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ Controller::Controller(AbstractRenderWindow* render_window)
6060

6161
m_tile_scheduler = std::make_unique<nucleus::tile_scheduler::Scheduler>();
6262
m_tile_scheduler->read_disk_cache();
63-
m_tile_scheduler->set_gpu_quad_limit(500);
63+
m_render_window->set_quad_limit(512); // must be same as scheduler, dynamic resizing is not supported atm
64+
m_tile_scheduler->set_gpu_quad_limit(512);
6465
m_tile_scheduler->set_ram_quad_limit(12000);
6566
{
6667
QFile file(":/map/height_data.atb");

0 commit comments

Comments
 (0)