@@ -61,23 +61,22 @@ void TileManager::init()
61
61
{
62
62
using nucleus::utils::terrain_mesh_index_generator::surface_quads_with_curtains;
63
63
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);
81
80
}
82
81
83
82
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
95
94
{
96
95
QOpenGLExtraFunctions* f = QOpenGLContext::currentContext ()->extraFunctions ();
97
96
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 );
99
98
shader_program->set_uniform (" height_sampler" , 1 );
100
99
101
100
// Sort depending on distance to sort_position
102
101
std::vector<std::pair<float , const TileSet*>> tile_list;
103
- for (const auto & tileset : tiles () ) {
102
+ for (const auto & tileset : m_gpu_tiles ) {
104
103
float dist = 0.0 ;
105
104
if (!draw_tiles.contains (tileset.tiles .front ().first ))
106
105
continue ;
@@ -115,12 +114,13 @@ void TileManager::draw(ShaderProgram* shader_program, const nucleus::camera::Def
115
114
}
116
115
if (sort_tiles) std::sort (tile_list.begin (), tile_list.end (), compareTileSetPair);
117
116
117
+ m_ortho_textures->bind (2 );
118
118
for (const auto & tileset : tile_list) {
119
119
tileset.second ->vao ->bind ();
120
120
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 ])));
122
122
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 ) );
124
124
tileset.second ->heightmap_texture ->bind (1 );
125
125
f->glDrawElements (GL_TRIANGLE_STRIP, tileset.second ->gl_element_count , tileset.second ->gl_index_type , nullptr );
126
126
}
@@ -131,14 +131,19 @@ void TileManager::remove_tile(const tile::Id& tile_id)
131
131
{
132
132
if (!QOpenGLContext::currentContext ()) // can happen during shutdown.
133
133
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
+
134
140
// clear slot
135
141
// or remove from list and free resources
136
142
const auto found_tile = std::find_if (m_gpu_tiles.begin (), m_gpu_tiles.end (), [&tile_id](const TileSet& tileset) {
137
143
return tileset.tiles .front ().first == tile_id;
138
144
});
139
145
if (found_tile != m_gpu_tiles.end ())
140
146
m_gpu_tiles.erase (found_tile);
141
- m_draw_list_generator.remove_tile (tile_id);
142
147
143
148
emit tiles_changed ();
144
149
}
@@ -150,6 +155,12 @@ void TileManager::set_aabb_decorator(const nucleus::tile_scheduler::utils::AabbD
150
155
m_draw_list_generator.set_aabb_decorator (new_aabb_decorator);
151
156
}
152
157
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
+
153
164
void TileManager::add_tile (
154
165
const tile::Id& id, tile::SrsAndHeightBounds bounds, const nucleus::utils::ColourTexture& ortho_texture, const nucleus::Raster<uint16_t >& height_map)
155
166
{
@@ -166,20 +177,23 @@ void TileManager::add_tile(
166
177
tileset.vao ->bind ();
167
178
168
179
{ // 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 );
171
182
tileset.gl_index_type = GL_UNSIGNED_SHORT;
172
183
}
173
184
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);
178
185
179
186
tileset.heightmap_texture = std::make_unique<Texture>(Texture::Target::_2d, Texture::Format::R16UI);
180
187
tileset.heightmap_texture ->setParams (Texture::Filter::Nearest, Texture::Filter::Nearest);
181
188
tileset.heightmap_texture ->upload (height_map);
182
189
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
+
183
197
// add to m_gpu_tiles
184
198
m_gpu_tiles.push_back (std::move (tileset));
185
199
m_draw_list_generator.add_tile (id);
@@ -194,6 +208,11 @@ void TileManager::set_permissible_screen_space_error(float new_permissible_scree
194
208
195
209
void TileManager::update_gpu_quads (const std::vector<nucleus::tile_scheduler::tile_types::GpuTileQuad>& new_quads, const std::vector<tile::Id>& deleted_quads)
196
210
{
211
+ for (const auto & quad : deleted_quads) {
212
+ for (const auto & id : quad.children ()) {
213
+ remove_tile (id);
214
+ }
215
+ }
197
216
for (const auto & quad : new_quads) {
198
217
for (const auto & tile : quad.tiles ) {
199
218
// test for validity
@@ -203,9 +222,4 @@ void TileManager::update_gpu_quads(const std::vector<nucleus::tile_scheduler::ti
203
222
add_tile (tile.id , tile.bounds , *tile.ortho , *tile.height );
204
223
}
205
224
}
206
- for (const auto & quad : deleted_quads) {
207
- for (const auto & id : quad.children ()) {
208
- remove_tile (id);
209
- }
210
- }
211
225
}
0 commit comments