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