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 #include "graphics/sp/sp_dynamic_draw_call.hpp"
19 #include "graphics/graphics_restrictions.hpp"
20 #include "graphics/material.hpp"
21 #include "graphics/sp/sp_shader.hpp"
22 #include "graphics/sp/sp_texture.hpp"
23 #include "graphics/sp/sp_texture_manager.hpp"
24 #include "utils/mini_glm.hpp"
25 #include "utils/string_utils.hpp"
26 
27 namespace SP
28 {
29 // ----------------------------------------------------------------------------
SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,std::shared_ptr<SPShader> shader,Material * m)30 SPDynamicDrawCall::SPDynamicDrawCall(scene::E_PRIMITIVE_TYPE pt,
31                                      std::shared_ptr<SPShader> shader,
32                                      Material* m)
33                  : SPMeshBuffer()
34 {
35 #ifndef SERVER_ONLY
36     m_primitive_type = pt;
37     m_shaders[0] = shader;
38     m_stk_material[0] = std::make_tuple(0u, 0u, m);
39     m_textures.resize(m_stk_material.size());
40     for (unsigned j = 0; j < 6; j++)
41     {
42         m_textures[0][j] = SPTextureManager::get()->getTexture(
43             m_shaders[0] && m_shaders[0]->hasTextureLayer(j) ?
44             std::get<2>(m_stk_material[0])->getSamplerPath(j) : "",
45             j == 0 ? std::get<2>(m_stk_material[0]) : NULL,
46             m_shaders[0] && m_shaders[0]->isSrgbForTextureLayer(j),
47             std::get<2>(m_stk_material[0])->getContainerId());
48     }
49     m_tex_cmp[m_textures[0][0]->getPath() + m_textures[0][1]->getPath()] = 0;
50     m_pitch = 48;
51 
52     // Rerserve 4 vertices, and use m_ibo buffer for instance array
53     glGenBuffers(1, &m_vbo);
54     m_vertices.reserve(4);
55     glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
56     glBufferData(GL_ARRAY_BUFFER, 4 * 48, NULL, GL_DYNAMIC_DRAW);
57     glGenBuffers(1, &m_ibo);
58     glBindBuffer(GL_ARRAY_BUFFER, m_ibo);
59     glBufferData(GL_ARRAY_BUFFER, 44, NULL, GL_DYNAMIC_DRAW);
60     SPInstancedData id = SPInstancedData(m_trans, 0.0f, 0.0f, 0.0f, 0);
61     glBufferSubData(GL_ARRAY_BUFFER, 0, 44, &id);
62     SPTextureManager::get()->increaseGLCommandFunctionCount(1);
63     SPTextureManager::get()->addGLCommandFunction
64         (std::bind(&SPDynamicDrawCall::initTextureDyDc, this));
65     glBindBuffer(GL_ARRAY_BUFFER, 0);
66 
67     glGenVertexArrays(1, &m_vao[0]);
68     glBindVertexArray(m_vao[0]);
69 
70     size_t offset = 0;
71     glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
72     // Position
73     glEnableVertexAttribArray(0);
74     glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 48, (void*)offset);
75     offset += 12;
76 
77     // Normal, if 10bit vector normalization is wrongly done by drivers, use
78     // original value and normalize ourselves in shader
79     glEnableVertexAttribArray(1);
80     glVertexAttribPointer(1, 4, GL_INT_2_10_10_10_REV,
81         GraphicsRestrictions::isDisabled
82         (GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION) ?
83         GL_FALSE : GL_TRUE, 48, (void*)offset);
84     offset += 4;
85 
86     // Vertex color
87     glEnableVertexAttribArray(2);
88     glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 48,
89         (void*)offset);
90     offset += 4;
91 
92     // 1st texture coordinates
93     glEnableVertexAttribArray(3);
94     glVertexAttribPointer(3, 2, GL_HALF_FLOAT, GL_FALSE, 48, (void*)offset);
95     offset += 4;
96     // 2nd texture coordinates
97     glEnableVertexAttribArray(4);
98     glVertexAttribPointer(4, 2, GL_HALF_FLOAT, GL_FALSE, 48,
99         (void*)offset);
100     offset += 4;
101 
102     // Tangent and bi-tanget sign
103     glEnableVertexAttribArray(5);
104     glVertexAttribPointer(5, 4, GL_INT_2_10_10_10_REV,
105         GraphicsRestrictions::isDisabled
106         (GraphicsRestrictions::GR_CORRECT_10BIT_NORMALIZATION) ?
107         GL_FALSE : GL_TRUE, 48, (void*)offset);
108         offset += 4;
109 
110     // 4 Joint indices
111     glEnableVertexAttribArray(6);
112     glVertexAttribIPointer(6, 4, GL_SHORT, 48, (void*)offset);
113     offset += 8;
114     // 4 Joint weights
115     glEnableVertexAttribArray(7);
116     glVertexAttribPointer(7, 4, GL_HALF_FLOAT, GL_FALSE, 48,
117         (void*)offset);
118     offset += 8;
119 
120     glBindBuffer(GL_ARRAY_BUFFER, m_ibo);
121     // Origin
122     glEnableVertexAttribArray(8);
123     glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 44, (void*)0);
124     glVertexAttribDivisorARB(8, 1);
125     // Rotation (quaternion in 4 32bit floats)
126     glEnableVertexAttribArray(9);
127     glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, 44, (void*)12);
128     glVertexAttribDivisorARB(9, 1);
129     // Scale (3 half floats and .w unused)
130     glEnableVertexAttribArray(10);
131     glVertexAttribPointer(10, 4, GL_HALF_FLOAT, GL_FALSE, 44, (void*)28);
132     glVertexAttribDivisorARB(10, 1);
133     // Texture translation
134     glEnableVertexAttribArray(11);
135     glVertexAttribPointer(11, 2, GL_SHORT, GL_TRUE, 44, (void*)36);
136     glVertexAttribDivisorARB(11, 1);
137     // Misc data (skinning offset and hue change)
138     glEnableVertexAttribArray(12);
139     glVertexAttribIPointer(12, 2, GL_SHORT, 44, (void*)40);
140     glVertexAttribDivisorARB(12, 1);
141     glBindVertexArray(0);
142     glBindBuffer(GL_ARRAY_BUFFER, 0);
143 #endif
144 }   // SPDynamicDrawCall
145 
146 // ----------------------------------------------------------------------------
initTextureDyDc()147 bool SPDynamicDrawCall::initTextureDyDc()
148 {
149 #ifndef SERVER_ONLY
150     for (unsigned i = 0; i < m_stk_material.size(); i++)
151     {
152         for (unsigned j = 0; j < 6; j++)
153         {
154             if (!m_textures[i][j]->initialized())
155             {
156                 return false;
157             }
158         }
159     }
160 #endif
161     return true;
162 }   // initTextureDyDc
163 
164 }
165