1 // SuperTuxKart - a fun racing game with go-kart
2 // Copyright (C) 2018 SuperTuxKart-Team
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License
6 // as published by the Free Software Foundation; either version 3
7 // of the License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 #ifndef SERVER_ONLY
19
20 #include "graphics/sp/sp_base.hpp"
21 #include "config/stk_config.hpp"
22 #include "config/user_config.hpp"
23 #include "graphics/central_settings.hpp"
24 #include "graphics/frame_buffer.hpp"
25 #include "graphics/irr_driver.hpp"
26 #include "graphics/material_manager.hpp"
27 #include "graphics/shader_based_renderer.hpp"
28 #include "graphics/shared_gpu_objects.hpp"
29 #include "graphics/shader_based_renderer.hpp"
30 #include "graphics/post_processing.hpp"
31 #include "graphics/render_info.hpp"
32 #include "graphics/rtts.hpp"
33 #include "graphics/shaders.hpp"
34 #include "graphics/sp/sp_dynamic_draw_call.hpp"
35 #include "graphics/sp/sp_instanced_data.hpp"
36 #include "graphics/sp/sp_per_object_uniform.hpp"
37 #include "graphics/sp/sp_mesh.hpp"
38 #include "graphics/sp/sp_mesh_buffer.hpp"
39 #include "graphics/sp/sp_mesh_node.hpp"
40 #include "graphics/sp/sp_shader.hpp"
41 #include "graphics/sp/sp_shader_manager.hpp"
42 #include "graphics/sp/sp_texture.hpp"
43 #include "graphics/sp/sp_texture_manager.hpp"
44 #include "graphics/sp/sp_uniform_assigner.hpp"
45 #include "guiengine/engine.hpp"
46 #include "tracks/track.hpp"
47 #include "utils/log.hpp"
48 #include "utils/helpers.hpp"
49 #include "utils/profiler.hpp"
50 #include "utils/string_utils.hpp"
51
52 #include <algorithm>
53 #include <array>
54 #include <cassert>
55 #include <string>
56 #include <unordered_map>
57 #include <unordered_set>
58 #include <vector>
59
60 namespace SP
61 {
62
63 // ----------------------------------------------------------------------------
64 ShaderBasedRenderer* g_stk_sbr = NULL;
65 // ----------------------------------------------------------------------------
66 std::array<float, 16>* g_joint_ptr = NULL;
67 // ----------------------------------------------------------------------------
68 bool sp_culling = true;
69 // ----------------------------------------------------------------------------
70 bool sp_apitrace = false;
71 // ----------------------------------------------------------------------------
72 bool sp_debug_view = false;
73 // ----------------------------------------------------------------------------
74 bool g_handle_shadow = false;
75 // ----------------------------------------------------------------------------
76 SPShader* g_normal_visualizer = NULL;
77 // ----------------------------------------------------------------------------
78 SPShader* g_glow_shader = NULL;
79 // ----------------------------------------------------------------------------
80 // std::string is layer_1 and layer_2 texture name combined
81 typedef std::unordered_map<SPShader*, std::unordered_map<std::string,
82 std::unordered_set<SPMeshBuffer*> > > DrawCall;
83
84 DrawCall g_draw_calls[DCT_FOR_VAO];
85 // ----------------------------------------------------------------------------
86 std::vector<std::pair<SPShader*, std::vector<std::pair<std::array<GLuint, 6>,
87 std::vector<std::pair<SPMeshBuffer*, int/*material_id*/> > > > > >
88 g_final_draw_calls[DCT_FOR_VAO];
89 // ----------------------------------------------------------------------------
90 std::unordered_map<unsigned, std::pair<core::vector3df,
91 std::unordered_set<SPMeshBuffer*> > > g_glow_meshes;
92 // ----------------------------------------------------------------------------
93 std::unordered_set<SPMeshBuffer*> g_instances;
94 // ----------------------------------------------------------------------------
95 std::array<GLuint, ST_COUNT> g_samplers;
96 // ----------------------------------------------------------------------------
97 // Check sp_shader.cpp for the name
98 std::array<GLuint, 1> sp_prefilled_tex;
99 // ----------------------------------------------------------------------------
100 std::atomic<uint32_t> sp_max_texture_size(2048);
101 // ----------------------------------------------------------------------------
102 std::vector<float> g_bounding_boxes;
103 // ----------------------------------------------------------------------------
104 std::vector<std::shared_ptr<SPDynamicDrawCall> > g_dy_dc;
105 // ----------------------------------------------------------------------------
106 float g_frustums[5][24] = { { } };
107 // ----------------------------------------------------------------------------
108 unsigned sp_solid_poly_count = 0;
109 // ----------------------------------------------------------------------------
110 unsigned sp_shadow_poly_count = 0;
111 // ----------------------------------------------------------------------------
112 unsigned sp_cur_player = 0;
113 // ----------------------------------------------------------------------------
114 unsigned sp_cur_buf_id[MAX_PLAYER_COUNT] = {};
115 // ----------------------------------------------------------------------------
116 unsigned g_skinning_offset = 0;
117 // ----------------------------------------------------------------------------
118 std::vector<SPMeshNode*> g_skinning_mesh;
119 // ----------------------------------------------------------------------------
120 int sp_cur_shadow_cascade = 0;
121 // ----------------------------------------------------------------------------
initSTKRenderer(ShaderBasedRenderer * sbr)122 void initSTKRenderer(ShaderBasedRenderer* sbr)
123 {
124 g_stk_sbr = sbr;
125 } // initSTKRenderer
126 // ----------------------------------------------------------------------------
127 GLuint sp_mat_ubo[MAX_PLAYER_COUNT][3] = {};
128 // ----------------------------------------------------------------------------
129 GLuint sp_fog_ubo = 0;
130 // ----------------------------------------------------------------------------
131 core::vector3df sp_wind_dir;
132 // ----------------------------------------------------------------------------
133 GLuint g_skinning_tex;
134 // ----------------------------------------------------------------------------
135 GLuint g_skinning_buf;
136 // ----------------------------------------------------------------------------
137 unsigned g_skinning_size;
138 // ----------------------------------------------------------------------------
getRenderer()139 ShaderBasedRenderer* getRenderer()
140 {
141 return g_stk_sbr;
142 } // getRenderer
143
144 // ----------------------------------------------------------------------------
displaceUniformAssigner(SP::SPUniformAssigner * ua)145 void displaceUniformAssigner(SP::SPUniformAssigner* ua)
146 {
147 static std::array<float, 4> g_direction = {{ 0, 0, 0, 0 }};
148 if (!Track::getCurrentTrack())
149 {
150 ua->setValue(g_direction);
151 return;
152 }
153 const float time = irr_driver->getDevice()->getTimer()->getTime() /
154 1000.0f;
155 const float speed = Track::getCurrentTrack()->getDisplacementSpeed();
156
157 float strength = time;
158 strength = fabsf(noise2d(strength / 10.0f)) * 0.006f + 0.002f;
159
160 core::vector3df wind = irr_driver->getWind() * strength * speed;
161 g_direction[0] += wind.X;
162 g_direction[1] += wind.Z;
163
164 strength = time * 0.56f + sinf(time);
165 strength = fabsf(noise2d(0.0, strength / 6.0f)) * 0.0095f + 0.0025f;
166
167 wind = irr_driver->getWind() * strength * speed;
168 wind.rotateXZBy(cosf(time));
169 g_direction[2] += wind.X;
170 g_direction[3] += wind.Z;
171 ua->setValue(g_direction);
172 } // displaceUniformAssigner
173
174 // ----------------------------------------------------------------------------
displaceShaderInit(SPShader * shader)175 void displaceShaderInit(SPShader* shader)
176 {
177 shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_1ST);
178 shader->addShaderFile("white.frag", GL_FRAGMENT_SHADER, RP_1ST);
179 shader->linkShaderFiles(RP_1ST);
180 shader->use(RP_1ST);
181 shader->addBasicUniforms(RP_1ST);
182 shader->setUseFunction([]()->void
183 {
184 assert(g_stk_sbr->getRTTs() != NULL);
185 glEnable(GL_DEPTH_TEST);
186 glDepthMask(GL_FALSE);
187 glDisable(GL_CULL_FACE);
188 glDisable(GL_BLEND);
189 glClear(GL_STENCIL_BUFFER_BIT);
190 glEnable(GL_STENCIL_TEST);
191 glStencilFunc(GL_ALWAYS, 1, 0xFF);
192 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
193 g_stk_sbr->getRTTs()->getFBO(FBO_RGBA_1).bind(),
194 glClear(GL_COLOR_BUFFER_BIT);
195 }, RP_1ST);
196 shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER, RP_RESERVED);
197 shader->addShaderFile("sp_displace.frag", GL_FRAGMENT_SHADER, RP_RESERVED);
198 shader->linkShaderFiles(RP_RESERVED);
199 shader->use(RP_RESERVED);
200 shader->addBasicUniforms(RP_RESERVED);
201 shader->addAllUniforms(RP_RESERVED);
202 shader->setUseFunction([]()->void
203 {
204 glEnable(GL_DEPTH_TEST);
205 glDepthMask(GL_FALSE);
206 glDisable(GL_CULL_FACE);
207 glDisable(GL_BLEND);
208 glEnable(GL_STENCIL_TEST);
209 glStencilFunc(GL_ALWAYS, 1, 0xFF);
210 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
211 g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).bind(),
212 glClear(GL_COLOR_BUFFER_BIT);
213 }, RP_RESERVED);
214 SPShaderManager::addPrefilledTexturesToShader(shader,
215 {std::make_tuple("displacement_tex", "displace.png", false/*srgb*/,
216 ST_BILINEAR)}, RP_RESERVED);
217 shader->addCustomPrefilledTextures(ST_BILINEAR,
218 GL_TEXTURE_2D, "mask_tex", []()->GLuint
219 {
220 return g_stk_sbr->getRTTs()->getFBO(FBO_RGBA_1).getRTT()[0];
221 }, RP_RESERVED);
222 shader->addCustomPrefilledTextures(ST_BILINEAR,
223 GL_TEXTURE_2D, "color_tex", []()->GLuint
224 {
225 return g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getRTT()[0];
226 }, RP_RESERVED);
227 shader->addAllTextures(RP_RESERVED);
228 shader->setUnuseFunction([]()->void
229 {
230 g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).bind();
231 glStencilFunc(GL_EQUAL, 1, 0xFF);
232 g_stk_sbr->getPostProcessing()->renderPassThrough
233 (g_stk_sbr->getRTTs()->getFBO(FBO_TMP1_WITH_DS).getRTT()[0],
234 g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getWidth(),
235 g_stk_sbr->getRTTs()->getFBO(FBO_COLORS).getHeight());
236 glDisable(GL_STENCIL_TEST);
237 }, RP_RESERVED);
238 static_cast<SPPerObjectUniform*>(shader)
239 ->addAssignerFunction("direction", displaceUniformAssigner);
240 } // displaceShaderInit
241
242 // ----------------------------------------------------------------------------
resizeSkinning(unsigned number)243 void resizeSkinning(unsigned number)
244 {
245 const irr::core::matrix4 m;
246 g_skinning_size = number;
247
248
249
250 if (!CVS->isARBTextureBufferObjectUsable())
251 {
252 glBindTexture(GL_TEXTURE_2D, g_skinning_tex);
253 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 4, number, 0, GL_RGBA,
254 GL_FLOAT, NULL);
255 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 1, GL_RGBA, GL_FLOAT,
256 m.pointer());
257 glBindTexture(GL_TEXTURE_2D, 0);
258 static std::vector<std::array<float, 16> >
259 tmp_buf(stk_config->m_max_skinning_bones);
260 g_joint_ptr = tmp_buf.data();
261 }
262 else
263 {
264 #ifndef USE_GLES2
265 glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf);
266 if (CVS->isARBBufferStorageUsable())
267 {
268 glBufferStorage(GL_TEXTURE_BUFFER, number << 6, NULL,
269 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
270 g_joint_ptr = (std::array<float, 16>*)glMapBufferRange(
271 GL_TEXTURE_BUFFER, 0, 64,
272 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
273 memcpy(g_joint_ptr, m.pointer(), 64);
274 glUnmapBuffer(GL_TEXTURE_BUFFER);
275 g_joint_ptr = (std::array<float, 16>*)glMapBufferRange(
276 GL_TEXTURE_BUFFER, 64, (number - 1) << 6,
277 GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
278 }
279 else
280 {
281 glBufferData(GL_TEXTURE_BUFFER, number << 6, NULL, GL_DYNAMIC_DRAW);
282 glBufferSubData(GL_TEXTURE_BUFFER, 0, 64, m.pointer());
283 }
284 glBindTexture(GL_TEXTURE_BUFFER, g_skinning_tex);
285 glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, g_skinning_buf);
286 glBindTexture(GL_TEXTURE_BUFFER, 0);
287 #endif
288 }
289
290 } // resizeSkinning
291
292 // ----------------------------------------------------------------------------
initSkinning()293 void initSkinning()
294 {
295 static_assert(sizeof(std::array<float, 16>) == 64, "No padding");
296
297 int max_size = 0;
298
299 if (!CVS->isARBTextureBufferObjectUsable())
300 {
301 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_size);
302
303 if (stk_config->m_max_skinning_bones > (unsigned)max_size)
304 {
305 Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d",
306 max_size);
307 stk_config->m_max_skinning_bones = max_size;
308 }
309 Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: %u"
310 " (max bones) * 16 RGBA float texture",
311 stk_config->m_max_skinning_bones);
312 }
313 else
314 {
315 #ifndef USE_GLES2
316 glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_size);
317 if (stk_config->m_max_skinning_bones << 6 > (unsigned)max_size)
318 {
319 Log::warn("SharedGPUObjects", "Too many bones for skinning, max: %d",
320 max_size >> 6);
321 stk_config->m_max_skinning_bones = max_size >> 6;
322 }
323 Log::info("SharedGPUObjects", "Hardware Skinning enabled, method: TBO, "
324 "max bones: %u", stk_config->m_max_skinning_bones);
325 #endif
326 }
327
328
329 // Reserve 1 identity matrix for non-weighted vertices
330 // All buffer / skinning texture start with 2 bones for power of 2 increase
331 const irr::core::matrix4 m;
332 glGenTextures(1, &g_skinning_tex);
333 #ifndef USE_GLES2
334 if (CVS->isARBTextureBufferObjectUsable())
335 {
336 glGenBuffers(1, &g_skinning_buf);
337 }
338 #endif
339 resizeSkinning(stk_config->m_max_skinning_bones);
340
341 sp_prefilled_tex[0] = g_skinning_tex;
342 } // initSkinning
343
344 // ----------------------------------------------------------------------------
loadShaders()345 void loadShaders()
346 {
347 SPShaderManager::get()->loadSPShaders(file_manager->getShadersDir());
348
349 // Displace shader is not specifiable in XML due to complex callback
350 std::shared_ptr<SPShader> sps;
351 if (CVS->isDeferredEnabled())
352 {
353 // This displace shader will be drawn the last in transparent pass
354 sps = std::make_shared<SPShader>("displace", displaceShaderInit,
355 true/*transparent_shader*/, 999/*drawing_priority*/,
356 true/*use_alpha_channel*/);
357 SPShaderManager::get()->addSPShader(sps->getName(), sps);
358 }
359 else
360 {
361 // Fallback shader
362 SPShaderManager::get()->addSPShader("displace",
363 SPShaderManager::get()->getSPShader("alphablend"));
364 }
365
366 // ========================================================================
367 // Glow shader
368 // ========================================================================
369 if (CVS->isDeferredEnabled())
370 {
371 sps = std::make_shared<SPShader>
372 ("sp_glow_shader", [](SPShader* shader)
373 {
374 shader->addShaderFile("sp_pass.vert", GL_VERTEX_SHADER,
375 RP_1ST);
376 shader->addShaderFile("colorize.frag", GL_FRAGMENT_SHADER,
377 RP_1ST);
378 shader->linkShaderFiles(RP_1ST);
379 shader->use(RP_1ST);
380 shader->addBasicUniforms(RP_1ST);
381 shader->addAllUniforms(RP_1ST);
382 });
383 SPShaderManager::get()->addSPShader(sps->getName(), sps);
384 g_glow_shader = sps.get();
385
386 // ====================================================================
387 // Normal visualizer
388 // ====================================================================
389 #ifndef USE_GLES2
390 if (CVS->isARBGeometryShadersUsable())
391 {
392 sps = std::make_shared<SPShader>
393 ("sp_normal_visualizer", [](SPShader* shader)
394 {
395 shader->addShaderFile("sp_normal_visualizer.vert",
396 GL_VERTEX_SHADER, RP_1ST);
397 shader->addShaderFile("sp_normal_visualizer.geom",
398 GL_GEOMETRY_SHADER, RP_1ST);
399 shader->addShaderFile("sp_normal_visualizer.frag",
400 GL_FRAGMENT_SHADER, RP_1ST);
401 shader->linkShaderFiles(RP_1ST);
402 shader->use(RP_1ST);
403 shader->addBasicUniforms(RP_1ST);
404 shader->addAllUniforms(RP_1ST);
405 shader->addAllTextures(RP_1ST);
406 });
407 SPShaderManager::get()->addSPShader(sps->getName(), sps);
408 g_normal_visualizer = sps.get();
409 }
410 #endif
411 }
412
413 SPShaderManager::get()->setOfficialShaders();
414
415 } // loadShaders
416
417 // ----------------------------------------------------------------------------
resetEmptyFogColor()418 void resetEmptyFogColor()
419 {
420 if (GUIEngine::isNoGraphics())
421 {
422 return;
423 }
424 glBindBuffer(GL_UNIFORM_BUFFER, sp_fog_ubo);
425 std::vector<float> fog_empty;
426 fog_empty.resize(8, 0.0f);
427 glBufferData(GL_UNIFORM_BUFFER, 8 * sizeof(float), fog_empty.data(),
428 GL_DYNAMIC_DRAW);
429 } // resetEmptyFogColor
430
431 // ----------------------------------------------------------------------------
init()432 void init()
433 {
434 if (GUIEngine::isNoGraphics())
435 {
436 return;
437 }
438
439 initSkinning();
440 for (unsigned i = 0; i < MAX_PLAYER_COUNT; i++)
441 {
442 for (int j = 0; j < 3; j++)
443 {
444 glGenBuffers(1, &sp_mat_ubo[i][j]);
445 glBindBuffer(GL_UNIFORM_BUFFER, sp_mat_ubo[i][j]);
446 glBufferData(GL_UNIFORM_BUFFER, (16 * 9 + 2) * sizeof(float), NULL,
447 GL_DYNAMIC_DRAW);
448 }
449 }
450
451 glGenBuffers(1, &sp_fog_ubo);
452 resetEmptyFogColor();
453 glBindBufferBase(GL_UNIFORM_BUFFER, 2, sp_fog_ubo);
454
455 glBindBuffer(GL_UNIFORM_BUFFER, 0);
456
457 for (unsigned st = ST_NEAREST; st < ST_COUNT; st++)
458 {
459 if ((SamplerType)st == ST_TEXTURE_BUFFER)
460 {
461 g_samplers[ST_TEXTURE_BUFFER] = 0;
462 continue;
463 }
464 switch ((SamplerType)st)
465 {
466 case ST_NEAREST:
467 {
468 unsigned id;
469 glGenSamplers(1, &id);
470 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
471 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
472 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
473 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
474 if (CVS->isEXTTextureFilterAnisotropicUsable())
475 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
476 g_samplers[ST_NEAREST] = id;
477 break;
478 }
479 case ST_NEAREST_CLAMPED:
480 {
481 unsigned id;
482 glGenSamplers(1, &id);
483 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
484 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
485 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
486 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
487 if (CVS->isEXTTextureFilterAnisotropicUsable())
488 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
489 g_samplers[ST_NEAREST_CLAMPED] = id;
490 break;
491 }
492 case ST_TRILINEAR:
493 {
494 unsigned id;
495 glGenSamplers(1, &id);
496 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
497 glSamplerParameteri(id,
498 GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
499 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
500 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
501 if (CVS->isEXTTextureFilterAnisotropicUsable())
502 {
503 int aniso = UserConfigParams::m_anisotropic;
504 if (aniso == 0) aniso = 1;
505 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT,
506 (float)aniso);
507 }
508 g_samplers[ST_TRILINEAR] = id;
509 break;
510 }
511 case ST_TRILINEAR_CLAMPED:
512 {
513 unsigned id;
514 glGenSamplers(1, &id);
515 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
516 glSamplerParameteri(id,
517 GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
518 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
519 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
520 if (CVS->isEXTTextureFilterAnisotropicUsable())
521 {
522 int aniso = UserConfigParams::m_anisotropic;
523 if (aniso == 0) aniso = 1;
524 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT,
525 (float)aniso);
526 }
527 g_samplers[ST_TRILINEAR_CLAMPED] = id;
528 break;
529 }
530 case ST_BILINEAR:
531 {
532 unsigned id;
533 glGenSamplers(1, &id);
534 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
535 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
536 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_REPEAT);
537 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_REPEAT);
538 if (CVS->isEXTTextureFilterAnisotropicUsable())
539 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
540 g_samplers[ST_BILINEAR] = id;
541 break;
542 }
543 case ST_BILINEAR_CLAMPED:
544 {
545 unsigned id;
546 glGenSamplers(1, &id);
547 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
548 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
549 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
550 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
551 if (CVS->isEXTTextureFilterAnisotropicUsable())
552 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
553 g_samplers[ST_BILINEAR_CLAMPED] = id;
554 break;
555 }
556 case ST_SEMI_TRILINEAR:
557 {
558 unsigned id;
559 glGenSamplers(1, &id);
560 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
561 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER,
562 GL_LINEAR_MIPMAP_NEAREST);
563 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
564 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
565 if (CVS->isEXTTextureFilterAnisotropicUsable())
566 glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.);
567 g_samplers[ST_SEMI_TRILINEAR] = id;
568 break;
569 }
570 case ST_SHADOW:
571 {
572 unsigned id;
573 glGenSamplers(1, &id);
574 glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
575 glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER,
576 GL_LINEAR_MIPMAP_LINEAR);
577 glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
578 glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
579 glSamplerParameterf(id, GL_TEXTURE_COMPARE_MODE,
580 GL_COMPARE_REF_TO_TEXTURE);
581 glSamplerParameterf(id, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
582 g_samplers[ST_SHADOW] = id;
583 break;
584 }
585 default:
586 break;
587 }
588 }
589 } // init
590
591 // ----------------------------------------------------------------------------
destroy()592 void destroy()
593 {
594 g_dy_dc.clear();
595 SPTextureManager::get()->stopThreads();
596 SPShaderManager::destroy();
597 g_glow_shader = NULL;
598 g_normal_visualizer = NULL;
599 SPTextureManager::destroy();
600
601 #ifndef USE_GLES2
602 if (CVS->isARBTextureBufferObjectUsable() &&
603 CVS->isARBBufferStorageUsable())
604 {
605 glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf);
606 glUnmapBuffer(GL_TEXTURE_BUFFER);
607 glBindBuffer(GL_TEXTURE_BUFFER, 0);
608 }
609 glDeleteBuffers(1, &g_skinning_buf);
610 #endif
611 glDeleteTextures(1, &g_skinning_tex);
612
613 for (unsigned i = 0; i < MAX_PLAYER_COUNT; i++)
614 {
615 for (int j = 0; j < 3; j++)
616 {
617 glDeleteBuffers(1, &sp_mat_ubo[i][j]);
618 }
619 }
620 glDeleteBuffers(1, &sp_fog_ubo);
621 glDeleteSamplers((unsigned)g_samplers.size() - 1, g_samplers.data());
622
623 } // destroy
624
625 // ----------------------------------------------------------------------------
getSampler(SamplerType st)626 GLuint getSampler(SamplerType st)
627 {
628 assert(st < ST_COUNT);
629 return g_samplers[st];
630 } // getSampler
631
632 // ----------------------------------------------------------------------------
getGlowShader()633 SPShader* getGlowShader()
634 {
635 return g_glow_shader;
636 } // getGlowShader
637
638 // ----------------------------------------------------------------------------
getNormalVisualizer()639 SPShader* getNormalVisualizer()
640 {
641 return g_normal_visualizer;
642 } // getNormalVisualizer
643
644 // ----------------------------------------------------------------------------
mathPlaneNormf(float * p)645 inline void mathPlaneNormf(float *p)
646 {
647 float f = 1.0f / sqrtf(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
648 p[0] *= f;
649 p[1] *= f;
650 p[2] *= f;
651 p[3] *= f;
652 } // mathPlaneNormf
653
654 // ----------------------------------------------------------------------------
mathPlaneFrustumf(float * out,const core::matrix4 & pvm)655 inline void mathPlaneFrustumf(float* out, const core::matrix4& pvm)
656 {
657 // return 6 planes, 24 floats
658 const float* m = pvm.pointer();
659
660 // near
661 out[0] = m[3] + m[2];
662 out[1] = m[7] + m[6];
663 out[2] = m[11] + m[10];
664 out[3] = m[15] + m[14];
665 mathPlaneNormf(&out[0]);
666
667 // right
668 out[4] = m[3] - m[0];
669 out[4 + 1] = m[7] - m[4];
670 out[4 + 2] = m[11] - m[8];
671 out[4 + 3] = m[15] - m[12];
672 mathPlaneNormf(&out[4]);
673
674 // left
675 out[2 * 4] = m[3] + m[0];
676 out[2 * 4 + 1] = m[7] + m[4];
677 out[2 * 4 + 2] = m[11] + m[8];
678 out[2 * 4 + 3] = m[15] + m[12];
679 mathPlaneNormf(&out[2 * 4]);
680
681 // bottom
682 out[3 * 4] = m[3] + m[1];
683 out[3 * 4 + 1] = m[7] + m[5];
684 out[3 * 4 + 2] = m[11] + m[9];
685 out[3 * 4 + 3] = m[15] + m[13];
686 mathPlaneNormf(&out[3 * 4]);
687
688 // top
689 out[4 * 4] = m[3] - m[1];
690 out[4 * 4 + 1] = m[7] - m[5];
691 out[4 * 4 + 2] = m[11] - m[9];
692 out[4 * 4 + 3] = m[15] - m[13];
693 mathPlaneNormf(&out[4 * 4]);
694
695 // far
696 out[5 * 4] = m[3] - m[2];
697 out[5 * 4 + 1] = m[7] - m[6];
698 out[5 * 4 + 2] = m[11] - m[10];
699 out[5 * 4 + 3] = m[15] - m[14];
700 mathPlaneNormf(&out[5 * 4]);
701 } // mathPlaneFrustumf
702
703 // ----------------------------------------------------------------------------
getCorner(const core::aabbox3df & bbox,unsigned n)704 inline core::vector3df getCorner(const core::aabbox3df& bbox, unsigned n)
705 {
706 switch (n)
707 {
708 case 0:
709 return irr::core::vector3df(bbox.MinEdge.X, bbox.MinEdge.Y,
710 bbox.MinEdge.Z);
711 case 1:
712 return irr::core::vector3df(bbox.MaxEdge.X, bbox.MinEdge.Y,
713 bbox.MinEdge.Z);
714 case 2:
715 return irr::core::vector3df(bbox.MinEdge.X, bbox.MaxEdge.Y,
716 bbox.MinEdge.Z);
717 case 3:
718 return irr::core::vector3df(bbox.MaxEdge.X, bbox.MaxEdge.Y,
719 bbox.MinEdge.Z);
720 case 4:
721 return irr::core::vector3df(bbox.MinEdge.X, bbox.MinEdge.Y,
722 bbox.MaxEdge.Z);
723 case 5:
724 return irr::core::vector3df(bbox.MaxEdge.X, bbox.MinEdge.Y,
725 bbox.MaxEdge.Z);
726 case 6:
727 return irr::core::vector3df(bbox.MinEdge.X, bbox.MaxEdge.Y,
728 bbox.MaxEdge.Z);
729 case 7:
730 return irr::core::vector3df(bbox.MaxEdge.X, bbox.MaxEdge.Y,
731 bbox.MaxEdge.Z);
732 default:
733 assert(false);
734 return irr::core::vector3df(0);
735 }
736 } // getCorner
737
738 // ----------------------------------------------------------------------------
addEdgeForViz(const core::vector3df & p0,const core::vector3df & p1)739 void addEdgeForViz(const core::vector3df& p0, const core::vector3df& p1)
740 {
741 g_bounding_boxes.push_back(p0.X);
742 g_bounding_boxes.push_back(p0.Y);
743 g_bounding_boxes.push_back(p0.Z);
744 g_bounding_boxes.push_back(p1.X);
745 g_bounding_boxes.push_back(p1.Y);
746 g_bounding_boxes.push_back(p1.Z);
747 } // addEdgeForViz
748
749 // ----------------------------------------------------------------------------
prepareDrawCalls()750 void prepareDrawCalls()
751 {
752 if (!sp_culling)
753 {
754 return;
755 }
756 g_bounding_boxes.clear();
757 sp_wind_dir = core::vector3df(1.0f, 0.0f, 0.0f) *
758 (irr_driver->getDevice()->getTimer()->getTime() / 1000.0f) * 1.5f;
759 sp_solid_poly_count = sp_shadow_poly_count = 0;
760 // 1st one is identity
761 g_skinning_offset = 1;
762 g_skinning_mesh.clear();
763 mathPlaneFrustumf(g_frustums[0], irr_driver->getProjViewMatrix());
764 g_handle_shadow = Track::getCurrentTrack() &&
765 Track::getCurrentTrack()->hasShadows() && CVS->isDeferredEnabled() &&
766 CVS->isShadowEnabled();
767
768 if (g_handle_shadow)
769 {
770 mathPlaneFrustumf(g_frustums[1],
771 g_stk_sbr->getShadowMatrices()->getSunOrthoMatrices()[0]);
772 mathPlaneFrustumf(g_frustums[2],
773 g_stk_sbr->getShadowMatrices()->getSunOrthoMatrices()[1]);
774 mathPlaneFrustumf(g_frustums[3],
775 g_stk_sbr->getShadowMatrices()->getSunOrthoMatrices()[2]);
776 mathPlaneFrustumf(g_frustums[4],
777 g_stk_sbr->getShadowMatrices()->getSunOrthoMatrices()[3]);
778 }
779
780 for (auto& p : g_draw_calls)
781 {
782 p.clear();
783 }
784 for (auto& p : g_final_draw_calls)
785 {
786 p.clear();
787 }
788 g_glow_meshes.clear();
789 g_instances.clear();
790 }
791
792 // ----------------------------------------------------------------------------
addObject(SPMeshNode * node)793 void addObject(SPMeshNode* node)
794 {
795 if (!sp_culling)
796 {
797 return;
798 }
799
800 if (node->getSPM() == NULL)
801 {
802 return;
803 }
804
805 const core::matrix4& model_matrix = node->getAbsoluteTransformation();
806 bool added_for_skinning = false;
807 for (unsigned m = 0; m < node->getSPM()->getMeshBufferCount(); m++)
808 {
809 SPMeshBuffer* mb = node->getSPM()->getSPMeshBuffer(m);
810 SPShader* shader = node->getShader(m);
811 if (shader == NULL)
812 {
813 continue;
814 }
815 core::aabbox3df bb = mb->getBoundingBox();
816 model_matrix.transformBoxEx(bb);
817 std::vector<bool> discard;
818 const bool handle_shadow = node->isInShadowPass() &&
819 g_handle_shadow && shader->hasShader(RP_SHADOW);
820 discard.resize((handle_shadow ? 5 : 1), false);
821
822 for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
823 {
824 for (int i = 0; i < 24; i += 4)
825 {
826 bool outside = true;
827 for (int j = 0; j < 8; j++)
828 {
829 const float dist =
830 getCorner(bb, j).X * g_frustums[dc_type][i] +
831 getCorner(bb, j).Y * g_frustums[dc_type][i + 1] +
832 getCorner(bb, j).Z * g_frustums[dc_type][i + 2] +
833 g_frustums[dc_type][i + 3];
834 outside = outside && dist < 0.0f;
835 if (!outside)
836 {
837 break;
838 }
839 }
840 if (outside)
841 {
842 discard[dc_type] = true;
843 break;
844 }
845 }
846 }
847 if (handle_shadow ?
848 (discard[0] && discard[1] && discard[2] && discard[3] &&
849 discard[4]) : discard[0])
850 {
851 continue;
852 }
853
854 if (irr_driver->getBoundingBoxesViz())
855 {
856 addEdgeForViz(getCorner(bb, 0), getCorner(bb, 1));
857 addEdgeForViz(getCorner(bb, 1), getCorner(bb, 5));
858 addEdgeForViz(getCorner(bb, 5), getCorner(bb, 4));
859 addEdgeForViz(getCorner(bb, 4), getCorner(bb, 0));
860 addEdgeForViz(getCorner(bb, 2), getCorner(bb, 3));
861 addEdgeForViz(getCorner(bb, 3), getCorner(bb, 7));
862 addEdgeForViz(getCorner(bb, 7), getCorner(bb, 6));
863 addEdgeForViz(getCorner(bb, 6), getCorner(bb, 2));
864 addEdgeForViz(getCorner(bb, 0), getCorner(bb, 2));
865 addEdgeForViz(getCorner(bb, 1), getCorner(bb, 3));
866 addEdgeForViz(getCorner(bb, 5), getCorner(bb, 7));
867 addEdgeForViz(getCorner(bb, 4), getCorner(bb, 6));
868 }
869
870 mb->uploadGLMesh();
871 // For first frame only need the vbo to be initialized
872 if (!added_for_skinning && node->getAnimationState())
873 {
874 added_for_skinning = true;
875 int skinning_offset = g_skinning_offset + node->getTotalJoints();
876 if (skinning_offset > int(stk_config->m_max_skinning_bones))
877 {
878 Log::error("SPBase", "No enough space to render skinned"
879 " mesh %s! Max joints can hold: %d",
880 node->getName(), stk_config->m_max_skinning_bones);
881 return;
882 }
883 node->setSkinningOffset(g_skinning_offset);
884 g_skinning_mesh.push_back(node);
885 g_skinning_offset = skinning_offset;
886 }
887
888 float hue = node->getRenderInfo(m) ?
889 node->getRenderInfo(m)->getHue() : 0.0f;
890 SPInstancedData id = SPInstancedData
891 (node->getAbsoluteTransformation(), node->getTextureMatrix(m)[0],
892 node->getTextureMatrix(m)[1], hue,
893 (short)node->getSkinningOffset());
894
895 for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
896 {
897 if (discard[dc_type])
898 {
899 continue;
900 }
901 if (dc_type == 0)
902 {
903 sp_solid_poly_count += mb->getIndexCount() / 3;
904 }
905 else
906 {
907 sp_shadow_poly_count += mb->getIndexCount() / 3;
908 }
909 if (shader->isTransparent())
910 {
911 // Transparent shader should always uses mesh samplers
912 // All transparent draw calls go DCT_TRANSPARENT
913 if (dc_type == 0)
914 {
915 auto& ret = g_draw_calls[DCT_TRANSPARENT][shader];
916 for (auto& p : mb->getTextureCompare())
917 {
918 ret[p.first].insert(mb);
919 }
920 mb->addInstanceData(id, DCT_TRANSPARENT);
921 }
922 else
923 {
924 continue;
925 }
926 }
927 else
928 {
929 // Check if shader for render pass uses mesh samplers
930 const RenderPass check_pass =
931 dc_type == DCT_NORMAL ? RP_1ST : RP_SHADOW;
932 const bool sampler_less = shader->samplerLess(check_pass);
933 auto& ret = g_draw_calls[dc_type][shader];
934 if (sampler_less)
935 {
936 ret[""].insert(mb);
937 }
938 else
939 {
940 for (auto& p : mb->getTextureCompare())
941 {
942 ret[p.first].insert(mb);
943 }
944 }
945 mb->addInstanceData(id, (DrawCallType)dc_type);
946 if (UserConfigParams::m_glow && node->hasGlowColor() &&
947 CVS->isDeferredEnabled() && dc_type == DCT_NORMAL)
948 {
949 video::SColorf gc = node->getGlowColor();
950 unsigned key = gc.toSColor().color;
951 auto ret = g_glow_meshes.find(key);
952 if (ret == g_glow_meshes.end())
953 {
954 g_glow_meshes[key] = std::make_pair(
955 core::vector3df(gc.r, gc.g, gc.b),
956 std::unordered_set<SPMeshBuffer*>());
957 }
958 g_glow_meshes.at(key).second.insert(mb);
959 }
960 }
961 g_instances.insert(mb);
962 }
963 }
964 }
965
966 // ----------------------------------------------------------------------------
handleDynamicDrawCall()967 void handleDynamicDrawCall()
968 {
969 for (unsigned dc_num = 0; dc_num < g_dy_dc.size(); dc_num++)
970 {
971 SPDynamicDrawCall* dydc = g_dy_dc[dc_num].get();
972 if (!dydc->isRemoving())
973 {
974 // They need to be updated independent of culling result
975 // otherwise some data will be missed if offset update is used
976 g_instances.insert(dydc);
977 }
978 if (!dydc->isVisible() || dydc->notReadyFromDrawing() ||
979 dydc->isRemoving() || !sp_culling)
980 {
981 continue;
982 }
983
984 SPShader* shader = dydc->getShader();
985 core::aabbox3df bb = dydc->getBoundingBox();
986 dydc->getAbsoluteTransformation().transformBoxEx(bb);
987 std::vector<bool> discard;
988 const bool handle_shadow =
989 g_handle_shadow && shader->hasShader(RP_SHADOW);
990 discard.resize((handle_shadow ? 5 : 1), false);
991 for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
992 {
993 for (int i = 0; i < 24; i += 4)
994 {
995 bool outside = true;
996 for (int j = 0; j < 8; j++)
997 {
998 const float dist =
999 getCorner(bb, j).X * g_frustums[dc_type][i] +
1000 getCorner(bb, j).Y * g_frustums[dc_type][i + 1] +
1001 getCorner(bb, j).Z * g_frustums[dc_type][i + 2] +
1002 g_frustums[dc_type][i + 3];
1003 outside = outside && dist < 0.0f;
1004 if (!outside)
1005 {
1006 break;
1007 }
1008 }
1009 if (outside)
1010 {
1011 discard[dc_type] = true;
1012 break;
1013 }
1014 }
1015 }
1016 if (handle_shadow ?
1017 (discard[0] && discard[1] && discard[2] && discard[3] &&
1018 discard[4]) : discard[0])
1019 {
1020 continue;
1021 }
1022
1023 if (irr_driver->getBoundingBoxesViz())
1024 {
1025 addEdgeForViz(getCorner(bb, 0), getCorner(bb, 1));
1026 addEdgeForViz(getCorner(bb, 1), getCorner(bb, 5));
1027 addEdgeForViz(getCorner(bb, 5), getCorner(bb, 4));
1028 addEdgeForViz(getCorner(bb, 4), getCorner(bb, 0));
1029 addEdgeForViz(getCorner(bb, 2), getCorner(bb, 3));
1030 addEdgeForViz(getCorner(bb, 3), getCorner(bb, 7));
1031 addEdgeForViz(getCorner(bb, 7), getCorner(bb, 6));
1032 addEdgeForViz(getCorner(bb, 6), getCorner(bb, 2));
1033 addEdgeForViz(getCorner(bb, 0), getCorner(bb, 2));
1034 addEdgeForViz(getCorner(bb, 1), getCorner(bb, 3));
1035 addEdgeForViz(getCorner(bb, 5), getCorner(bb, 7));
1036 addEdgeForViz(getCorner(bb, 4), getCorner(bb, 6));
1037 }
1038
1039 for (int dc_type = 0; dc_type < (handle_shadow ? 5 : 1); dc_type++)
1040 {
1041 if (discard[dc_type])
1042 {
1043 continue;
1044 }
1045 if (dc_type == 0)
1046 {
1047 sp_solid_poly_count += dydc->getVertexCount();
1048 }
1049 else
1050 {
1051 sp_shadow_poly_count += dydc->getVertexCount();
1052 }
1053 if (shader->isTransparent())
1054 {
1055 // Transparent shader should always uses mesh samplers
1056 // All transparent draw calls go DCT_TRANSPARENT
1057 if (dc_type == 0)
1058 {
1059 auto& ret = g_draw_calls[DCT_TRANSPARENT][shader];
1060 for (auto& p : dydc->getTextureCompare())
1061 {
1062 ret[p.first].insert(dydc);
1063 }
1064 }
1065 else
1066 {
1067 continue;
1068 }
1069 }
1070 else
1071 {
1072 // Check if shader for render pass uses mesh samplers
1073 const RenderPass check_pass =
1074 dc_type == DCT_NORMAL ? RP_1ST : RP_SHADOW;
1075 const bool sampler_less = shader->samplerLess(check_pass);
1076 auto& ret = g_draw_calls[dc_type][shader];
1077 if (sampler_less)
1078 {
1079 ret[""].insert(dydc);
1080 }
1081 else
1082 {
1083 for (auto& p : dydc->getTextureCompare())
1084 {
1085 ret[p.first].insert(dydc);
1086 }
1087 }
1088 }
1089 }
1090 }
1091 }
1092
1093 // ----------------------------------------------------------------------------
updateModelMatrix()1094 void updateModelMatrix()
1095 {
1096 // Make sure all textures (with handles) are loaded
1097 SPTextureManager::get()->checkForGLCommand(true/*before_scene*/);
1098 if (!sp_culling)
1099 {
1100 return;
1101 }
1102 irr_driver->setSkinningJoint(g_skinning_offset - 1);
1103
1104 for (unsigned i = 0; i < DCT_FOR_VAO; i++)
1105 {
1106 DrawCall* dc = &g_draw_calls[(DrawCallType)i];
1107 // Sort dc based on the drawing priority of shaders
1108 // The larger the drawing priority int, the last it will be drawn
1109 using DrawCallPair = std::pair<SPShader*,
1110 std::unordered_map<std::string,
1111 std::unordered_set<SPMeshBuffer*> > >;
1112 std::vector<DrawCallPair> sorted_dc;
1113 for (auto& p : *dc)
1114 {
1115 sorted_dc.push_back(p);
1116 }
1117 std::sort(sorted_dc.begin(), sorted_dc.end(),
1118 [](const DrawCallPair& a, const DrawCallPair& b)->bool
1119 {
1120 return a.first->getDrawingPriority() <
1121 b.first->getDrawingPriority();
1122 });
1123 for (unsigned dc = 0; dc < sorted_dc.size(); dc++)
1124 {
1125 auto& p = sorted_dc[dc];
1126 g_final_draw_calls[i].emplace_back(p.first,
1127 std::vector<std::pair<std::array<GLuint, 6>,
1128 std::vector<std::pair<SPMeshBuffer*, int> > > >());
1129
1130 unsigned texture = 0;
1131 for (auto& q : p.second)
1132 {
1133 if (q.second.empty())
1134 {
1135 continue;
1136 }
1137 std::array<GLuint, 6> texture_names =
1138 {{ 0, 0, 0, 0, 0, 0 }};
1139 int material_id =
1140 (*(q.second.begin()))->getMaterialID(q.first);
1141
1142 if (material_id != -1)
1143 {
1144 const std::array<std::shared_ptr<SPTexture>, 6>& textures =
1145 (*(q.second.begin()))->getSPTexturesByMaterialID
1146 (material_id);
1147 texture_names =
1148 {{
1149 textures[0]->getOpenGLTextureName(),
1150 textures[1]->getOpenGLTextureName(),
1151 textures[2]->getOpenGLTextureName(),
1152 textures[3]->getOpenGLTextureName(),
1153 textures[4]->getOpenGLTextureName(),
1154 textures[5]->getOpenGLTextureName()
1155 }};
1156 }
1157 g_final_draw_calls[i][dc].second.emplace_back
1158 (texture_names,
1159 std::vector<std::pair<SPMeshBuffer*, int> >());
1160 for (SPMeshBuffer* spmb : q.second)
1161 {
1162 g_final_draw_calls[i][dc].second[texture].second.push_back
1163 (std::make_pair(spmb, material_id == -1 ?
1164 -1 : spmb->getMaterialID(q.first)));
1165 }
1166 texture++;
1167 }
1168 }
1169 }
1170 }
1171
1172 // ----------------------------------------------------------------------------
uploadSkinningMatrices()1173 void uploadSkinningMatrices()
1174 {
1175 if (g_skinning_mesh.empty())
1176 {
1177 return;
1178 }
1179
1180 unsigned buffer_offset = 0;
1181 #ifndef USE_GLES2
1182 if (CVS->isARBTextureBufferObjectUsable() &&
1183 !CVS->isARBBufferStorageUsable())
1184 {
1185 glBindBuffer(GL_TEXTURE_BUFFER, g_skinning_buf);
1186 g_joint_ptr = (std::array<float, 16>*)
1187 glMapBufferRange(GL_TEXTURE_BUFFER, 64, (g_skinning_offset - 1) * 64,
1188 GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT |
1189 GL_MAP_INVALIDATE_RANGE_BIT);
1190 }
1191 #endif
1192
1193 for (unsigned i = 0; i < g_skinning_mesh.size(); i++)
1194 {
1195 memcpy(g_joint_ptr + buffer_offset,
1196 g_skinning_mesh[i]->getSkinningMatrices(),
1197 g_skinning_mesh[i]->getTotalJoints() * 64);
1198 buffer_offset += g_skinning_mesh[i]->getTotalJoints();
1199 }
1200
1201 if (!CVS->isARBTextureBufferObjectUsable())
1202 {
1203 glBindTexture(GL_TEXTURE_2D, g_skinning_tex);
1204 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 1, 4, buffer_offset, GL_RGBA,
1205 GL_FLOAT, g_joint_ptr);
1206 glBindTexture(GL_TEXTURE_2D, 0);
1207 }
1208
1209 #ifndef USE_GLES2
1210 if (CVS->isARBTextureBufferObjectUsable() &&
1211 !CVS->isARBBufferStorageUsable())
1212 {
1213 glUnmapBuffer(GL_TEXTURE_BUFFER);
1214 glBindBuffer(GL_TEXTURE_BUFFER, 0);
1215 }
1216 #endif
1217 }
1218
1219 // ----------------------------------------------------------------------------
uploadAll()1220 void uploadAll()
1221 {
1222 uploadSkinningMatrices();
1223 glBindBuffer(GL_UNIFORM_BUFFER,
1224 sp_mat_ubo[sp_cur_player][sp_cur_buf_id[sp_cur_player]]);
1225 /*void* ptr = glMapBufferRange(GL_UNIFORM_BUFFER, 0,
1226 (16 * 9 + 2) * sizeof(float), GL_MAP_WRITE_BIT |
1227 GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
1228 memcpy(ptr, g_stk_sbr->getShadowMatrices()->getMatricesData(),
1229 (16 * 9 + 2) * sizeof(float));
1230 glUnmapBuffer(GL_UNIFORM_BUFFER);*/
1231 glBufferSubData(GL_UNIFORM_BUFFER, 0, (16 * 9 + 2) * sizeof(float),
1232 g_stk_sbr->getShadowMatrices()->getMatricesData());
1233 glBindBuffer(GL_UNIFORM_BUFFER, 0);
1234
1235 for (SPMeshBuffer* spmb : g_instances)
1236 {
1237 spmb->uploadInstanceData();
1238 }
1239
1240 g_dy_dc.erase(std::remove_if(g_dy_dc.begin(), g_dy_dc.end(),
1241 [] (std::shared_ptr<SPDynamicDrawCall> dc)
1242 {
1243 return dc->isRemoving();
1244 }), g_dy_dc.end());
1245 }
1246
1247 // ----------------------------------------------------------------------------
drawSPDebugView()1248 void drawSPDebugView()
1249 {
1250 if (g_normal_visualizer == NULL)
1251 {
1252 return;
1253 }
1254 g_normal_visualizer->use();
1255 g_normal_visualizer->bindPrefilledTextures();
1256 for (unsigned i = 0; i < g_final_draw_calls[0].size(); i++)
1257 {
1258 auto& p = g_final_draw_calls[0][i];
1259 for (unsigned j = 0; j < p.second.size(); j++)
1260 {
1261 for (unsigned k = 0; k < p.second[j].second.size(); k++)
1262 {
1263 // Make sure tangents and joints are not drawn undefined
1264 glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 0.0f);
1265 glVertexAttribI4i(6, 0, 0, 0, 0);
1266 glVertexAttrib4f(7, 0.0f, 0.0f, 0.0f, 0.0f);
1267 p.second[j].second[k].first->draw(DCT_NORMAL,
1268 -1/*material_id*/);
1269 }
1270 }
1271 }
1272 for (unsigned i = 0; i < g_final_draw_calls[5].size(); i++)
1273 {
1274 auto& p = g_final_draw_calls[5][i];
1275 for (unsigned j = 0; j < p.second.size(); j++)
1276 {
1277 for (unsigned k = 0; k < p.second[j].second.size(); k++)
1278 {
1279 // Make sure tangents and joints are not drawn undefined
1280 glVertexAttrib4f(5, 0.0f, 0.0f, 0.0f, 0.0f);
1281 glVertexAttribI4i(6, 0, 0, 0, 0);
1282 glVertexAttrib4f(7, 0.0f, 0.0f, 0.0f, 0.0f);
1283 p.second[j].second[k].first->draw(DCT_TRANSPARENT,
1284 -1/*material_id*/);
1285 }
1286 }
1287 }
1288 g_normal_visualizer->unuse();
1289 }
1290
1291 // ----------------------------------------------------------------------------
drawGlow()1292 void drawGlow()
1293 {
1294 if (g_glow_meshes.empty())
1295 {
1296 return;
1297 }
1298 g_glow_shader->use();
1299 SPUniformAssigner* glow_color_assigner =
1300 g_glow_shader->getUniformAssigner("col");
1301 assert(glow_color_assigner != NULL);
1302 for (auto& p : g_glow_meshes)
1303 {
1304 glow_color_assigner->setValue(p.second.first);
1305 for (SPMeshBuffer* spmb : p.second.second)
1306 {
1307 spmb->draw(DCT_NORMAL, -1/*material_id*/);
1308 }
1309 }
1310 g_glow_shader->unuse();
1311 }
1312
1313 // ----------------------------------------------------------------------------
draw(RenderPass rp,DrawCallType dct)1314 void draw(RenderPass rp, DrawCallType dct)
1315 {
1316 std::stringstream profiler_name;
1317 profiler_name << "SP::Draw " << dct << " with " << rp;
1318 PROFILER_PUSH_CPU_MARKER(profiler_name.str().c_str(),
1319 (uint8_t)(float(dct + rp + 2) / float(DCT_FOR_VAO + RP_COUNT) * 255.0f),
1320 (uint8_t)(float(dct + 1) / (float)DCT_FOR_VAO * 255.0f) ,
1321 (uint8_t)(float(rp + 1) / (float)RP_COUNT * 255.0f));
1322
1323 assert(dct < DCT_FOR_VAO);
1324 for (unsigned i = 0; i < g_final_draw_calls[dct].size(); i++)
1325 {
1326 auto& p = g_final_draw_calls[dct][i];
1327 if (!p.first->hasShader(rp))
1328 {
1329 continue;
1330 }
1331 p.first->use(rp);
1332 static std::vector<SPUniformAssigner*> shader_uniforms;
1333 p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
1334 (p.first), &shader_uniforms, rp);
1335 p.first->bindPrefilledTextures(rp);
1336 for (unsigned j = 0; j < p.second.size(); j++)
1337 {
1338 p.first->bindTextures(p.second[j].first, rp);
1339 for (unsigned k = 0; k < p.second[j].second.size(); k++)
1340 {
1341 static std::vector<SPUniformAssigner*> draw_call_uniforms;
1342 p.first->setUniformsPerObject(static_cast<SPPerObjectUniform*>
1343 (p.second[j].second[k].first), &draw_call_uniforms, rp);
1344 p.second[j].second[k].first->draw(dct,
1345 p.second[j].second[k].second/*material_id*/);
1346 for (SPUniformAssigner* ua : draw_call_uniforms)
1347 {
1348 ua->reset();
1349 }
1350 draw_call_uniforms.clear();
1351 }
1352 }
1353 for (SPUniformAssigner* ua : shader_uniforms)
1354 {
1355 ua->reset();
1356 }
1357 shader_uniforms.clear();
1358 p.first->unuse(rp);
1359 }
1360 PROFILER_POP_CPU_MARKER();
1361 } // draw
1362
1363 // ----------------------------------------------------------------------------
drawBoundingBoxes()1364 void drawBoundingBoxes()
1365 {
1366 Shaders::ColoredLine *line = Shaders::ColoredLine::getInstance();
1367 line->use();
1368 line->bindVertexArray();
1369 line->bindBuffer();
1370 line->setUniforms(irr::video::SColor(255, 255, 0, 0));
1371 const float *tmp = g_bounding_boxes.data();
1372 for (unsigned int i = 0; i < g_bounding_boxes.size(); i += 1024 * 6)
1373 {
1374 unsigned count = std::min((unsigned)g_bounding_boxes.size() - i,
1375 (unsigned)1024 * 6);
1376 glBufferSubData(GL_ARRAY_BUFFER, 0, count * sizeof(float), &tmp[i]);
1377 glDrawArrays(GL_LINES, 0, count / 3);
1378 }
1379 } // drawBoundingBoxes
1380
1381 // ----------------------------------------------------------------------------
addDynamicDrawCall(std::shared_ptr<SPDynamicDrawCall> dy_dc)1382 void addDynamicDrawCall(std::shared_ptr<SPDynamicDrawCall> dy_dc)
1383 {
1384 g_dy_dc.push_back(dy_dc);
1385 } // addDynamicDrawCall
1386
1387 // ----------------------------------------------------------------------------
convertEVTStandard(irr::scene::IMesh * mesh,const irr::video::SColor * color)1388 SPMesh* convertEVTStandard(irr::scene::IMesh* mesh,
1389 const irr::video::SColor* color)
1390 {
1391 SPMesh* spm = new SPMesh();
1392 Material* material = material_manager->getDefaultSPMaterial("solid");
1393 for (unsigned i = 0; i < mesh->getMeshBufferCount(); i++)
1394 {
1395 std::vector<video::S3DVertexSkinnedMesh> vertices;
1396 scene::IMeshBuffer* mb = mesh->getMeshBuffer(i);
1397 if (!mb)
1398 {
1399 continue;
1400 }
1401 assert(mb->getVertexType() == video::EVT_STANDARD);
1402 video::S3DVertex* v_ptr = (video::S3DVertex*)mb->getVertices();
1403 for (unsigned j = 0; j < mb->getVertexCount(); j++)
1404 {
1405 video::S3DVertexSkinnedMesh sp;
1406 sp.m_position = v_ptr[j].Pos;
1407 sp.m_normal = MiniGLM::compressVector3(v_ptr[j].Normal);
1408 sp.m_color = color ? *color : v_ptr[j].Color;
1409 sp.m_all_uvs[0] = MiniGLM::toFloat16(v_ptr[j].TCoords.X);
1410 sp.m_all_uvs[1] = MiniGLM::toFloat16(v_ptr[j].TCoords.Y);
1411 vertices.push_back(sp);
1412 }
1413 uint16_t* idx_ptr = mb->getIndices();
1414 std::vector<uint16_t> indices(idx_ptr, idx_ptr + mb->getIndexCount());
1415 SPMeshBuffer* buffer = new SPMeshBuffer();
1416 buffer->setSPMVertices(vertices);
1417 buffer->setIndices(indices);
1418 buffer->setSTKMaterial(material);
1419 spm->addSPMeshBuffer(buffer);
1420 }
1421 mesh->drop();
1422 spm->updateBoundingBox();
1423 return spm;
1424 } // convertEVTStandard
1425
1426 // ----------------------------------------------------------------------------
uploadSPM(irr::scene::IMesh * mesh)1427 void uploadSPM(irr::scene::IMesh* mesh)
1428 {
1429 if (!CVS->isGLSL())
1430 {
1431 return;
1432 }
1433 SP::SPMesh* spm = dynamic_cast<SP::SPMesh*>(mesh);
1434 if (spm)
1435 {
1436 for (u32 i = 0; i < spm->getMeshBufferCount(); i++)
1437 {
1438 SP::SPMeshBuffer* mb = spm->getSPMeshBuffer(i);
1439 mb->uploadGLMesh();
1440 }
1441 }
1442 } // uploadSPM
1443
1444 // ----------------------------------------------------------------------------
setMaxTextureSize()1445 void setMaxTextureSize()
1446 {
1447 const unsigned max =
1448 (UserConfigParams::m_high_definition_textures & 0x01) == 0 ?
1449 UserConfigParams::m_max_texture_size : 2048;
1450 sp_max_texture_size.store(max);
1451 } // setMaxTextureSize
1452
1453 }
1454
1455 #endif
1456