1 | #include "backend_opengl3.h" |
2 | |
3 | #include <base/detect.h> |
4 | |
5 | #if defined(BACKEND_AS_OPENGL_ES) || !defined(CONF_BACKEND_OPENGL_ES) |
6 | |
7 | #ifndef BACKEND_AS_OPENGL_ES |
8 | #include <GL/glew.h> |
9 | #else |
10 | #include <GLES3/gl3.h> |
11 | #endif |
12 | |
13 | #include <engine/client/backend_sdl.h> |
14 | |
15 | #include <engine/client/backend/opengl/opengl_sl.h> |
16 | #include <engine/client/backend/opengl/opengl_sl_program.h> |
17 | |
18 | #include <engine/gfx/image_manipulation.h> |
19 | |
20 | #include <engine/client/backend/glsl_shader_compiler.h> |
21 | |
22 | #ifdef CONF_WEBASM |
23 | // WebGL2 defines the type of a buffer at the first bind to a buffer target |
24 | // this is different to GLES 3 (https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.1) |
25 | static constexpr GLenum BUFFER_INIT_INDEX_TARGET = GL_ELEMENT_ARRAY_BUFFER; |
26 | static constexpr GLenum BUFFER_INIT_VERTEX_TARGET = GL_ARRAY_BUFFER; |
27 | #else |
28 | static constexpr GLenum BUFFER_INIT_INDEX_TARGET = GL_COPY_WRITE_BUFFER; |
29 | static constexpr GLenum BUFFER_INIT_VERTEX_TARGET = GL_COPY_WRITE_BUFFER; |
30 | #endif |
31 | |
32 | // ------------ CCommandProcessorFragment_OpenGL3_3 |
33 | void CCommandProcessorFragment_OpenGL3_3::UseProgram(CGLSLTWProgram *pProgram) |
34 | { |
35 | if(m_LastProgramId != pProgram->GetProgramId()) |
36 | { |
37 | pProgram->UseProgram(); |
38 | m_LastProgramId = pProgram->GetProgramId(); |
39 | } |
40 | } |
41 | |
42 | void CCommandProcessorFragment_OpenGL3_3::InitPrimExProgram(CGLSLPrimitiveExProgram *pProgram, CGLSLCompiler *pCompiler, IStorage *pStorage, bool Textured, bool Rotationless) |
43 | { |
44 | CGLSL PrimitiveVertexShader; |
45 | CGLSL PrimitiveFragmentShader; |
46 | if(Textured) |
47 | pCompiler->AddDefine(pDefineName: "TW_TEXTURED" , pDefineValue: "" ); |
48 | if(Rotationless) |
49 | pCompiler->AddDefine(pDefineName: "TW_ROTATIONLESS" , pDefineValue: "" ); |
50 | PrimitiveVertexShader.LoadShader(pCompiler, pStorage, pFile: "shader/primex.vert" , GL_VERTEX_SHADER); |
51 | PrimitiveFragmentShader.LoadShader(pCompiler, pStorage, pFile: "shader/primex.frag" , GL_FRAGMENT_SHADER); |
52 | if(Textured || Rotationless) |
53 | pCompiler->ClearDefines(); |
54 | |
55 | pProgram->CreateProgram(); |
56 | pProgram->AddShader(pShader: &PrimitiveVertexShader); |
57 | pProgram->AddShader(pShader: &PrimitiveFragmentShader); |
58 | pProgram->LinkProgram(); |
59 | |
60 | UseProgram(pProgram); |
61 | |
62 | pProgram->m_LocPos = pProgram->GetUniformLoc(pName: "gPos" ); |
63 | pProgram->m_LocTextureSampler = pProgram->GetUniformLoc(pName: "gTextureSampler" ); |
64 | pProgram->m_LocRotation = pProgram->GetUniformLoc(pName: "gRotation" ); |
65 | pProgram->m_LocCenter = pProgram->GetUniformLoc(pName: "gCenter" ); |
66 | pProgram->m_LocVertciesColor = pProgram->GetUniformLoc(pName: "gVerticesColor" ); |
67 | |
68 | pProgram->SetUniform(Loc: pProgram->m_LocRotation, Value: 0.0f); |
69 | float aCenter[2] = {0.f, 0.f}; |
70 | pProgram->SetUniformVec2(Loc: pProgram->m_LocCenter, Count: 1, pValue: aCenter); |
71 | } |
72 | |
73 | bool CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand) |
74 | { |
75 | if(!InitOpenGL(pCommand)) |
76 | return false; |
77 | |
78 | m_OpenGLTextureLodBIAS = g_Config.m_GfxGLTextureLODBIAS; |
79 | |
80 | glActiveTexture(GL_TEXTURE0); |
81 | |
82 | m_Has2DArrayTextures = true; |
83 | m_Has2DArrayTexturesAsExtension = false; |
84 | m_2DArrayTarget = GL_TEXTURE_2D_ARRAY; |
85 | m_Has3DTextures = false; |
86 | m_HasMipMaps = true; |
87 | m_HasNPOTTextures = true; |
88 | m_HasShaders = true; |
89 | |
90 | m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage; |
91 | m_pTextureMemoryUsage->store(i: 0, m: std::memory_order_relaxed); |
92 | m_LastBlendMode = CCommandBuffer::BLEND_ALPHA; |
93 | m_LastClipEnable = false; |
94 | m_pPrimitiveProgram = new CGLSLPrimitiveProgram; |
95 | m_pPrimitiveProgramTextured = new CGLSLPrimitiveProgram; |
96 | m_pTileProgram = new CGLSLTileProgram; |
97 | m_pTileProgramTextured = new CGLSLTileProgram; |
98 | m_pPrimitive3DProgram = new CGLSLPrimitiveProgram; |
99 | m_pPrimitive3DProgramTextured = new CGLSLPrimitiveProgram; |
100 | m_pBorderTileProgram = new CGLSLTileProgram; |
101 | m_pBorderTileProgramTextured = new CGLSLTileProgram; |
102 | m_pQuadProgram = new CGLSLQuadProgram; |
103 | m_pQuadProgramTextured = new CGLSLQuadProgram; |
104 | m_pTextProgram = new CGLSLTextProgram; |
105 | m_pPrimitiveExProgram = new CGLSLPrimitiveExProgram; |
106 | m_pPrimitiveExProgramTextured = new CGLSLPrimitiveExProgram; |
107 | m_pPrimitiveExProgramRotationless = new CGLSLPrimitiveExProgram; |
108 | m_pPrimitiveExProgramTexturedRotationless = new CGLSLPrimitiveExProgram; |
109 | m_pSpriteProgramMultiple = new CGLSLSpriteMultipleProgram; |
110 | m_LastProgramId = 0; |
111 | |
112 | CGLSLCompiler ShaderCompiler(g_Config.m_GfxGLMajor, g_Config.m_GfxGLMinor, g_Config.m_GfxGLPatch, m_IsOpenGLES, m_OpenGLTextureLodBIAS / 1000.0f); |
113 | |
114 | GLint CapVal; |
115 | glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, params: &CapVal); |
116 | |
117 | m_MaxQuadsAtOnce = minimum<int>(a: ((CapVal - 20) / (3 * 4)), b: ms_MaxQuadsPossible); |
118 | |
119 | { |
120 | CGLSL PrimitiveVertexShader; |
121 | CGLSL PrimitiveFragmentShader; |
122 | PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.vert" , GL_VERTEX_SHADER); |
123 | PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.frag" , GL_FRAGMENT_SHADER); |
124 | |
125 | m_pPrimitiveProgram->CreateProgram(); |
126 | m_pPrimitiveProgram->AddShader(pShader: &PrimitiveVertexShader); |
127 | m_pPrimitiveProgram->AddShader(pShader: &PrimitiveFragmentShader); |
128 | m_pPrimitiveProgram->LinkProgram(); |
129 | |
130 | UseProgram(pProgram: m_pPrimitiveProgram); |
131 | |
132 | m_pPrimitiveProgram->m_LocPos = m_pPrimitiveProgram->GetUniformLoc(pName: "gPos" ); |
133 | m_pPrimitiveProgram->m_LocTextureSampler = m_pPrimitiveProgram->GetUniformLoc(pName: "gTextureSampler" ); |
134 | } |
135 | { |
136 | CGLSL PrimitiveVertexShader; |
137 | CGLSL PrimitiveFragmentShader; |
138 | ShaderCompiler.AddDefine(pDefineName: "TW_TEXTURED" , pDefineValue: "" ); |
139 | PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.vert" , GL_VERTEX_SHADER); |
140 | PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/prim.frag" , GL_FRAGMENT_SHADER); |
141 | ShaderCompiler.ClearDefines(); |
142 | |
143 | m_pPrimitiveProgramTextured->CreateProgram(); |
144 | m_pPrimitiveProgramTextured->AddShader(pShader: &PrimitiveVertexShader); |
145 | m_pPrimitiveProgramTextured->AddShader(pShader: &PrimitiveFragmentShader); |
146 | m_pPrimitiveProgramTextured->LinkProgram(); |
147 | |
148 | UseProgram(pProgram: m_pPrimitiveProgramTextured); |
149 | |
150 | m_pPrimitiveProgramTextured->m_LocPos = m_pPrimitiveProgramTextured->GetUniformLoc(pName: "gPos" ); |
151 | m_pPrimitiveProgramTextured->m_LocTextureSampler = m_pPrimitiveProgramTextured->GetUniformLoc(pName: "gTextureSampler" ); |
152 | } |
153 | |
154 | { |
155 | CGLSL PrimitiveVertexShader; |
156 | CGLSL PrimitiveFragmentShader; |
157 | ShaderCompiler.AddDefine(pDefineName: "TW_MODERN_GL" , pDefineValue: "" ); |
158 | PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.vert" , GL_VERTEX_SHADER); |
159 | PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.frag" , GL_FRAGMENT_SHADER); |
160 | ShaderCompiler.ClearDefines(); |
161 | |
162 | m_pPrimitive3DProgram->CreateProgram(); |
163 | m_pPrimitive3DProgram->AddShader(pShader: &PrimitiveVertexShader); |
164 | m_pPrimitive3DProgram->AddShader(pShader: &PrimitiveFragmentShader); |
165 | m_pPrimitive3DProgram->LinkProgram(); |
166 | |
167 | UseProgram(pProgram: m_pPrimitive3DProgram); |
168 | |
169 | m_pPrimitive3DProgram->m_LocPos = m_pPrimitive3DProgram->GetUniformLoc(pName: "gPos" ); |
170 | } |
171 | { |
172 | CGLSL PrimitiveVertexShader; |
173 | CGLSL PrimitiveFragmentShader; |
174 | ShaderCompiler.AddDefine(pDefineName: "TW_MODERN_GL" , pDefineValue: "" ); |
175 | ShaderCompiler.AddDefine(pDefineName: "TW_TEXTURED" , pDefineValue: "" ); |
176 | if(!pCommand->m_pCapabilities->m_2DArrayTextures) |
177 | ShaderCompiler.AddDefine(pDefineName: "TW_3D_TEXTURED" , pDefineValue: "" ); |
178 | PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.vert" , GL_VERTEX_SHADER); |
179 | PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/pipeline.frag" , GL_FRAGMENT_SHADER); |
180 | ShaderCompiler.ClearDefines(); |
181 | |
182 | m_pPrimitive3DProgramTextured->CreateProgram(); |
183 | m_pPrimitive3DProgramTextured->AddShader(pShader: &PrimitiveVertexShader); |
184 | m_pPrimitive3DProgramTextured->AddShader(pShader: &PrimitiveFragmentShader); |
185 | m_pPrimitive3DProgramTextured->LinkProgram(); |
186 | |
187 | UseProgram(pProgram: m_pPrimitive3DProgramTextured); |
188 | |
189 | m_pPrimitive3DProgramTextured->m_LocPos = m_pPrimitive3DProgramTextured->GetUniformLoc(pName: "gPos" ); |
190 | m_pPrimitive3DProgramTextured->m_LocTextureSampler = m_pPrimitive3DProgramTextured->GetUniformLoc(pName: "gTextureSampler" ); |
191 | } |
192 | |
193 | { |
194 | CGLSL VertexShader; |
195 | CGLSL FragmentShader; |
196 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.vert" , GL_VERTEX_SHADER); |
197 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.frag" , GL_FRAGMENT_SHADER); |
198 | |
199 | m_pTileProgram->CreateProgram(); |
200 | m_pTileProgram->AddShader(pShader: &VertexShader); |
201 | m_pTileProgram->AddShader(pShader: &FragmentShader); |
202 | m_pTileProgram->LinkProgram(); |
203 | |
204 | UseProgram(pProgram: m_pTileProgram); |
205 | |
206 | m_pTileProgram->m_LocPos = m_pTileProgram->GetUniformLoc(pName: "gPos" ); |
207 | m_pTileProgram->m_LocColor = m_pTileProgram->GetUniformLoc(pName: "gVertColor" ); |
208 | } |
209 | { |
210 | CGLSL VertexShader; |
211 | CGLSL FragmentShader; |
212 | ShaderCompiler.AddDefine(pDefineName: "TW_TILE_TEXTURED" , pDefineValue: "" ); |
213 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.vert" , GL_VERTEX_SHADER); |
214 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile.frag" , GL_FRAGMENT_SHADER); |
215 | ShaderCompiler.ClearDefines(); |
216 | |
217 | m_pTileProgramTextured->CreateProgram(); |
218 | m_pTileProgramTextured->AddShader(pShader: &VertexShader); |
219 | m_pTileProgramTextured->AddShader(pShader: &FragmentShader); |
220 | m_pTileProgramTextured->LinkProgram(); |
221 | |
222 | UseProgram(pProgram: m_pTileProgramTextured); |
223 | |
224 | m_pTileProgramTextured->m_LocPos = m_pTileProgramTextured->GetUniformLoc(pName: "gPos" ); |
225 | m_pTileProgramTextured->m_LocTextureSampler = m_pTileProgramTextured->GetUniformLoc(pName: "gTextureSampler" ); |
226 | m_pTileProgramTextured->m_LocColor = m_pTileProgramTextured->GetUniformLoc(pName: "gVertColor" ); |
227 | } |
228 | { |
229 | CGLSL VertexShader; |
230 | CGLSL FragmentShader; |
231 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.vert" , GL_VERTEX_SHADER); |
232 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.frag" , GL_FRAGMENT_SHADER); |
233 | ShaderCompiler.ClearDefines(); |
234 | |
235 | m_pBorderTileProgram->CreateProgram(); |
236 | m_pBorderTileProgram->AddShader(pShader: &VertexShader); |
237 | m_pBorderTileProgram->AddShader(pShader: &FragmentShader); |
238 | m_pBorderTileProgram->LinkProgram(); |
239 | |
240 | UseProgram(pProgram: m_pBorderTileProgram); |
241 | |
242 | m_pBorderTileProgram->m_LocPos = m_pBorderTileProgram->GetUniformLoc(pName: "gPos" ); |
243 | m_pBorderTileProgram->m_LocColor = m_pBorderTileProgram->GetUniformLoc(pName: "gVertColor" ); |
244 | m_pBorderTileProgram->m_LocOffset = m_pBorderTileProgram->GetUniformLoc(pName: "gOffset" ); |
245 | m_pBorderTileProgram->m_LocScale = m_pBorderTileProgram->GetUniformLoc(pName: "gScale" ); |
246 | } |
247 | { |
248 | CGLSL VertexShader; |
249 | CGLSL FragmentShader; |
250 | ShaderCompiler.AddDefine(pDefineName: "TW_TILE_TEXTURED" , pDefineValue: "" ); |
251 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.vert" , GL_VERTEX_SHADER); |
252 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/tile_border.frag" , GL_FRAGMENT_SHADER); |
253 | ShaderCompiler.ClearDefines(); |
254 | |
255 | m_pBorderTileProgramTextured->CreateProgram(); |
256 | m_pBorderTileProgramTextured->AddShader(pShader: &VertexShader); |
257 | m_pBorderTileProgramTextured->AddShader(pShader: &FragmentShader); |
258 | m_pBorderTileProgramTextured->LinkProgram(); |
259 | |
260 | UseProgram(pProgram: m_pBorderTileProgramTextured); |
261 | |
262 | m_pBorderTileProgramTextured->m_LocPos = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gPos" ); |
263 | m_pBorderTileProgramTextured->m_LocTextureSampler = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gTextureSampler" ); |
264 | m_pBorderTileProgramTextured->m_LocColor = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gVertColor" ); |
265 | m_pBorderTileProgramTextured->m_LocOffset = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gOffset" ); |
266 | m_pBorderTileProgramTextured->m_LocScale = m_pBorderTileProgramTextured->GetUniformLoc(pName: "gScale" ); |
267 | } |
268 | { |
269 | CGLSL VertexShader; |
270 | CGLSL FragmentShader; |
271 | ShaderCompiler.AddDefine(pDefineName: "TW_MAX_QUADS" , pDefineValue: std::to_string(val: m_MaxQuadsAtOnce).c_str()); |
272 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert" , GL_VERTEX_SHADER); |
273 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag" , GL_FRAGMENT_SHADER); |
274 | ShaderCompiler.ClearDefines(); |
275 | |
276 | m_pQuadProgram->CreateProgram(); |
277 | m_pQuadProgram->AddShader(pShader: &VertexShader); |
278 | m_pQuadProgram->AddShader(pShader: &FragmentShader); |
279 | m_pQuadProgram->LinkProgram(); |
280 | |
281 | UseProgram(pProgram: m_pQuadProgram); |
282 | |
283 | m_pQuadProgram->m_LocPos = m_pQuadProgram->GetUniformLoc(pName: "gPos" ); |
284 | m_pQuadProgram->m_LocColors = m_pQuadProgram->GetUniformLoc(pName: "gVertColors" ); |
285 | m_pQuadProgram->m_LocRotations = m_pQuadProgram->GetUniformLoc(pName: "gRotations" ); |
286 | m_pQuadProgram->m_LocOffsets = m_pQuadProgram->GetUniformLoc(pName: "gOffsets" ); |
287 | m_pQuadProgram->m_LocQuadOffset = m_pQuadProgram->GetUniformLoc(pName: "gQuadOffset" ); |
288 | } |
289 | { |
290 | CGLSL VertexShader; |
291 | CGLSL FragmentShader; |
292 | ShaderCompiler.AddDefine(pDefineName: "TW_QUAD_TEXTURED" , pDefineValue: "" ); |
293 | ShaderCompiler.AddDefine(pDefineName: "TW_MAX_QUADS" , pDefineValue: std::to_string(val: m_MaxQuadsAtOnce).c_str()); |
294 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.vert" , GL_VERTEX_SHADER); |
295 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/quad.frag" , GL_FRAGMENT_SHADER); |
296 | ShaderCompiler.ClearDefines(); |
297 | |
298 | m_pQuadProgramTextured->CreateProgram(); |
299 | m_pQuadProgramTextured->AddShader(pShader: &VertexShader); |
300 | m_pQuadProgramTextured->AddShader(pShader: &FragmentShader); |
301 | m_pQuadProgramTextured->LinkProgram(); |
302 | |
303 | UseProgram(pProgram: m_pQuadProgramTextured); |
304 | |
305 | m_pQuadProgramTextured->m_LocPos = m_pQuadProgramTextured->GetUniformLoc(pName: "gPos" ); |
306 | m_pQuadProgramTextured->m_LocTextureSampler = m_pQuadProgramTextured->GetUniformLoc(pName: "gTextureSampler" ); |
307 | m_pQuadProgramTextured->m_LocColors = m_pQuadProgramTextured->GetUniformLoc(pName: "gVertColors" ); |
308 | m_pQuadProgramTextured->m_LocRotations = m_pQuadProgramTextured->GetUniformLoc(pName: "gRotations" ); |
309 | m_pQuadProgramTextured->m_LocOffsets = m_pQuadProgramTextured->GetUniformLoc(pName: "gOffsets" ); |
310 | m_pQuadProgramTextured->m_LocQuadOffset = m_pQuadProgramTextured->GetUniformLoc(pName: "gQuadOffset" ); |
311 | } |
312 | { |
313 | CGLSL VertexShader; |
314 | CGLSL FragmentShader; |
315 | VertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/text.vert" , GL_VERTEX_SHADER); |
316 | FragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/text.frag" , GL_FRAGMENT_SHADER); |
317 | |
318 | m_pTextProgram->CreateProgram(); |
319 | m_pTextProgram->AddShader(pShader: &VertexShader); |
320 | m_pTextProgram->AddShader(pShader: &FragmentShader); |
321 | m_pTextProgram->LinkProgram(); |
322 | |
323 | UseProgram(pProgram: m_pTextProgram); |
324 | |
325 | m_pTextProgram->m_LocPos = m_pTextProgram->GetUniformLoc(pName: "gPos" ); |
326 | m_pTextProgram->m_LocTextureSampler = -1; |
327 | m_pTextProgram->m_LocTextSampler = m_pTextProgram->GetUniformLoc(pName: "gTextSampler" ); |
328 | m_pTextProgram->m_LocTextOutlineSampler = m_pTextProgram->GetUniformLoc(pName: "gTextOutlineSampler" ); |
329 | m_pTextProgram->m_LocColor = m_pTextProgram->GetUniformLoc(pName: "gVertColor" ); |
330 | m_pTextProgram->m_LocOutlineColor = m_pTextProgram->GetUniformLoc(pName: "gVertOutlineColor" ); |
331 | m_pTextProgram->m_LocTextureSize = m_pTextProgram->GetUniformLoc(pName: "gTextureSize" ); |
332 | } |
333 | InitPrimExProgram(pProgram: m_pPrimitiveExProgram, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: false, Rotationless: false); |
334 | InitPrimExProgram(pProgram: m_pPrimitiveExProgramTextured, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: true, Rotationless: false); |
335 | InitPrimExProgram(pProgram: m_pPrimitiveExProgramRotationless, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: false, Rotationless: true); |
336 | InitPrimExProgram(pProgram: m_pPrimitiveExProgramTexturedRotationless, pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, Textured: true, Rotationless: true); |
337 | { |
338 | CGLSL PrimitiveVertexShader; |
339 | CGLSL PrimitiveFragmentShader; |
340 | PrimitiveVertexShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/spritemulti.vert" , GL_VERTEX_SHADER); |
341 | PrimitiveFragmentShader.LoadShader(pCompiler: &ShaderCompiler, pStorage: pCommand->m_pStorage, pFile: "shader/spritemulti.frag" , GL_FRAGMENT_SHADER); |
342 | |
343 | m_pSpriteProgramMultiple->CreateProgram(); |
344 | m_pSpriteProgramMultiple->AddShader(pShader: &PrimitiveVertexShader); |
345 | m_pSpriteProgramMultiple->AddShader(pShader: &PrimitiveFragmentShader); |
346 | m_pSpriteProgramMultiple->LinkProgram(); |
347 | |
348 | UseProgram(pProgram: m_pSpriteProgramMultiple); |
349 | |
350 | m_pSpriteProgramMultiple->m_LocPos = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gPos" ); |
351 | m_pSpriteProgramMultiple->m_LocTextureSampler = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gTextureSampler" ); |
352 | m_pSpriteProgramMultiple->m_LocRSP = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gRSP[0]" ); |
353 | m_pSpriteProgramMultiple->m_LocCenter = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gCenter" ); |
354 | m_pSpriteProgramMultiple->m_LocVertciesColor = m_pSpriteProgramMultiple->GetUniformLoc(pName: "gVerticesColor" ); |
355 | |
356 | float aCenter[2] = {0.f, 0.f}; |
357 | m_pSpriteProgramMultiple->SetUniformVec2(Loc: m_pSpriteProgramMultiple->m_LocCenter, Count: 1, pValue: aCenter); |
358 | } |
359 | |
360 | m_LastStreamBuffer = 0; |
361 | |
362 | glGenBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId); |
363 | glGenVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId); |
364 | glGenBuffers(1, &m_PrimitiveDrawBufferIdTex3D); |
365 | glGenVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D); |
366 | |
367 | for(int i = 0; i < MAX_STREAM_BUFFER_COUNT; ++i) |
368 | { |
369 | glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[i]); |
370 | glBindVertexArray(m_aPrimitiveDrawVertexId[i]); |
371 | glEnableVertexAttribArray(0); |
372 | glEnableVertexAttribArray(1); |
373 | glEnableVertexAttribArray(2); |
374 | |
375 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertex), 0); |
376 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertex), (void *)(sizeof(float) * 2)); |
377 | glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(CCommandBuffer::SVertex), (void *)(sizeof(float) * 4)); |
378 | |
379 | m_aLastIndexBufferBound[i] = 0; |
380 | } |
381 | |
382 | glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D); |
383 | glBindVertexArray(m_PrimitiveDrawVertexIdTex3D); |
384 | glEnableVertexAttribArray(0); |
385 | glEnableVertexAttribArray(1); |
386 | glEnableVertexAttribArray(2); |
387 | |
388 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertexTex3DStream), 0); |
389 | glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(CCommandBuffer::SVertexTex3DStream), (void *)(sizeof(float) * 2)); |
390 | glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(CCommandBuffer::SVertexTex3DStream), (void *)(sizeof(float) * 2 + sizeof(unsigned char) * 4)); |
391 | |
392 | // query the image max size only once |
393 | glGetIntegerv(GL_MAX_TEXTURE_SIZE, params: &m_MaxTexSize); |
394 | |
395 | glBindVertexArray(0); |
396 | glGenBuffers(1, &m_QuadDrawIndexBufferId); |
397 | glBindBuffer(BUFFER_INIT_INDEX_TARGET, m_QuadDrawIndexBufferId); |
398 | |
399 | unsigned int aIndices[CCommandBuffer::MAX_VERTICES / 4 * 6]; |
400 | int Primq = 0; |
401 | for(int i = 0; i < CCommandBuffer::MAX_VERTICES / 4 * 6; i += 6) |
402 | { |
403 | aIndices[i] = Primq; |
404 | aIndices[i + 1] = Primq + 1; |
405 | aIndices[i + 2] = Primq + 2; |
406 | aIndices[i + 3] = Primq; |
407 | aIndices[i + 4] = Primq + 2; |
408 | aIndices[i + 5] = Primq + 3; |
409 | Primq += 4; |
410 | } |
411 | glBufferData(BUFFER_INIT_INDEX_TARGET, sizeof(unsigned int) * CCommandBuffer::MAX_VERTICES / 4 * 6, aIndices, GL_STATIC_DRAW); |
412 | |
413 | m_CurrentIndicesInBuffer = CCommandBuffer::MAX_VERTICES / 4 * 6; |
414 | |
415 | m_vTextures.resize(new_size: CCommandBuffer::MAX_TEXTURES); |
416 | |
417 | m_ClearColor.r = m_ClearColor.g = m_ClearColor.b = -1.f; |
418 | |
419 | // fix the alignment to allow even 1byte changes, e.g. for alpha components |
420 | glPixelStorei(GL_UNPACK_ALIGNMENT, param: 1); |
421 | |
422 | return true; |
423 | } |
424 | |
425 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Shutdown(const SCommand_Shutdown *pCommand) |
426 | { |
427 | glUseProgram(0); |
428 | |
429 | m_pPrimitiveProgram->DeleteProgram(); |
430 | m_pPrimitiveProgramTextured->DeleteProgram(); |
431 | m_pBorderTileProgram->DeleteProgram(); |
432 | m_pBorderTileProgramTextured->DeleteProgram(); |
433 | m_pQuadProgram->DeleteProgram(); |
434 | m_pQuadProgramTextured->DeleteProgram(); |
435 | m_pTileProgram->DeleteProgram(); |
436 | m_pTileProgramTextured->DeleteProgram(); |
437 | m_pPrimitive3DProgram->DeleteProgram(); |
438 | m_pPrimitive3DProgramTextured->DeleteProgram(); |
439 | m_pTextProgram->DeleteProgram(); |
440 | m_pPrimitiveExProgram->DeleteProgram(); |
441 | m_pPrimitiveExProgramTextured->DeleteProgram(); |
442 | m_pPrimitiveExProgramRotationless->DeleteProgram(); |
443 | m_pPrimitiveExProgramTexturedRotationless->DeleteProgram(); |
444 | m_pSpriteProgramMultiple->DeleteProgram(); |
445 | |
446 | // clean up everything |
447 | delete m_pPrimitiveProgram; |
448 | delete m_pPrimitiveProgramTextured; |
449 | delete m_pBorderTileProgram; |
450 | delete m_pBorderTileProgramTextured; |
451 | delete m_pQuadProgram; |
452 | delete m_pQuadProgramTextured; |
453 | delete m_pTileProgram; |
454 | delete m_pTileProgramTextured; |
455 | delete m_pPrimitive3DProgram; |
456 | delete m_pPrimitive3DProgramTextured; |
457 | delete m_pTextProgram; |
458 | delete m_pPrimitiveExProgram; |
459 | delete m_pPrimitiveExProgramTextured; |
460 | delete m_pPrimitiveExProgramRotationless; |
461 | delete m_pPrimitiveExProgramTexturedRotationless; |
462 | delete m_pSpriteProgramMultiple; |
463 | |
464 | glBindVertexArray(0); |
465 | glDeleteBuffers(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawBufferId); |
466 | glDeleteBuffers(1, &m_QuadDrawIndexBufferId); |
467 | glDeleteVertexArrays(MAX_STREAM_BUFFER_COUNT, m_aPrimitiveDrawVertexId); |
468 | glDeleteBuffers(1, &m_PrimitiveDrawBufferIdTex3D); |
469 | glDeleteVertexArrays(1, &m_PrimitiveDrawVertexIdTex3D); |
470 | |
471 | for(int i = 0; i < (int)m_vTextures.size(); ++i) |
472 | { |
473 | DestroyTexture(Slot: i); |
474 | } |
475 | |
476 | for(size_t i = 0; i < m_vBufferContainers.size(); ++i) |
477 | { |
478 | DestroyBufferContainer(Index: i); |
479 | } |
480 | |
481 | m_vBufferContainers.clear(); |
482 | } |
483 | |
484 | void CCommandProcessorFragment_OpenGL3_3::TextureUpdate(int Slot, int X, int Y, int Width, int Height, int GLFormat, uint8_t *pTexData) |
485 | { |
486 | glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[Slot].m_Tex); |
487 | |
488 | if(m_vTextures[Slot].m_RescaleCount > 0) |
489 | { |
490 | for(int i = 0; i < m_vTextures[Slot].m_RescaleCount; ++i) |
491 | { |
492 | Width >>= 1; |
493 | Height >>= 1; |
494 | |
495 | X /= 2; |
496 | Y /= 2; |
497 | } |
498 | |
499 | uint8_t *pTmpData = ResizeImage(pImageData: pTexData, Width, Height, NewWidth: Width, NewHeight: Height, BPP: GLFormatToPixelSize(GLFormat)); |
500 | free(ptr: pTexData); |
501 | pTexData = pTmpData; |
502 | } |
503 | |
504 | glTexSubImage2D(GL_TEXTURE_2D, level: 0, xoffset: X, yoffset: Y, width: Width, height: Height, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData); |
505 | free(ptr: pTexData); |
506 | } |
507 | |
508 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand) |
509 | { |
510 | TextureUpdate(Slot: pCommand->m_Slot, X: pCommand->m_X, Y: pCommand->m_Y, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RGBA, pTexData: pCommand->m_pData); |
511 | } |
512 | |
513 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand) |
514 | { |
515 | int Slot = 0; |
516 | glBindTexture(GL_TEXTURE_2D, texture: 0); |
517 | glBindSampler(Slot, 0); |
518 | DestroyTexture(Slot: pCommand->m_Slot); |
519 | } |
520 | |
521 | void CCommandProcessorFragment_OpenGL3_3::TextureCreate(int Slot, int Width, int Height, int GLFormat, int GLStoreFormat, int Flags, uint8_t *pTexData) |
522 | { |
523 | while(Slot >= (int)m_vTextures.size()) |
524 | m_vTextures.resize(new_size: m_vTextures.size() * 2); |
525 | |
526 | // resample if needed |
527 | int RescaleCount = 0; |
528 | if(GLFormat == GL_RGBA) |
529 | { |
530 | if(Width > m_MaxTexSize || Height > m_MaxTexSize) |
531 | { |
532 | do |
533 | { |
534 | Width >>= 1; |
535 | Height >>= 1; |
536 | ++RescaleCount; |
537 | } while(Width > m_MaxTexSize || Height > m_MaxTexSize); |
538 | |
539 | uint8_t *pTmpData = ResizeImage(pImageData: pTexData, Width, Height, NewWidth: Width, NewHeight: Height, BPP: GLFormatToPixelSize(GLFormat)); |
540 | free(ptr: pTexData); |
541 | pTexData = pTmpData; |
542 | } |
543 | } |
544 | m_vTextures[Slot].m_Width = Width; |
545 | m_vTextures[Slot].m_Height = Height; |
546 | m_vTextures[Slot].m_RescaleCount = RescaleCount; |
547 | |
548 | if(GLStoreFormat == GL_RED) |
549 | GLStoreFormat = GL_R8; |
550 | const size_t PixelSize = GLFormatToPixelSize(GLFormat); |
551 | |
552 | int SamplerSlot = 0; |
553 | |
554 | if((Flags & CCommandBuffer::TEXFLAG_NO_2D_TEXTURE) == 0) |
555 | { |
556 | glGenTextures(n: 1, textures: &m_vTextures[Slot].m_Tex); |
557 | glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[Slot].m_Tex); |
558 | |
559 | glGenSamplers(1, &m_vTextures[Slot].m_Sampler); |
560 | glBindSampler(SamplerSlot, m_vTextures[Slot].m_Sampler); |
561 | } |
562 | |
563 | if(Flags & CCommandBuffer::TEXFLAG_NOMIPMAPS) |
564 | { |
565 | if((Flags & CCommandBuffer::TEXFLAG_NO_2D_TEXTURE) == 0) |
566 | { |
567 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
568 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
569 | glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
570 | glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
571 | glTexImage2D(GL_TEXTURE_2D, level: 0, internalformat: GLStoreFormat, width: Width, height: Height, border: 0, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData); |
572 | } |
573 | } |
574 | else |
575 | { |
576 | if((Flags & CCommandBuffer::TEXFLAG_NO_2D_TEXTURE) == 0) |
577 | { |
578 | glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
579 | glSamplerParameteri(m_vTextures[Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); |
580 | |
581 | #ifndef BACKEND_AS_OPENGL_ES |
582 | if(m_OpenGLTextureLodBIAS != 0 && !m_IsOpenGLES) |
583 | glSamplerParameterf(m_vTextures[Slot].m_Sampler, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f)); |
584 | #endif |
585 | |
586 | // prevent mipmap display bugs, when zooming out far |
587 | if(Width >= 1024 && Height >= 1024) |
588 | { |
589 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, param: 5.f); |
590 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, param: 5); |
591 | } |
592 | glTexImage2D(GL_TEXTURE_2D, level: 0, internalformat: GLStoreFormat, width: Width, height: Height, border: 0, format: GLFormat, GL_UNSIGNED_BYTE, pixels: pTexData); |
593 | glGenerateMipmap(GL_TEXTURE_2D); |
594 | } |
595 | |
596 | if((Flags & (CCommandBuffer::TEXFLAG_TO_2D_ARRAY_TEXTURE)) != 0) |
597 | { |
598 | glGenTextures(n: 1, textures: &m_vTextures[Slot].m_Tex2DArray); |
599 | glBindTexture(GL_TEXTURE_2D_ARRAY, texture: m_vTextures[Slot].m_Tex2DArray); |
600 | |
601 | glGenSamplers(1, &m_vTextures[Slot].m_Sampler2DArray); |
602 | glBindSampler(SamplerSlot, m_vTextures[Slot].m_Sampler2DArray); |
603 | glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
604 | glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); |
605 | glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
606 | glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
607 | glSamplerParameteri(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_WRAP_R, GL_MIRRORED_REPEAT); |
608 | |
609 | #ifndef BACKEND_AS_OPENGL_ES |
610 | if(m_OpenGLTextureLodBIAS != 0 && !m_IsOpenGLES) |
611 | glSamplerParameterf(m_vTextures[Slot].m_Sampler2DArray, GL_TEXTURE_LOD_BIAS, ((GLfloat)m_OpenGLTextureLodBIAS / 1000.0f)); |
612 | #endif |
613 | |
614 | uint8_t *p3DImageData = static_cast<uint8_t *>(malloc(size: (size_t)Width * Height * PixelSize)); |
615 | int Image3DWidth, Image3DHeight; |
616 | |
617 | int ConvertWidth = Width; |
618 | int ConvertHeight = Height; |
619 | |
620 | if(ConvertWidth == 0 || (ConvertWidth % 16) != 0 || ConvertHeight == 0 || (ConvertHeight % 16) != 0) |
621 | { |
622 | dbg_msg(sys: "gfx" , fmt: "3D/2D array texture was resized" ); |
623 | int NewWidth = maximum<int>(a: HighestBit(OfVar: ConvertWidth), b: 16); |
624 | int NewHeight = maximum<int>(a: HighestBit(OfVar: ConvertHeight), b: 16); |
625 | uint8_t *pNewTexData = ResizeImage(pImageData: pTexData, Width: ConvertWidth, Height: ConvertHeight, NewWidth, NewHeight, BPP: GLFormatToPixelSize(GLFormat)); |
626 | |
627 | ConvertWidth = NewWidth; |
628 | ConvertHeight = NewHeight; |
629 | |
630 | free(ptr: pTexData); |
631 | pTexData = pNewTexData; |
632 | } |
633 | |
634 | if(Texture2DTo3D(pImageBuffer: pTexData, ImageWidth: ConvertWidth, ImageHeight: ConvertHeight, PixelSize, SplitCountWidth: 16, SplitCountHeight: 16, pTarget3DImageData: p3DImageData, Target3DImageWidth&: Image3DWidth, Target3DImageHeight&: Image3DHeight)) |
635 | { |
636 | glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GLStoreFormat, Image3DWidth, Image3DHeight, 256, 0, GLFormat, GL_UNSIGNED_BYTE, p3DImageData); |
637 | glGenerateMipmap(GL_TEXTURE_2D_ARRAY); |
638 | } |
639 | |
640 | free(ptr: p3DImageData); |
641 | } |
642 | } |
643 | |
644 | // This is the initial value for the wrap modes |
645 | m_vTextures[Slot].m_LastWrapMode = CCommandBuffer::WRAP_REPEAT; |
646 | |
647 | // calculate memory usage |
648 | m_vTextures[Slot].m_MemSize = (size_t)Width * Height * PixelSize; |
649 | while(Width > 2 && Height > 2) |
650 | { |
651 | Width >>= 1; |
652 | Height >>= 1; |
653 | m_vTextures[Slot].m_MemSize += (size_t)Width * Height * PixelSize; |
654 | } |
655 | m_pTextureMemoryUsage->store(i: m_pTextureMemoryUsage->load(m: std::memory_order_relaxed) + m_vTextures[Slot].m_MemSize, m: std::memory_order_relaxed); |
656 | |
657 | free(ptr: pTexData); |
658 | } |
659 | |
660 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand) |
661 | { |
662 | TextureCreate(Slot: pCommand->m_Slot, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RGBA, GL_RGBA, Flags: pCommand->m_Flags, pTexData: pCommand->m_pData); |
663 | } |
664 | |
665 | void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTexture_Update(const CCommandBuffer::SCommand_TextTexture_Update *pCommand) |
666 | { |
667 | TextureUpdate(Slot: pCommand->m_Slot, X: pCommand->m_X, Y: pCommand->m_Y, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, pTexData: pCommand->m_pData); |
668 | } |
669 | |
670 | void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Destroy(const CCommandBuffer::SCommand_TextTextures_Destroy *pCommand) |
671 | { |
672 | DestroyTexture(Slot: pCommand->m_Slot); |
673 | DestroyTexture(Slot: pCommand->m_SlotOutline); |
674 | } |
675 | |
676 | void CCommandProcessorFragment_OpenGL3_3::Cmd_TextTextures_Create(const CCommandBuffer::SCommand_TextTextures_Create *pCommand) |
677 | { |
678 | TextureCreate(Slot: pCommand->m_Slot, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, GL_RED, Flags: CCommandBuffer::TEXFLAG_NOMIPMAPS, pTexData: pCommand->m_pTextData); |
679 | TextureCreate(Slot: pCommand->m_SlotOutline, Width: pCommand->m_Width, Height: pCommand->m_Height, GL_RED, GL_RED, Flags: CCommandBuffer::TEXFLAG_NOMIPMAPS, pTexData: pCommand->m_pTextOutlineData); |
680 | } |
681 | |
682 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand) |
683 | { |
684 | // if clip is still active, force disable it for clearing, enable it again afterwards |
685 | bool ClipWasEnabled = m_LastClipEnable; |
686 | if(ClipWasEnabled) |
687 | { |
688 | glDisable(GL_SCISSOR_TEST); |
689 | } |
690 | if(pCommand->m_Color.r != m_ClearColor.r || pCommand->m_Color.g != m_ClearColor.g || pCommand->m_Color.b != m_ClearColor.b) |
691 | { |
692 | glClearColor(red: pCommand->m_Color.r, green: pCommand->m_Color.g, blue: pCommand->m_Color.b, alpha: 0.0f); |
693 | m_ClearColor = pCommand->m_Color; |
694 | } |
695 | glClear(GL_COLOR_BUFFER_BIT); |
696 | if(ClipWasEnabled) |
697 | { |
698 | glEnable(GL_SCISSOR_TEST); |
699 | } |
700 | } |
701 | |
702 | void CCommandProcessorFragment_OpenGL3_3::UploadStreamBufferData(unsigned int PrimitiveType, const void *pVertices, size_t VertSize, unsigned int PrimitiveCount, bool AsTex3D) |
703 | { |
704 | int Count = 0; |
705 | switch(PrimitiveType) |
706 | { |
707 | case CCommandBuffer::PRIMTYPE_LINES: |
708 | Count = PrimitiveCount * 2; |
709 | break; |
710 | case CCommandBuffer::PRIMTYPE_TRIANGLES: |
711 | Count = PrimitiveCount * 3; |
712 | break; |
713 | case CCommandBuffer::PRIMTYPE_QUADS: |
714 | Count = PrimitiveCount * 4; |
715 | break; |
716 | default: |
717 | return; |
718 | }; |
719 | |
720 | if(AsTex3D) |
721 | glBindBuffer(GL_ARRAY_BUFFER, m_PrimitiveDrawBufferIdTex3D); |
722 | else |
723 | glBindBuffer(GL_ARRAY_BUFFER, m_aPrimitiveDrawBufferId[m_LastStreamBuffer]); |
724 | |
725 | glBufferData(GL_ARRAY_BUFFER, VertSize * Count, pVertices, GL_STREAM_DRAW); |
726 | } |
727 | |
728 | void CCommandProcessorFragment_OpenGL3_3::Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand) |
729 | { |
730 | CGLSLTWProgram *pProgram = m_pPrimitiveProgram; |
731 | if(IsTexturedState(State: pCommand->m_State)) |
732 | pProgram = m_pPrimitiveProgramTextured; |
733 | UseProgram(pProgram); |
734 | SetState(State: pCommand->m_State, pProgram); |
735 | |
736 | UploadStreamBufferData(PrimitiveType: pCommand->m_PrimType, pVertices: pCommand->m_pVertices, VertSize: sizeof(CCommandBuffer::SVertex), PrimitiveCount: pCommand->m_PrimCount); |
737 | |
738 | glBindVertexArray(m_aPrimitiveDrawVertexId[m_LastStreamBuffer]); |
739 | |
740 | switch(pCommand->m_PrimType) |
741 | { |
742 | // We don't support GL_QUADS due to core profile |
743 | case CCommandBuffer::PRIMTYPE_LINES: |
744 | glDrawArrays(GL_LINES, first: 0, count: pCommand->m_PrimCount * 2); |
745 | break; |
746 | case CCommandBuffer::PRIMTYPE_TRIANGLES: |
747 | glDrawArrays(GL_TRIANGLES, first: 0, count: pCommand->m_PrimCount * 3); |
748 | break; |
749 | case CCommandBuffer::PRIMTYPE_QUADS: |
750 | if(m_aLastIndexBufferBound[m_LastStreamBuffer] != m_QuadDrawIndexBufferId) |
751 | { |
752 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
753 | m_aLastIndexBufferBound[m_LastStreamBuffer] = m_QuadDrawIndexBufferId; |
754 | } |
755 | glDrawElements(GL_TRIANGLES, count: pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, indices: 0); |
756 | break; |
757 | default: |
758 | dbg_msg(sys: "render" , fmt: "unknown primtype %d\n" , pCommand->m_PrimType); |
759 | }; |
760 | |
761 | m_LastStreamBuffer = (m_LastStreamBuffer + 1 >= MAX_STREAM_BUFFER_COUNT ? 0 : m_LastStreamBuffer + 1); |
762 | } |
763 | |
764 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTex3D(const CCommandBuffer::SCommand_RenderTex3D *pCommand) |
765 | { |
766 | CGLSLPrimitiveProgram *pProg = m_pPrimitive3DProgram; |
767 | if(IsTexturedState(State: pCommand->m_State)) |
768 | pProg = m_pPrimitive3DProgramTextured; |
769 | UseProgram(pProgram: pProg); |
770 | SetState(State: pCommand->m_State, pProgram: pProg, Use2DArrayTextures: true); |
771 | |
772 | UploadStreamBufferData(PrimitiveType: pCommand->m_PrimType, pVertices: pCommand->m_pVertices, VertSize: sizeof(CCommandBuffer::SVertexTex3DStream), PrimitiveCount: pCommand->m_PrimCount, AsTex3D: true); |
773 | |
774 | glBindVertexArray(m_PrimitiveDrawVertexIdTex3D); |
775 | |
776 | switch(pCommand->m_PrimType) |
777 | { |
778 | // We don't support GL_QUADS due to core profile |
779 | case CCommandBuffer::PRIMTYPE_LINES: |
780 | glDrawArrays(GL_LINES, first: 0, count: pCommand->m_PrimCount * 2); |
781 | break; |
782 | case CCommandBuffer::PRIMTYPE_QUADS: |
783 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
784 | glDrawElements(GL_TRIANGLES, count: pCommand->m_PrimCount * 6, GL_UNSIGNED_INT, indices: 0); |
785 | break; |
786 | default: |
787 | dbg_msg(sys: "render" , fmt: "unknown primtype %d\n" , pCommand->m_PrimType); |
788 | }; |
789 | } |
790 | |
791 | void CCommandProcessorFragment_OpenGL3_3::DestroyBufferContainer(int Index, bool DeleteBOs) |
792 | { |
793 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
794 | if(BufferContainer.m_VertArrayId != 0) |
795 | glDeleteVertexArrays(1, &BufferContainer.m_VertArrayId); |
796 | |
797 | // all buffer objects can deleted automatically, so the program doesn't need to deal with them (e.g. causing crashes because of driver bugs) |
798 | if(DeleteBOs) |
799 | { |
800 | int VertBufferId = BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex; |
801 | if(VertBufferId != -1) |
802 | { |
803 | glDeleteBuffers(1, &m_vBufferObjectIndices[VertBufferId]); |
804 | } |
805 | } |
806 | |
807 | BufferContainer.m_LastIndexBufferBound = 0; |
808 | BufferContainer.m_ContainerInfo.m_vAttributes.clear(); |
809 | } |
810 | |
811 | void CCommandProcessorFragment_OpenGL3_3::AppendIndices(unsigned int NewIndicesCount) |
812 | { |
813 | if(NewIndicesCount <= m_CurrentIndicesInBuffer) |
814 | return; |
815 | unsigned int AddCount = NewIndicesCount - m_CurrentIndicesInBuffer; |
816 | unsigned int *pIndices = new unsigned int[AddCount]; |
817 | int Primq = (m_CurrentIndicesInBuffer / 6) * 4; |
818 | for(unsigned int i = 0; i < AddCount; i += 6) |
819 | { |
820 | pIndices[i] = Primq; |
821 | pIndices[i + 1] = Primq + 1; |
822 | pIndices[i + 2] = Primq + 2; |
823 | pIndices[i + 3] = Primq; |
824 | pIndices[i + 4] = Primq + 2; |
825 | pIndices[i + 5] = Primq + 3; |
826 | Primq += 4; |
827 | } |
828 | |
829 | glBindBuffer(GL_COPY_READ_BUFFER, m_QuadDrawIndexBufferId); |
830 | GLuint NewIndexBufferId; |
831 | glGenBuffers(1, &NewIndexBufferId); |
832 | glBindBuffer(BUFFER_INIT_INDEX_TARGET, NewIndexBufferId); |
833 | GLsizeiptr size = sizeof(unsigned int); |
834 | glBufferData(BUFFER_INIT_INDEX_TARGET, (GLsizeiptr)NewIndicesCount * size, NULL, GL_STATIC_DRAW); |
835 | glCopyBufferSubData(GL_COPY_READ_BUFFER, BUFFER_INIT_INDEX_TARGET, 0, 0, (GLsizeiptr)m_CurrentIndicesInBuffer * size); |
836 | glBufferSubData(BUFFER_INIT_INDEX_TARGET, (GLsizeiptr)m_CurrentIndicesInBuffer * size, (GLsizeiptr)AddCount * size, pIndices); |
837 | glBindBuffer(BUFFER_INIT_INDEX_TARGET, 0); |
838 | glBindBuffer(GL_COPY_READ_BUFFER, 0); |
839 | |
840 | glDeleteBuffers(1, &m_QuadDrawIndexBufferId); |
841 | m_QuadDrawIndexBufferId = NewIndexBufferId; |
842 | |
843 | for(unsigned int &i : m_aLastIndexBufferBound) |
844 | i = 0; |
845 | for(auto &BufferContainer : m_vBufferContainers) |
846 | { |
847 | BufferContainer.m_LastIndexBufferBound = 0; |
848 | } |
849 | |
850 | m_CurrentIndicesInBuffer = NewIndicesCount; |
851 | delete[] pIndices; |
852 | } |
853 | |
854 | void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferObject(const CCommandBuffer::SCommand_CreateBufferObject *pCommand) |
855 | { |
856 | void *pUploadData = pCommand->m_pUploadData; |
857 | int Index = pCommand->m_BufferIndex; |
858 | // create necessary space |
859 | if((size_t)Index >= m_vBufferObjectIndices.size()) |
860 | { |
861 | for(int i = m_vBufferObjectIndices.size(); i < Index + 1; ++i) |
862 | { |
863 | m_vBufferObjectIndices.push_back(x: 0); |
864 | } |
865 | } |
866 | |
867 | GLuint VertBufferId = 0; |
868 | |
869 | glGenBuffers(1, &VertBufferId); |
870 | glBindBuffer(BUFFER_INIT_VERTEX_TARGET, VertBufferId); |
871 | glBufferData(BUFFER_INIT_VERTEX_TARGET, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW); |
872 | |
873 | m_vBufferObjectIndices[Index] = VertBufferId; |
874 | |
875 | if(pCommand->m_DeletePointer) |
876 | free(ptr: pUploadData); |
877 | } |
878 | |
879 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RecreateBufferObject(const CCommandBuffer::SCommand_RecreateBufferObject *pCommand) |
880 | { |
881 | void *pUploadData = pCommand->m_pUploadData; |
882 | int Index = pCommand->m_BufferIndex; |
883 | |
884 | glBindBuffer(BUFFER_INIT_VERTEX_TARGET, m_vBufferObjectIndices[Index]); |
885 | glBufferData(BUFFER_INIT_VERTEX_TARGET, (GLsizeiptr)(pCommand->m_DataSize), pUploadData, GL_STATIC_DRAW); |
886 | |
887 | if(pCommand->m_DeletePointer) |
888 | free(ptr: pUploadData); |
889 | } |
890 | |
891 | void CCommandProcessorFragment_OpenGL3_3::Cmd_UpdateBufferObject(const CCommandBuffer::SCommand_UpdateBufferObject *pCommand) |
892 | { |
893 | void *pUploadData = pCommand->m_pUploadData; |
894 | int Index = pCommand->m_BufferIndex; |
895 | |
896 | glBindBuffer(BUFFER_INIT_VERTEX_TARGET, m_vBufferObjectIndices[Index]); |
897 | glBufferSubData(BUFFER_INIT_VERTEX_TARGET, (GLintptr)(pCommand->m_pOffset), (GLsizeiptr)(pCommand->m_DataSize), pUploadData); |
898 | |
899 | if(pCommand->m_DeletePointer) |
900 | free(ptr: pUploadData); |
901 | } |
902 | |
903 | void CCommandProcessorFragment_OpenGL3_3::Cmd_CopyBufferObject(const CCommandBuffer::SCommand_CopyBufferObject *pCommand) |
904 | { |
905 | int WriteIndex = pCommand->m_WriteBufferIndex; |
906 | int ReadIndex = pCommand->m_ReadBufferIndex; |
907 | |
908 | glBindBuffer(GL_COPY_WRITE_BUFFER, m_vBufferObjectIndices[WriteIndex]); |
909 | glBindBuffer(GL_COPY_READ_BUFFER, m_vBufferObjectIndices[ReadIndex]); |
910 | glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, (GLsizeiptr)(pCommand->m_ReadOffset), (GLsizeiptr)(pCommand->m_WriteOffset), (GLsizeiptr)pCommand->m_CopySize); |
911 | } |
912 | |
913 | void CCommandProcessorFragment_OpenGL3_3::Cmd_DeleteBufferObject(const CCommandBuffer::SCommand_DeleteBufferObject *pCommand) |
914 | { |
915 | int Index = pCommand->m_BufferIndex; |
916 | |
917 | glDeleteBuffers(1, &m_vBufferObjectIndices[Index]); |
918 | } |
919 | |
920 | void CCommandProcessorFragment_OpenGL3_3::Cmd_CreateBufferContainer(const CCommandBuffer::SCommand_CreateBufferContainer *pCommand) |
921 | { |
922 | int Index = pCommand->m_BufferContainerIndex; |
923 | // create necessary space |
924 | if((size_t)Index >= m_vBufferContainers.size()) |
925 | { |
926 | for(int i = m_vBufferContainers.size(); i < Index + 1; ++i) |
927 | { |
928 | SBufferContainer Container; |
929 | Container.m_ContainerInfo.m_Stride = 0; |
930 | Container.m_ContainerInfo.m_VertBufferBindingIndex = -1; |
931 | m_vBufferContainers.push_back(x: Container); |
932 | } |
933 | } |
934 | |
935 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
936 | glGenVertexArrays(1, &BufferContainer.m_VertArrayId); |
937 | glBindVertexArray(BufferContainer.m_VertArrayId); |
938 | |
939 | BufferContainer.m_LastIndexBufferBound = 0; |
940 | |
941 | for(size_t i = 0; i < pCommand->m_AttrCount; ++i) |
942 | { |
943 | glEnableVertexAttribArray((GLuint)i); |
944 | |
945 | glBindBuffer(GL_ARRAY_BUFFER, m_vBufferObjectIndices[pCommand->m_VertBufferBindingIndex]); |
946 | |
947 | SBufferContainerInfo::SAttribute &Attr = pCommand->m_pAttributes[i]; |
948 | |
949 | if(Attr.m_FuncType == 0) |
950 | glVertexAttribPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, (GLboolean)Attr.m_Normalized, pCommand->m_Stride, Attr.m_pOffset); |
951 | else if(Attr.m_FuncType == 1) |
952 | glVertexAttribIPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, pCommand->m_Stride, Attr.m_pOffset); |
953 | |
954 | BufferContainer.m_ContainerInfo.m_vAttributes.push_back(x: Attr); |
955 | } |
956 | |
957 | BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex = pCommand->m_VertBufferBindingIndex; |
958 | BufferContainer.m_ContainerInfo.m_Stride = pCommand->m_Stride; |
959 | } |
960 | |
961 | void CCommandProcessorFragment_OpenGL3_3::Cmd_UpdateBufferContainer(const CCommandBuffer::SCommand_UpdateBufferContainer *pCommand) |
962 | { |
963 | SBufferContainer &BufferContainer = m_vBufferContainers[pCommand->m_BufferContainerIndex]; |
964 | |
965 | glBindVertexArray(BufferContainer.m_VertArrayId); |
966 | |
967 | // disable all old attributes |
968 | for(size_t i = 0; i < BufferContainer.m_ContainerInfo.m_vAttributes.size(); ++i) |
969 | { |
970 | glDisableVertexAttribArray((GLuint)i); |
971 | } |
972 | BufferContainer.m_ContainerInfo.m_vAttributes.clear(); |
973 | |
974 | for(size_t i = 0; i < pCommand->m_AttrCount; ++i) |
975 | { |
976 | glEnableVertexAttribArray((GLuint)i); |
977 | |
978 | glBindBuffer(GL_ARRAY_BUFFER, m_vBufferObjectIndices[pCommand->m_VertBufferBindingIndex]); |
979 | SBufferContainerInfo::SAttribute &Attr = pCommand->m_pAttributes[i]; |
980 | if(Attr.m_FuncType == 0) |
981 | glVertexAttribPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, Attr.m_Normalized, pCommand->m_Stride, Attr.m_pOffset); |
982 | else if(Attr.m_FuncType == 1) |
983 | glVertexAttribIPointer((GLuint)i, Attr.m_DataTypeCount, Attr.m_Type, pCommand->m_Stride, Attr.m_pOffset); |
984 | |
985 | BufferContainer.m_ContainerInfo.m_vAttributes.push_back(x: Attr); |
986 | } |
987 | |
988 | BufferContainer.m_ContainerInfo.m_VertBufferBindingIndex = pCommand->m_VertBufferBindingIndex; |
989 | BufferContainer.m_ContainerInfo.m_Stride = pCommand->m_Stride; |
990 | } |
991 | |
992 | void CCommandProcessorFragment_OpenGL3_3::Cmd_DeleteBufferContainer(const CCommandBuffer::SCommand_DeleteBufferContainer *pCommand) |
993 | { |
994 | DestroyBufferContainer(Index: pCommand->m_BufferContainerIndex, DeleteBOs: pCommand->m_DestroyAllBO); |
995 | } |
996 | |
997 | void CCommandProcessorFragment_OpenGL3_3::Cmd_IndicesRequiredNumNotify(const CCommandBuffer::SCommand_IndicesRequiredNumNotify *pCommand) |
998 | { |
999 | if(pCommand->m_RequiredIndicesNum > m_CurrentIndicesInBuffer) |
1000 | AppendIndices(NewIndicesCount: pCommand->m_RequiredIndicesNum); |
1001 | } |
1002 | |
1003 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuffer::SCommand_RenderBorderTile *pCommand) |
1004 | { |
1005 | int Index = pCommand->m_BufferContainerIndex; |
1006 | // if space not there return |
1007 | if((size_t)Index >= m_vBufferContainers.size()) |
1008 | return; |
1009 | |
1010 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1011 | if(BufferContainer.m_VertArrayId == 0) |
1012 | return; |
1013 | |
1014 | CGLSLTileProgram *pProgram = NULL; |
1015 | if(IsTexturedState(State: pCommand->m_State)) |
1016 | pProgram = m_pBorderTileProgramTextured; |
1017 | else |
1018 | pProgram = m_pBorderTileProgram; |
1019 | UseProgram(pProgram); |
1020 | |
1021 | SetState(State: pCommand->m_State, pProgram, Use2DArrayTextures: true); |
1022 | pProgram->SetUniformVec4(Loc: pProgram->m_LocColor, Count: 1, pValue: (float *)&pCommand->m_Color); |
1023 | |
1024 | pProgram->SetUniformVec2(Loc: pProgram->m_LocOffset, Count: 1, pValue: (float *)&pCommand->m_Offset); |
1025 | pProgram->SetUniformVec2(Loc: pProgram->m_LocScale, Count: 1, pValue: (float *)&pCommand->m_Scale); |
1026 | |
1027 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1028 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1029 | { |
1030 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1031 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1032 | } |
1033 | glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum * 6, GL_UNSIGNED_INT, indices: pCommand->m_pIndicesOffset); |
1034 | } |
1035 | |
1036 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderTileLayer(const CCommandBuffer::SCommand_RenderTileLayer *pCommand) |
1037 | { |
1038 | int Index = pCommand->m_BufferContainerIndex; |
1039 | // if space not there return |
1040 | if((size_t)Index >= m_vBufferContainers.size()) |
1041 | return; |
1042 | |
1043 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1044 | if(BufferContainer.m_VertArrayId == 0) |
1045 | return; |
1046 | |
1047 | if(pCommand->m_IndicesDrawNum == 0) |
1048 | { |
1049 | return; // nothing to draw |
1050 | } |
1051 | |
1052 | CGLSLTileProgram *pProgram = NULL; |
1053 | if(IsTexturedState(State: pCommand->m_State)) |
1054 | { |
1055 | pProgram = m_pTileProgramTextured; |
1056 | } |
1057 | else |
1058 | pProgram = m_pTileProgram; |
1059 | |
1060 | UseProgram(pProgram); |
1061 | |
1062 | SetState(State: pCommand->m_State, pProgram, Use2DArrayTextures: true); |
1063 | pProgram->SetUniformVec4(Loc: pProgram->m_LocColor, Count: 1, pValue: (float *)&pCommand->m_Color); |
1064 | |
1065 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1066 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1067 | { |
1068 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1069 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1070 | } |
1071 | for(int i = 0; i < pCommand->m_IndicesDrawNum; ++i) |
1072 | { |
1073 | glDrawElements(GL_TRIANGLES, count: pCommand->m_pDrawCount[i], GL_UNSIGNED_INT, indices: pCommand->m_pIndicesOffsets[i]); |
1074 | } |
1075 | } |
1076 | |
1077 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadLayer(const CCommandBuffer::SCommand_RenderQuadLayer *pCommand) |
1078 | { |
1079 | int Index = pCommand->m_BufferContainerIndex; |
1080 | // if space not there return |
1081 | if((size_t)Index >= m_vBufferContainers.size()) |
1082 | return; |
1083 | |
1084 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1085 | if(BufferContainer.m_VertArrayId == 0) |
1086 | return; |
1087 | |
1088 | if(pCommand->m_QuadNum == 0) |
1089 | { |
1090 | return; // nothing to draw |
1091 | } |
1092 | |
1093 | CGLSLQuadProgram *pProgram = NULL; |
1094 | if(IsTexturedState(State: pCommand->m_State)) |
1095 | { |
1096 | pProgram = m_pQuadProgramTextured; |
1097 | } |
1098 | else |
1099 | pProgram = m_pQuadProgram; |
1100 | |
1101 | UseProgram(pProgram); |
1102 | SetState(State: pCommand->m_State, pProgram); |
1103 | |
1104 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1105 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1106 | { |
1107 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1108 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1109 | } |
1110 | |
1111 | int QuadsLeft = pCommand->m_QuadNum; |
1112 | size_t QuadOffset = 0; |
1113 | // the extra offset is not related to the information from the command, but an actual offset in the buffer |
1114 | size_t = pCommand->m_QuadOffset; |
1115 | |
1116 | vec4 aColors[ms_MaxQuadsPossible]; |
1117 | vec2 aOffsets[ms_MaxQuadsPossible]; |
1118 | float aRotations[ms_MaxQuadsPossible]; |
1119 | |
1120 | while(QuadsLeft > 0) |
1121 | { |
1122 | int ActualQuadCount = minimum<int>(a: QuadsLeft, b: m_MaxQuadsAtOnce); |
1123 | |
1124 | for(size_t i = 0; i < (size_t)ActualQuadCount; ++i) |
1125 | { |
1126 | aColors[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Color; |
1127 | aOffsets[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Offsets; |
1128 | aRotations[i] = pCommand->m_pQuadInfo[i + QuadOffset].m_Rotation; |
1129 | } |
1130 | |
1131 | pProgram->SetUniformVec4(Loc: pProgram->m_LocColors, Count: ActualQuadCount, pValue: (float *)aColors); |
1132 | pProgram->SetUniformVec2(Loc: pProgram->m_LocOffsets, Count: ActualQuadCount, pValue: (float *)aOffsets); |
1133 | pProgram->SetUniform(Loc: pProgram->m_LocRotations, Count: ActualQuadCount, pValues: (float *)aRotations); |
1134 | pProgram->SetUniform(Loc: pProgram->m_LocQuadOffset, Value: (int)(QuadOffset + QuadOffsetExtra)); |
1135 | glDrawElements(GL_TRIANGLES, count: ActualQuadCount * 6, GL_UNSIGNED_INT, indices: (void *)((QuadOffset + QuadOffsetExtra) * 6 * sizeof(unsigned int))); |
1136 | |
1137 | QuadsLeft -= ActualQuadCount; |
1138 | QuadOffset += (size_t)ActualQuadCount; |
1139 | } |
1140 | } |
1141 | |
1142 | void CCommandProcessorFragment_OpenGL3_3::RenderText(const CCommandBuffer::SState &State, int DrawNum, int TextTextureIndex, int TextOutlineTextureIndex, int TextureSize, const ColorRGBA &TextColor, const ColorRGBA &TextOutlineColor) |
1143 | { |
1144 | if(DrawNum == 0) |
1145 | { |
1146 | return; // nothing to draw |
1147 | } |
1148 | |
1149 | UseProgram(pProgram: m_pTextProgram); |
1150 | |
1151 | int SlotText = 0; |
1152 | int SlotTextOutline = 1; |
1153 | glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[TextTextureIndex].m_Tex); |
1154 | glBindSampler(SlotText, m_vTextures[TextTextureIndex].m_Sampler); |
1155 | glActiveTexture(GL_TEXTURE1); |
1156 | glBindTexture(GL_TEXTURE_2D, texture: m_vTextures[TextOutlineTextureIndex].m_Tex); |
1157 | glBindSampler(SlotTextOutline, m_vTextures[TextOutlineTextureIndex].m_Sampler); |
1158 | glActiveTexture(GL_TEXTURE0); |
1159 | |
1160 | if(m_pTextProgram->m_LastTextSampler != SlotText) |
1161 | { |
1162 | m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextSampler, Value: SlotText); |
1163 | m_pTextProgram->m_LastTextSampler = SlotText; |
1164 | } |
1165 | |
1166 | if(m_pTextProgram->m_LastTextOutlineSampler != SlotTextOutline) |
1167 | { |
1168 | m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextOutlineSampler, Value: SlotTextOutline); |
1169 | m_pTextProgram->m_LastTextOutlineSampler = SlotTextOutline; |
1170 | } |
1171 | |
1172 | SetState(State, pProgram: m_pTextProgram); |
1173 | |
1174 | if(m_pTextProgram->m_LastTextureSize != TextureSize) |
1175 | { |
1176 | m_pTextProgram->SetUniform(Loc: m_pTextProgram->m_LocTextureSize, Value: (float)TextureSize); |
1177 | m_pTextProgram->m_LastTextureSize = TextureSize; |
1178 | } |
1179 | |
1180 | if(m_pTextProgram->m_LastOutlineColor != TextOutlineColor) |
1181 | { |
1182 | m_pTextProgram->SetUniformVec4(Loc: m_pTextProgram->m_LocOutlineColor, Count: 1, pValue: (float *)&TextOutlineColor); |
1183 | m_pTextProgram->m_LastOutlineColor = TextOutlineColor; |
1184 | } |
1185 | |
1186 | if(m_pTextProgram->m_LastColor != TextColor) |
1187 | { |
1188 | m_pTextProgram->SetUniformVec4(Loc: m_pTextProgram->m_LocColor, Count: 1, pValue: (float *)&TextColor); |
1189 | m_pTextProgram->m_LastColor = TextColor; |
1190 | } |
1191 | |
1192 | glDrawElements(GL_TRIANGLES, count: DrawNum, GL_UNSIGNED_INT, indices: (void *)(0)); |
1193 | } |
1194 | |
1195 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderText(const CCommandBuffer::SCommand_RenderText *pCommand) |
1196 | { |
1197 | int Index = pCommand->m_BufferContainerIndex; |
1198 | // if space not there return |
1199 | if((size_t)Index >= m_vBufferContainers.size()) |
1200 | return; |
1201 | |
1202 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1203 | if(BufferContainer.m_VertArrayId == 0) |
1204 | return; |
1205 | |
1206 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1207 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1208 | { |
1209 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1210 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1211 | } |
1212 | |
1213 | RenderText(State: pCommand->m_State, DrawNum: pCommand->m_DrawNum, TextTextureIndex: pCommand->m_TextTextureIndex, TextOutlineTextureIndex: pCommand->m_TextOutlineTextureIndex, TextureSize: pCommand->m_TextureSize, TextColor: pCommand->m_TextColor, TextOutlineColor: pCommand->m_TextOutlineColor); |
1214 | } |
1215 | |
1216 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainer(const CCommandBuffer::SCommand_RenderQuadContainer *pCommand) |
1217 | { |
1218 | if(pCommand->m_DrawNum == 0) |
1219 | { |
1220 | return; // nothing to draw |
1221 | } |
1222 | |
1223 | int Index = pCommand->m_BufferContainerIndex; |
1224 | // if space not there return |
1225 | if((size_t)Index >= m_vBufferContainers.size()) |
1226 | return; |
1227 | |
1228 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1229 | if(BufferContainer.m_VertArrayId == 0) |
1230 | return; |
1231 | |
1232 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1233 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1234 | { |
1235 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1236 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1237 | } |
1238 | |
1239 | CGLSLTWProgram *pProgram = m_pPrimitiveProgram; |
1240 | if(IsTexturedState(State: pCommand->m_State)) |
1241 | pProgram = m_pPrimitiveProgramTextured; |
1242 | UseProgram(pProgram); |
1243 | SetState(State: pCommand->m_State, pProgram); |
1244 | |
1245 | glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum, GL_UNSIGNED_INT, indices: pCommand->m_pOffset); |
1246 | } |
1247 | |
1248 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerEx(const CCommandBuffer::SCommand_RenderQuadContainerEx *pCommand) |
1249 | { |
1250 | if(pCommand->m_DrawNum == 0) |
1251 | { |
1252 | return; // nothing to draw |
1253 | } |
1254 | |
1255 | int Index = pCommand->m_BufferContainerIndex; |
1256 | // if space not there return |
1257 | if((size_t)Index >= m_vBufferContainers.size()) |
1258 | return; |
1259 | |
1260 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1261 | if(BufferContainer.m_VertArrayId == 0) |
1262 | return; |
1263 | |
1264 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1265 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1266 | { |
1267 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1268 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1269 | } |
1270 | |
1271 | CGLSLPrimitiveExProgram *pProgram = m_pPrimitiveExProgramRotationless; |
1272 | if(IsTexturedState(State: pCommand->m_State)) |
1273 | { |
1274 | if(pCommand->m_Rotation != 0.0f) |
1275 | pProgram = m_pPrimitiveExProgramTextured; |
1276 | else |
1277 | pProgram = m_pPrimitiveExProgramTexturedRotationless; |
1278 | } |
1279 | else |
1280 | { |
1281 | if(pCommand->m_Rotation != 0.0f) |
1282 | pProgram = m_pPrimitiveExProgram; |
1283 | } |
1284 | |
1285 | UseProgram(pProgram); |
1286 | SetState(State: pCommand->m_State, pProgram); |
1287 | |
1288 | if(pCommand->m_Rotation != 0.0f && pProgram->m_LastCenter != pCommand->m_Center) |
1289 | { |
1290 | pProgram->SetUniformVec2(Loc: pProgram->m_LocCenter, Count: 1, pValue: (float *)&pCommand->m_Center); |
1291 | pProgram->m_LastCenter = pCommand->m_Center; |
1292 | } |
1293 | |
1294 | if(pProgram->m_LastRotation != pCommand->m_Rotation) |
1295 | { |
1296 | pProgram->SetUniform(Loc: pProgram->m_LocRotation, Value: pCommand->m_Rotation); |
1297 | pProgram->m_LastRotation = pCommand->m_Rotation; |
1298 | } |
1299 | |
1300 | if(pProgram->m_LastVerticesColor != pCommand->m_VertexColor) |
1301 | { |
1302 | pProgram->SetUniformVec4(Loc: pProgram->m_LocVertciesColor, Count: 1, pValue: (float *)&pCommand->m_VertexColor); |
1303 | pProgram->m_LastVerticesColor = pCommand->m_VertexColor; |
1304 | } |
1305 | |
1306 | glDrawElements(GL_TRIANGLES, count: pCommand->m_DrawNum, GL_UNSIGNED_INT, indices: pCommand->m_pOffset); |
1307 | } |
1308 | |
1309 | void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderQuadContainerAsSpriteMultiple(const CCommandBuffer::SCommand_RenderQuadContainerAsSpriteMultiple *pCommand) |
1310 | { |
1311 | if(pCommand->m_DrawNum == 0 || pCommand->m_DrawCount == 0) |
1312 | { |
1313 | return; // nothing to draw |
1314 | } |
1315 | |
1316 | int Index = pCommand->m_BufferContainerIndex; |
1317 | // if space not there return |
1318 | if((size_t)Index >= m_vBufferContainers.size()) |
1319 | return; |
1320 | |
1321 | SBufferContainer &BufferContainer = m_vBufferContainers[Index]; |
1322 | if(BufferContainer.m_VertArrayId == 0) |
1323 | return; |
1324 | |
1325 | glBindVertexArray(BufferContainer.m_VertArrayId); |
1326 | if(BufferContainer.m_LastIndexBufferBound != m_QuadDrawIndexBufferId) |
1327 | { |
1328 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_QuadDrawIndexBufferId); |
1329 | BufferContainer.m_LastIndexBufferBound = m_QuadDrawIndexBufferId; |
1330 | } |
1331 | |
1332 | UseProgram(pProgram: m_pSpriteProgramMultiple); |
1333 | SetState(State: pCommand->m_State, pProgram: m_pSpriteProgramMultiple); |
1334 | |
1335 | if(m_pSpriteProgramMultiple->m_LastCenter != pCommand->m_Center) |
1336 | { |
1337 | m_pSpriteProgramMultiple->SetUniformVec2(Loc: m_pSpriteProgramMultiple->m_LocCenter, Count: 1, pValue: (float *)&pCommand->m_Center); |
1338 | m_pSpriteProgramMultiple->m_LastCenter = pCommand->m_Center; |
1339 | } |
1340 | |
1341 | if(m_pSpriteProgramMultiple->m_LastVerticesColor != pCommand->m_VertexColor) |
1342 | { |
1343 | m_pSpriteProgramMultiple->SetUniformVec4(Loc: m_pSpriteProgramMultiple->m_LocVertciesColor, Count: 1, pValue: (float *)&pCommand->m_VertexColor); |
1344 | m_pSpriteProgramMultiple->m_LastVerticesColor = pCommand->m_VertexColor; |
1345 | } |
1346 | |
1347 | int DrawCount = pCommand->m_DrawCount; |
1348 | size_t RenderOffset = 0; |
1349 | |
1350 | // 4 for the center (always use vec4) and 16 for the matrix(just to be sure), 4 for the sampler and vertex color |
1351 | const int RSPCount = 256 - 4 - 16 - 8; |
1352 | |
1353 | while(DrawCount > 0) |
1354 | { |
1355 | int UniformCount = (DrawCount > RSPCount ? RSPCount : DrawCount); |
1356 | |
1357 | m_pSpriteProgramMultiple->SetUniformVec4(Loc: m_pSpriteProgramMultiple->m_LocRSP, Count: UniformCount, pValue: (float *)(pCommand->m_pRenderInfo + RenderOffset)); |
1358 | |
1359 | glDrawElementsInstanced(GL_TRIANGLES, pCommand->m_DrawNum, GL_UNSIGNED_INT, pCommand->m_pOffset, UniformCount); |
1360 | |
1361 | RenderOffset += RSPCount; |
1362 | DrawCount -= RSPCount; |
1363 | } |
1364 | } |
1365 | |
1366 | #endif |
1367 | |