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