@@ -73,7 +73,8 @@ ClientMap::ClientMap(
73
73
rendering_engine->get_scene_manager(), id),
74
74
m_client(client),
75
75
m_rendering_engine(rendering_engine),
76
- m_control(control)
76
+ m_control(control),
77
+ m_drawlist(MapBlockComparer(v3s16(0 ,0 ,0 )))
77
78
{
78
79
79
80
/*
@@ -164,6 +165,8 @@ void ClientMap::updateDrawList()
164
165
{
165
166
ScopeProfiler sp (g_profiler, " CM::updateDrawList()" , SPT_AVG);
166
167
168
+ m_needs_update_drawlist = false ;
169
+
167
170
for (auto &i : m_drawlist) {
168
171
MapBlock *block = i.second ;
169
172
block->refDrop ();
@@ -178,6 +181,7 @@ void ClientMap::updateDrawList()
178
181
const f32 camera_fov = m_camera_fov * 1 .1f ;
179
182
180
183
v3s16 cam_pos_nodes = floatToInt (camera_position, BS);
184
+
181
185
v3s16 p_blocks_min;
182
186
v3s16 p_blocks_max;
183
187
getBlocksInViewRange (cam_pos_nodes, &p_blocks_min, &p_blocks_max);
@@ -202,6 +206,8 @@ void ClientMap::updateDrawList()
202
206
occlusion_culling_enabled = false ;
203
207
}
204
208
209
+ v3s16 camera_block = getContainerPos (cam_pos_nodes, MAP_BLOCKSIZE);
210
+ m_drawlist = std::map<v3s16, MapBlock*, MapBlockComparer>(MapBlockComparer (camera_block));
205
211
206
212
// Uncomment to debug occluded blocks in the wireframe mode
207
213
// TODO: Include this as a flag for an extended debugging setting
@@ -321,7 +327,20 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
321
327
Draw the selected MapBlocks
322
328
*/
323
329
324
- MeshBufListList drawbufs;
330
+ MeshBufListList grouped_buffers;
331
+
332
+ struct DrawDescriptor {
333
+ v3s16 m_pos;
334
+ scene::IMeshBuffer *m_buffer;
335
+ bool m_reuse_material;
336
+
337
+ DrawDescriptor (const v3s16 &pos, scene::IMeshBuffer *buffer, bool reuse_material) :
338
+ m_pos (pos), m_buffer(buffer), m_reuse_material(reuse_material)
339
+ {}
340
+ };
341
+
342
+ std::vector<DrawDescriptor> draw_order;
343
+ video::SMaterial previous_material;
325
344
326
345
for (auto &i : m_drawlist) {
327
346
v3s16 block_pos = i.first ;
@@ -386,62 +405,90 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
386
405
material.setFlag (video::EMF_WIREFRAME,
387
406
m_control.show_wireframe );
388
407
389
- drawbufs.add (buf, block_pos, layer);
408
+ if (is_transparent_pass) {
409
+ // Same comparison as in MeshBufListList
410
+ bool new_material = material.getTexture (0 ) != previous_material.getTexture (0 ) ||
411
+ material != previous_material;
412
+
413
+ draw_order.emplace_back (block_pos, buf, !new_material);
414
+
415
+ if (new_material)
416
+ previous_material = material;
417
+ }
418
+ else {
419
+ grouped_buffers.add (buf, block_pos, layer);
420
+ }
390
421
}
391
422
}
392
423
}
393
424
}
394
425
}
395
426
427
+ // Capture draw order for all solid meshes
428
+ for (auto &lists : grouped_buffers.lists ) {
429
+ for (MeshBufList &list : lists) {
430
+ // iterate in reverse to draw closest blocks first
431
+ for (auto it = list.bufs .rbegin (); it != list.bufs .rend (); ++it) {
432
+ draw_order.emplace_back (it->first , it->second , it != list.bufs .rbegin ());
433
+ }
434
+ }
435
+ }
436
+
396
437
TimeTaker draw (" Drawing mesh buffers" );
397
438
398
439
core::matrix4 m; // Model matrix
399
440
v3f offset = intToFloat (m_camera_offset, BS);
441
+ u32 material_swaps = 0 ;
400
442
401
- // Render all layers in order
402
- for (auto &lists : drawbufs.lists ) {
403
- for (MeshBufList &list : lists) {
404
- // Check and abort if the machine is swapping a lot
405
- if (draw.getTimerTime () > 2000 ) {
406
- infostream << " ClientMap::renderMap(): Rendering took >2s, " <<
407
- " returning." << std::endl;
408
- return ;
409
- }
443
+ // Render all mesh buffers in order
444
+ drawcall_count += draw_order.size ();
445
+ for (auto &descriptor : draw_order) {
446
+ scene::IMeshBuffer *buf = descriptor.m_buffer ;
410
447
448
+ // Check and abort if the machine is swapping a lot
449
+ if (draw.getTimerTime () > 2000 ) {
450
+ infostream << " ClientMap::renderMap(): Rendering took >2s, " <<
451
+ " returning." << std::endl;
452
+ return ;
453
+ }
454
+
455
+ if (!descriptor.m_reuse_material ) {
456
+ auto &material = buf->getMaterial ();
411
457
// pass the shadow map texture to the buffer texture
412
458
ShadowRenderer *shadow = m_rendering_engine->get_shadow_renderer ();
413
459
if (shadow && shadow ->is_active ()) {
414
- auto &layer = list. m .TextureLayer [3 ];
460
+ auto &layer = material .TextureLayer [3 ];
415
461
layer.Texture = shadow ->get_texture ();
416
462
layer.TextureWrapU = video::E_TEXTURE_CLAMP::ETC_CLAMP_TO_EDGE;
417
463
layer.TextureWrapV = video::E_TEXTURE_CLAMP::ETC_CLAMP_TO_EDGE;
418
464
layer.TrilinearFilter = true ;
419
465
}
466
+ driver->setMaterial (material);
467
+ ++material_swaps;
468
+ }
420
469
421
- driver->setMaterial (list.m );
422
-
423
- drawcall_count += list.bufs .size ();
424
- for (auto &pair : list.bufs ) {
425
- scene::IMeshBuffer *buf = pair.second ;
470
+ v3f block_wpos = intToFloat (descriptor.m_pos * MAP_BLOCKSIZE, BS);
471
+ m.setTranslation (block_wpos - offset);
426
472
427
- v3f block_wpos = intToFloat (pair.first * MAP_BLOCKSIZE, BS);
428
- m.setTranslation (block_wpos - offset);
429
-
430
- driver->setTransform (video::ETS_WORLD, m);
431
- driver->drawMeshBuffer (buf);
432
- vertex_count += buf->getVertexCount ();
433
- }
434
- }
473
+ driver->setTransform (video::ETS_WORLD, m);
474
+ driver->drawMeshBuffer (buf);
475
+ vertex_count += buf->getVertexCount ();
435
476
}
477
+
436
478
g_profiler->avg (prefix + " draw meshes [ms]" , draw.stop (true ));
437
479
438
480
// Log only on solid pass because values are the same
439
481
if (pass == scene::ESNRP_SOLID) {
440
482
g_profiler->avg (" renderMap(): animated meshes [#]" , mesh_animate_count);
441
483
}
442
484
485
+ if (pass == scene::ESNRP_TRANSPARENT) {
486
+ g_profiler->avg (" renderMap(): transparent buffers [#]" , draw_order.size ());
487
+ }
488
+
443
489
g_profiler->avg (prefix + " vertices drawn [#]" , vertex_count);
444
490
g_profiler->avg (prefix + " drawcalls [#]" , drawcall_count);
491
+ g_profiler->avg (prefix + " material swaps [#]" , material_swaps);
445
492
}
446
493
447
494
static bool getVisibleBrightness (Map *map, const v3f &p0, v3f dir, float step,
0 commit comments