OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4DrawGL.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
5  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
6  *
7  * Distributed under the terms of the ISC license; see accompanying file
8  * "COPYING" for details.
9  *
10  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11  * See accompanying file "TRADEMARK" for details.
12  *
13  * To redistribute this file separately, substitute the full license texts
14  * for the above references.
15  */
16 
17 /* OpenGL implementation of NewGfx */
18 
19 #include "C4Include.h"
21 #include "graphics/C4DrawGL.h"
22 
23 #include "graphics/C4Surface.h"
24 #include "platform/C4Window.h"
26 #include "lib/C4Rect.h"
27 #include "config/C4Config.h"
28 #include "game/C4Application.h"
29 #include "lib/StdColors.h"
30 
31 #ifndef USE_CONSOLE
32 
33 // MSVC doesn't define M_PI in math.h unless requested
34 #ifdef _MSC_VER
35 #define _USE_MATH_DEFINES
36 #endif /* _MSC_VER */
37 
38 #include <stdio.h>
39 #include <math.h>
40 
41 namespace
42 {
43  const char *MsgSourceToStr(GLenum source)
44  {
45  switch (source)
46  {
47  case GL_DEBUG_SOURCE_API_ARB: return "API";
48  case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB: return "window system";
49  case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB: return "shader compiler";
50  case GL_DEBUG_SOURCE_THIRD_PARTY_ARB: return "third party";
51  case GL_DEBUG_SOURCE_APPLICATION_ARB: return "application";
52  case GL_DEBUG_SOURCE_OTHER_ARB: return "other";
53  default: return "<unknown>";
54  }
55  }
56 
57  const char *MsgTypeToStr(GLenum type)
58  {
59  switch (type)
60  {
61  case GL_DEBUG_TYPE_ERROR_ARB: return "error";
62  case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: return "deprecation warning";
63  case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: return "undefined behavior warning";
64  case GL_DEBUG_TYPE_PORTABILITY_ARB: return "portability warning";
65  case GL_DEBUG_TYPE_PERFORMANCE_ARB: return "performance warning";
66  case GL_DEBUG_TYPE_OTHER_ARB: return "other message";
67  default: return "unknown message";
68  }
69  }
70 
71  const char *MsgSeverityToStr(GLenum severity)
72  {
73  switch (severity)
74  {
75  case GL_DEBUG_SEVERITY_HIGH_ARB: return "high";
76  case GL_DEBUG_SEVERITY_MEDIUM_ARB: return "medium";
77  case GL_DEBUG_SEVERITY_LOW_ARB: return "low";
78 #ifdef GL_DEBUG_SEVERITY_NOTIFICATION
79  case GL_DEBUG_SEVERITY_NOTIFICATION: return "notification";
80 #endif
81  default: return "<unknown>";
82  }
83  }
84 
85 #ifdef GLDEBUGPROCARB_USERPARAM_IS_CONST
86 #define USERPARAM_CONST const
87 #else
88 #define USERPARAM_CONST
89 #endif
90 
91  void GLAPIENTRY OpenGLDebugProc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const char* message, USERPARAM_CONST void* userParam)
92  {
93  const char *msg_source = MsgSourceToStr(source);
94  const char *msg_type = MsgTypeToStr(type);
95  const char *msg_severity = MsgSeverityToStr(severity);
96 
97  LogSilentF(" gl: %s severity %s %s: %s", msg_severity, msg_source, msg_type, message);
98 #ifdef USE_WIN32_WINDOWS
99  if (IsDebuggerPresent() && severity == GL_DEBUG_SEVERITY_HIGH_ARB)
101 #endif
102  }
103 }
104 
105 #undef USERPARAM_CONST
106 
108  pMainCtx(0), CurrentVBO(0), NextVAOID(VAOIDs.end())
109 {
110  GenericVBOs[0] = 0;
111  Default();
112  // global ptr
113  pGL = this;
114  lines_tex = 0;
115 }
116 
118 {
119  Clear();
120  pGL=nullptr;
121 }
122 
124 {
126  // cannot unlock TexMgr here or we can't preserve textures across GL reinitialization as required when changing multisampling
129  RenderTarget = nullptr;
130  // Clear all shaders
147  // clear context
148  if (pCurrCtx) pCurrCtx->Deselect();
149  pMainCtx=0;
150  C4Draw::Clear();
151 }
152 
154 {
155  if (!pCurrCtx) return;
156  glClearColor((float)GetRedValue(dwClr)/255.0f, (float)GetGreenValue(dwClr)/255.0f, (float)GetBlueValue(dwClr)/255.0f, 0.0f);
157  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
158 }
159 
161 {
162  // no render target? do nothing
163  if (!RenderTarget || !Active) return true;
164  // negative/zero?
165  C4Rect clipRect = GetClipRect();
166  if (clipRect.Wdt<=0 || clipRect.Hgt<=0)
167  {
168  ClipAll=true;
169  return true;
170  }
171  ClipAll=false;
172  // set it
173  glViewport(clipRect.x, RenderTarget->Hgt-clipRect.y-clipRect.Hgt, clipRect.Wdt, clipRect.Hgt);
174  ProjectionMatrix = StdProjectionMatrix::Orthographic(clipRect.x, clipRect.x + clipRect.Wdt, clipRect.y + clipRect.Hgt, clipRect.y);
175  return true;
176 }
177 
179 {
180  // call from gfx thread only!
181  if (!pApp || !pApp->AssertMainThread()) return false;
182  // not ready?
183  if (!Active)
184  return false;
185  // target?
186  if (!sfcToSurface) return false;
187  // target locked?
188  if (sfcToSurface->Locked) return false;
189  // target is already set as render target?
190  if (sfcToSurface != RenderTarget)
191  {
192  // target is a render-target?
193  if (!sfcToSurface->IsRenderTarget()) return false;
194  // context
195  if (sfcToSurface->pCtx && sfcToSurface->pCtx != pCurrCtx)
196  if (!sfcToSurface->pCtx->Select()) return false;
197  // set target
198  RenderTarget=sfcToSurface;
199  // new target has different size; needs other clipping rect
200  UpdateClipper();
201  }
202  // done
203  return true;
204 }
205 
206 
207 bool CStdGL::PrepareSpriteShader(C4Shader& shader, const char* name, int ssc, C4GroupSet* pGroups, const char* const* additionalDefines, const char* const* additionalSlices)
208 {
209  const char* uniformNames[C4SSU_Count + 1];
210  uniformNames[C4SSU_ProjectionMatrix] = "projectionMatrix";
211  uniformNames[C4SSU_ModelViewMatrix] = "modelviewMatrix";
212  uniformNames[C4SSU_NormalMatrix] = "normalMatrix";
213  uniformNames[C4SSU_ClrMod] = "clrMod";
214  uniformNames[C4SSU_Gamma] = "gamma";
215  uniformNames[C4SSU_BaseTex] = "baseTex";
216  uniformNames[C4SSU_OverlayTex] = "overlayTex";
217  uniformNames[C4SSU_OverlayClr] = "overlayClr";
218  uniformNames[C4SSU_LightTex] = "lightTex";
219  uniformNames[C4SSU_LightTransform] = "lightTransform";
220  uniformNames[C4SSU_NormalTex] = "normalTex";
221  uniformNames[C4SSU_AmbientTex] = "ambientTex";
222  uniformNames[C4SSU_AmbientTransform] = "ambientTransform";
223  uniformNames[C4SSU_AmbientBrightness] = "ambientBrightness";
224  uniformNames[C4SSU_MaterialAmbient] = "materialAmbient"; // unused
225  uniformNames[C4SSU_MaterialDiffuse] = "materialDiffuse"; // unused
226  uniformNames[C4SSU_MaterialSpecular] = "materialSpecular"; // unused
227  uniformNames[C4SSU_MaterialEmission] = "materialEmission"; // unused
228  uniformNames[C4SSU_MaterialShininess] = "materialShininess"; // unused
229  uniformNames[C4SSU_Bones] = "bones"; // unused
230  uniformNames[C4SSU_CullMode] = "cullMode"; // unused
231  uniformNames[C4SSU_FrameCounter] = "frameCounter";
232  uniformNames[C4SSU_Count] = nullptr;
233 
234  const char* attributeNames[C4SSA_Count + 1];
235  attributeNames[C4SSA_Position] = "oc_Position";
236  attributeNames[C4SSA_Normal] = "oc_Normal"; // unused
237  attributeNames[C4SSA_TexCoord] = "oc_TexCoord"; // only used if C4SSC_Base is set
238  attributeNames[C4SSA_Color] = "oc_Color";
239  attributeNames[C4SSA_BoneIndices0] = "oc_BoneIndices0"; // unused
240  attributeNames[C4SSA_BoneIndices1] = "oc_BoneIndices1"; // unused
241  attributeNames[C4SSA_BoneWeights0] = "oc_BoneWeights0"; // unused
242  attributeNames[C4SSA_BoneWeights1] = "oc_BoneWeights1"; // unused
243  attributeNames[C4SSA_Count] = nullptr;
244 
245  // Clear previous content
246  shader.Clear();
247  shader.ClearSlices();
248 
249  // Start with #defines
250  shader.AddDefine("OPENCLONK");
251  shader.AddDefine("OC_SPRITE");
252  if (ssc & C4SSC_MOD2) shader.AddDefine("OC_CLRMOD_MOD2");
253  if (ssc & C4SSC_NORMAL) shader.AddDefine("OC_WITH_NORMALMAP");
254  if (ssc & C4SSC_LIGHT) shader.AddDefine("OC_DYNAMIC_LIGHT");
255  if (ssc & C4SSC_BASE) shader.AddDefine("OC_HAVE_BASE");
256  if (ssc & C4SSC_OVERLAY) shader.AddDefine("OC_HAVE_OVERLAY");
257 
258  if (additionalDefines)
259  for (const char* const* define = additionalDefines; *define != nullptr; ++define)
260  shader.AddDefine(*define);
261 
262  // Then load slices for fragment and vertex shader
263  shader.LoadVertexSlices(pGroups, "SpriteVertexShader.glsl");
264  shader.LoadFragmentSlices(pGroups, "CommonShader.glsl");
265  shader.LoadFragmentSlices(pGroups, "ObjectShader.glsl");
266 
267  // Categories for script shaders.
268  shader.SetScriptCategories({"Common", "Object"});
269 
270  if (additionalSlices)
271  for (const char* const* slice = additionalSlices; *slice != nullptr; ++slice)
272  shader.LoadFragmentSlices(pGroups, *slice);
273 
274  if (!shader.Init(name, uniformNames, attributeNames))
275  {
276  shader.ClearSlices();
277  return false;
278  }
279 
280  return true;
281 }
282 
283 void CStdGL::ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char * label)
284 {
285 #ifdef GL_KHR_debug
286  if (glObjectLabel)
287  glObjectLabel(identifier, name, length, label);
288 #endif
289 }
290 
292 {
293  // safety
294  if (!pWindow) return nullptr;
295 
296  // create it
297  CStdGLCtx *pCtx;
298 #ifdef WITH_QT_EDITOR
299  auto app = dynamic_cast<C4Application*>(pApp);
300  if (app->isEditor)
301  pCtx = new CStdGLCtxQt();
302  else
303 #endif
304  pCtx = new CStdGLCtx();
305  bool first_ctx = !pMainCtx;
306  if (first_ctx)
307  {
308  pMainCtx = pCtx;
309  LogF(" gl: Create first %scontext...", Config.Graphics.DebugOpenGL ? "debug " : "");
310  }
311  bool success = pCtx->Init(pWindow, pApp);
312  if (Config.Graphics.DebugOpenGL && glDebugMessageCallbackARB)
313  {
314  if (first_ctx) Log(" gl: Setting OpenGLDebugProc callback");
315  glDebugMessageCallbackARB(&OpenGLDebugProc, nullptr);
316  glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
317 #ifdef GL_KHR_debug
318  if (GLEW_KHR_debug)
319  glEnable(GL_DEBUG_OUTPUT);
320 #endif
321  }
322  // First context: Log some information about hardware/drivers
323  // Must log after context creation to get valid results
324  if (first_ctx)
325  {
326  const char *gl_vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
327  const char *gl_renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
328  const char *gl_version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
329  LogF("GL %s on %s (%s)", gl_version ? gl_version : "", gl_renderer ? gl_renderer : "", gl_vendor ? gl_vendor : "");
330 
332  {
333  // Dump extension list
334  if (glGetStringi)
335  {
336  GLint gl_extension_count = 0;
337  glGetIntegerv(GL_NUM_EXTENSIONS, &gl_extension_count);
338  if (gl_extension_count == 0)
339  {
340  LogSilentF("No available extensions.");
341  }
342  else
343  {
344  LogSilentF("%d available extensions:", gl_extension_count);
345  for (GLint i = 0; i < gl_extension_count; ++i)
346  {
347  const char *gl_extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
348  LogSilentF(" %4d: %s", i, gl_extension);
349  }
350  }
351  }
352  else
353  {
354  const char *gl_extensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
355  LogSilentF("GLExt: %s", gl_extensions ? gl_extensions : "");
356  }
357  }
358  }
359  if (!success)
360  {
361  delete pCtx; Error(" gl: Error creating secondary context!"); return nullptr;
362  }
363  // creation selected the new context - switch back to previous context
364  RenderTarget = nullptr;
365  pCurrCtx = nullptr;
366  // done
367  return pCtx;
368 }
369 
370 void CStdGL::SetupMultiBlt(C4ShaderCall& call, const C4BltTransform* pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix* out_modelview)
371 {
372  // Initialize multi blit shader.
373  int iAdditive = dwBlitMode & C4GFXBLIT_ADDITIVE;
374  glBlendFunc(GL_SRC_ALPHA, iAdditive ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA);
375 
376  call.Start();
377 
378  // Upload uniforms
379  const DWORD dwModClr = BlitModulated ? BlitModulateClr : 0xffffffff;
380  const float fMod[4] = {
381  ((dwModClr >> 16) & 0xff) / 255.0f,
382  ((dwModClr >> 8) & 0xff) / 255.0f,
383  ((dwModClr ) & 0xff) / 255.0f,
384  ((dwModClr >> 24) & 0xff) / 255.0f
385  };
386 
387  call.SetUniform4fv(C4SSU_ClrMod, 1, fMod);
389 
390  if(baseTex != 0)
391  {
393  glBindTexture(GL_TEXTURE_2D, baseTex);
394  }
395 
396  if(overlayTex != 0)
397  {
399  glBindTexture(GL_TEXTURE_2D, overlayTex);
400 
401  const float fOverlayModClr[4] = {
402  ((dwOverlayModClr >> 16) & 0xff) / 255.0f,
403  ((dwOverlayModClr >> 8) & 0xff) / 255.0f,
404  ((dwOverlayModClr ) & 0xff) / 255.0f,
405  ((dwOverlayModClr >> 24) & 0xff) / 255.0f
406  };
407 
408  call.SetUniform4fv(C4SSU_OverlayClr, 1, fOverlayModClr);
409  }
410 
411  if(pFoW != nullptr && normalTex != 0)
412  {
414  glBindTexture(GL_TEXTURE_2D, normalTex);
415  }
416 
417  if(pFoW != nullptr)
418  {
419  const C4Rect OutRect = GetOutRect();
420  const C4Rect ClipRect = GetClipRect();
421  const FLOAT_RECT vpRect = pFoW->getViewportRegion();
422 
423  // Dynamic Light
425  glBindTexture(GL_TEXTURE_2D, pFoW->getSurfaceName());
426 
427  float lightTransform[6];
428  pFoW->GetFragTransform(ClipRect, OutRect, lightTransform);
429  call.SetUniformMatrix2x3fv(C4SSU_LightTransform, 1, lightTransform);
430 
431  // Ambient Light
433  glBindTexture(GL_TEXTURE_2D, pFoW->getFoW()->Ambient.Tex);
435 
436  float ambientTransform[6];
437  pFoW->getFoW()->Ambient.GetFragTransform(vpRect, ClipRect, OutRect, ambientTransform);
438  call.SetUniformMatrix2x3fv(C4SSU_AmbientTransform, 1, ambientTransform);
439  }
440 
441  call.SetUniform1f(C4SSU_CullMode, 0.0f);
442 
443  // The primary reason we use a 4x4 matrix for the modelview matrix is that
444  // that the C4BltTransform pTransform parameter can have projection components
445  // (see SetObjDrawTransform2). Still, for sprites the situation is a bit
446  // unsatisfactory because there's no distinction between modelview and projection
447  // components in the BltTransform. Object rotation is part of the BltTransform
448  // for sprites, which should be part of the modelview matrix, so that lighting
449  // is correct for rotated sprites. This is much more common than projection
450  // components in the BltTransform, and therefore we turn the BltTransform into
451  // the modelview matrix and not the projection matrix.
452  StdProjectionMatrix default_modelview = StdProjectionMatrix::Identity();
453  StdProjectionMatrix& modelview = out_modelview ? *out_modelview : default_modelview;
454 
455  // Apply zoom and transform
456  Translate(modelview, ZoomX, ZoomY, 0.0f);
457  // Scale Z as well so that we don't distort normals.
458  Scale(modelview, Zoom, Zoom, Zoom);
459  Translate(modelview, -ZoomX, -ZoomY, 0.0f);
460 
461  if(pTransform)
462  {
463  float sz = 1.0f;
464  if (pFoW != nullptr && normalTex != 0)
465  {
466  // Decompose scale factors and scale Z accordingly to X and Y, again to avoid distorting normals
467  // We could instead work around this by using the projection matrix, but then for object rotations (SetR)
468  // the normals would not be correct.
469  const float sx = sqrt(pTransform->mat[0]*pTransform->mat[0] + pTransform->mat[1]*pTransform->mat[1]);
470  const float sy = sqrt(pTransform->mat[3]*pTransform->mat[3] + pTransform->mat[4]*pTransform->mat[4]);
471  sz = sqrt(sx * sy);
472  }
473 
474  // Multiply modelview matrix with transform
475  StdProjectionMatrix transform;
476  transform(0, 0) = pTransform->mat[0];
477  transform(0, 1) = pTransform->mat[1];
478  transform(0, 2) = 0.0f;
479  transform(0, 3) = pTransform->mat[2];
480  transform(1, 0) = pTransform->mat[3];
481  transform(1, 1) = pTransform->mat[4];
482  transform(1, 2) = 0.0f;
483  transform(1, 3) = pTransform->mat[5];
484  transform(2, 0) = 0.0f;
485  transform(2, 1) = 0.0f;
486  transform(2, 2) = sz;
487  transform(2, 3) = 0.0f;
488  transform(3, 0) = pTransform->mat[6];
489  transform(3, 1) = pTransform->mat[7];
490  transform(3, 2) = 0.0f;
491  transform(3, 3) = pTransform->mat[8];
492  modelview *= transform;
493  }
494 
497 
498  if (pFoW != nullptr && normalTex != 0)
499  call.SetUniformMatrix3x3Transpose(C4SSU_NormalMatrix, StdMeshMatrix::Inverse(StdProjectionMatrix::Upper3x4(modelview)));
500 
501  scriptUniform.Apply(call);
502 }
503 
504 void CStdGL::PerformMultiPix(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, C4ShaderCall* shader_call)
505 {
506  // Draw on pixel center:
507  StdProjectionMatrix transform = StdProjectionMatrix::Translate(0.5f, 0.5f, 0.0f);
508 
509  // This is a workaround. Instead of submitting the whole vertex array to the GL, we do it
510  // in batches of 256 vertices. The intel graphics driver on Linux crashes with
511  // significantly larger arrays, such as 400. It's not clear to me why, maybe POINT drawing
512  // is just not very well tested.
513  const unsigned int BATCH_SIZE = 256;
514 
515  // Feed the vertices to the GL
516  if (!shader_call)
517  {
518  C4ShaderCall call(GetSpriteShader(false, false, false));
519  SetupMultiBlt(call, nullptr, 0, 0, 0, 0, &transform);
520  for(unsigned int i = 0; i < n_vertices; i += BATCH_SIZE)
521  PerformMultiBlt(sfcTarget, OP_POINTS, &vertices[i], std::min(n_vertices - i, BATCH_SIZE), false, &call);
522  }
523  else
524  {
525  SetupMultiBlt(*shader_call, nullptr, 0, 0, 0, 0, &transform);
526  for(unsigned int i = 0; i < n_vertices; i += BATCH_SIZE)
527  PerformMultiBlt(sfcTarget, OP_POINTS, &vertices[i], std::min(n_vertices - i, BATCH_SIZE), false, shader_call);
528  }
529 }
530 
531 void CStdGL::PerformMultiLines(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, float width, C4ShaderCall* shader_call)
532 {
533  // In a first step, we transform the lines array to a triangle array, so that we can draw
534  // the lines with some thickness.
535  // In principle, this step could be easily (and probably much more efficiently) performed
536  // by a geometry shader as well, however that would require OpenGL 3.2.
537  C4BltVertex* tri_vertices = new C4BltVertex[n_vertices * 3];
538  for(unsigned int i = 0; i < n_vertices; i += 2)
539  {
540  const float x1 = vertices[i].ftx;
541  const float y1 = vertices[i].fty;
542  const float x2 = vertices[i+1].ftx;
543  const float y2 = vertices[i+1].fty;
544 
545  float offx = y1 - y2;
546  float offy = x2 - x1;
547  float l = sqrtf(offx * offx + offy * offy);
548  // avoid division by zero
549  l += 0.000000005f;
550  offx *= width/l;
551  offy *= width/l;
552 
553  tri_vertices[3*i + 0].ftx = x1 + offx; tri_vertices[3*i + 0].fty = y1 + offy;
554  tri_vertices[3*i + 1].ftx = x1 - offx; tri_vertices[3*i + 1].fty = y1 - offy;
555  tri_vertices[3*i + 2].ftx = x2 - offx; tri_vertices[3*i + 2].fty = y2 - offy;
556  tri_vertices[3*i + 3].ftx = x2 + offx; tri_vertices[3*i + 3].fty = y2 + offy;
557 
558  for(int j = 0; j < 4; ++j)
559  {
560  tri_vertices[3*i + 0].color[j] = vertices[i].color[j];
561  tri_vertices[3*i + 1].color[j] = vertices[i].color[j];
562  tri_vertices[3*i + 2].color[j] = vertices[i + 1].color[j];
563  tri_vertices[3*i + 3].color[j] = vertices[i + 1].color[j];
564  }
565 
566  tri_vertices[3*i + 0].tx = 0.f; tri_vertices[3*i + 0].ty = 0.f;
567  tri_vertices[3*i + 1].tx = 0.f; tri_vertices[3*i + 1].ty = 2.f;
568  tri_vertices[3*i + 2].tx = 1.f; tri_vertices[3*i + 2].ty = 2.f;
569  tri_vertices[3*i + 3].tx = 1.f; tri_vertices[3*i + 3].ty = 0.f;
570 
571  tri_vertices[3*i + 4] = tri_vertices[3*i + 2]; // duplicate vertex
572  tri_vertices[3*i + 5] = tri_vertices[3*i + 0]; // duplicate vertex
573  }
574 
575  // Then, feed the vertices to the GL
576  if (!shader_call)
577  {
578  C4ShaderCall call(GetSpriteShader(true, false, false));
579  SetupMultiBlt(call, nullptr, lines_tex, 0, 0, 0, nullptr);
580  PerformMultiBlt(sfcTarget, OP_TRIANGLES, tri_vertices, n_vertices * 3, true, &call);
581  }
582  else
583  {
584  SetupMultiBlt(*shader_call, nullptr, lines_tex, 0, 0, 0, nullptr);
585  PerformMultiBlt(sfcTarget, OP_TRIANGLES, tri_vertices, n_vertices * 3, true, shader_call);
586  }
587 
588  delete[] tri_vertices;
589 }
590 
591 void CStdGL::PerformMultiTris(C4Surface* sfcTarget, const C4BltVertex* vertices, unsigned int n_vertices, const C4BltTransform* pTransform, C4TexRef* pTex, C4TexRef* pOverlay, C4TexRef* pNormal, DWORD dwOverlayModClr, C4ShaderCall* shader_call)
592 {
593  // Feed the vertices to the GL
594  if (!shader_call)
595  {
596  C4ShaderCall call(GetSpriteShader(pTex != nullptr, pOverlay != nullptr, pNormal != nullptr));
597  SetupMultiBlt(call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr, nullptr);
598  PerformMultiBlt(sfcTarget, OP_TRIANGLES, vertices, n_vertices, pTex != nullptr, &call);
599  }
600  else
601  {
602  SetupMultiBlt(*shader_call, pTransform, pTex ? pTex->texName : 0, pOverlay ? pOverlay->texName : 0, pNormal ? pNormal->texName : 0, dwOverlayModClr, nullptr);
603  PerformMultiBlt(sfcTarget, OP_TRIANGLES, vertices, n_vertices, pTex != nullptr, shader_call);
604  }
605 }
606 
607 void CStdGL::PerformMultiBlt(C4Surface* sfcTarget, DrawOperation op, const C4BltVertex* vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall* shader_call)
608 {
609  // Only direct rendering
610  assert(sfcTarget->IsRenderTarget());
611  if(!PrepareRendering(sfcTarget)) return;
612 
613  // Select a buffer
614  const unsigned int vbo_index = CurrentVBO;
616 
617  // Upload data into the buffer, resize buffer if necessary
618  glBindBuffer(GL_ARRAY_BUFFER, GenericVBOs[vbo_index]);
619  if (GenericVBOSizes[vbo_index] < n_vertices)
620  {
621  GenericVBOSizes[vbo_index] = n_vertices;
622  glBufferData(GL_ARRAY_BUFFER, n_vertices * sizeof(C4BltVertex), vertices, GL_STREAM_DRAW);
623  }
624  else
625  {
626  glBufferSubData(GL_ARRAY_BUFFER, 0, n_vertices * sizeof(C4BltVertex), vertices);
627  }
628 
629  // Choose the VAO that corresponds to the chosen VBO. Also, use one
630  // that supplies texture coordinates if we have texturing enabled.
631  GLuint vao;
632  const unsigned int vao_index = vbo_index + (has_tex ? N_GENERIC_VBOS : 0);
633  const unsigned int vao_id = GenericVAOs[vao_index];
634  const bool has_vao = GetVAO(vao_id, vao);
635  glBindVertexArray(vao);
636  if (!has_vao)
637  {
638  // Initialize VAO for this context
639  const GLuint position = shader_call->GetAttribute(C4SSA_Position);
640  const GLuint color = shader_call->GetAttribute(C4SSA_Color);
641  const GLuint texcoord = has_tex ? shader_call->GetAttribute(C4SSA_TexCoord) : 0;
642 
643  glEnableVertexAttribArray(position);
644  glEnableVertexAttribArray(color);
645  if (has_tex)
646  glEnableVertexAttribArray(texcoord);
647 
648 
649  glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, sizeof(C4BltVertex), reinterpret_cast<const uint8_t*>(offsetof(C4BltVertex, ftx)));
650  glVertexAttribPointer(color, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(C4BltVertex), reinterpret_cast<const uint8_t*>(offsetof(C4BltVertex, color)));
651  if (has_tex)
652  glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, sizeof(C4BltVertex), reinterpret_cast<const uint8_t*>(offsetof(C4BltVertex, tx)));
653  }
654 
655  switch (op)
656  {
657  case OP_POINTS:
658  glDrawArrays(GL_POINTS, 0, n_vertices);
659  break;
660  case OP_TRIANGLES:
661  glDrawArrays(GL_TRIANGLES, 0, n_vertices);
662  break;
663  default:
664  assert(false);
665  break;
666  }
667 
668  glBindVertexArray(0);
669  glBindBuffer(GL_ARRAY_BUFFER, 0);
670 }
671 
672 C4Shader* CStdGL::GetSpriteShader(bool haveBase, bool haveOverlay, bool haveNormal)
673 {
674  int ssc = 0;
675  if(dwBlitMode & C4GFXBLIT_MOD2) ssc |= C4SSC_MOD2;
676  if(haveBase) ssc |= C4SSC_BASE;
677  if(haveBase && haveOverlay) ssc |= C4SSC_OVERLAY;
678  if(pFoW != nullptr) ssc |= C4SSC_LIGHT;
679  if(pFoW != nullptr && haveBase && haveNormal) ssc |= C4SSC_NORMAL;
680  return GetSpriteShader(ssc);
681 }
682 
684 {
685  C4Shader* shaders[16] = {
686  &SpriteShader,
692 
703  };
704 
705  int index = 0;
706  if(ssc & C4SSC_LIGHT) index += 6;
707 
708  if(ssc & C4SSC_BASE)
709  {
710  index += 2;
711  if(ssc & C4SSC_OVERLAY)
712  index += 2;
713  if( (ssc & C4SSC_NORMAL) && (ssc & C4SSC_LIGHT))
714  index += 4;
715  }
716 
717  if(ssc & C4SSC_MOD2)
718  index += 1;
719 
720  assert(index < 16);
721  return shaders[index];
722 }
723 
725 {
726  // Create sprite blitting shaders
727  if(!PrepareSpriteShader(SpriteShader, "sprite", 0, pGroups, nullptr, nullptr))
728  return false;
729  if(!PrepareSpriteShader(SpriteShaderMod2, "spriteMod2", C4SSC_MOD2, pGroups, nullptr, nullptr))
730  return false;
731  if(!PrepareSpriteShader(SpriteShaderBase, "spriteBase", C4SSC_BASE, pGroups, nullptr, nullptr))
732  return false;
733  if(!PrepareSpriteShader(SpriteShaderBaseMod2, "spriteBaseMod2", C4SSC_MOD2 | C4SSC_BASE, pGroups, nullptr, nullptr))
734  return false;
735  if(!PrepareSpriteShader(SpriteShaderBaseOverlay, "spriteBaseOverlay", C4SSC_BASE | C4SSC_OVERLAY, pGroups, nullptr, nullptr))
736  return false;
737  if(!PrepareSpriteShader(SpriteShaderBaseOverlayMod2, "spriteBaseOverlayMod2", C4SSC_MOD2 | C4SSC_BASE | C4SSC_OVERLAY, pGroups, nullptr, nullptr))
738  return false;
739 
740  if(!PrepareSpriteShader(SpriteShaderLight, "spriteLight", C4SSC_LIGHT, pGroups, nullptr, nullptr))
741  return false;
742  if(!PrepareSpriteShader(SpriteShaderLightMod2, "spriteLightMod2", C4SSC_LIGHT | C4SSC_MOD2, pGroups, nullptr, nullptr))
743  return false;
744  if(!PrepareSpriteShader(SpriteShaderLightBase, "spriteLightBase", C4SSC_LIGHT | C4SSC_BASE, pGroups, nullptr, nullptr))
745  return false;
746  if(!PrepareSpriteShader(SpriteShaderLightBaseMod2, "spriteLightBaseMod2", C4SSC_LIGHT | C4SSC_BASE | C4SSC_MOD2, pGroups, nullptr, nullptr))
747  return false;
748  if(!PrepareSpriteShader(SpriteShaderLightBaseOverlay, "spriteLightBaseOverlay", C4SSC_LIGHT | C4SSC_BASE | C4SSC_OVERLAY, pGroups, nullptr, nullptr))
749  return false;
750  if(!PrepareSpriteShader(SpriteShaderLightBaseOverlayMod2, "spriteLightBaseOverlayMod2", C4SSC_LIGHT | C4SSC_BASE | C4SSC_OVERLAY | C4SSC_MOD2, pGroups, nullptr, nullptr))
751  return false;
752  if(!PrepareSpriteShader(SpriteShaderLightBaseNormal, "spriteLightBaseNormal", C4SSC_LIGHT | C4SSC_BASE | C4SSC_NORMAL, pGroups, nullptr, nullptr))
753  return false;
754  if(!PrepareSpriteShader(SpriteShaderLightBaseNormalMod2, "spriteLightBaseNormalMod2", C4SSC_LIGHT | C4SSC_BASE | C4SSC_NORMAL | C4SSC_MOD2, pGroups, nullptr, nullptr))
755  return false;
756  if(!PrepareSpriteShader(SpriteShaderLightBaseNormalOverlay, "spriteLightBaseNormalOverlay", C4SSC_LIGHT | C4SSC_BASE | C4SSC_OVERLAY | C4SSC_NORMAL, pGroups, nullptr, nullptr))
757  return false;
758  if(!PrepareSpriteShader(SpriteShaderLightBaseNormalOverlayMod2, "spriteLightBaseNormalOverlayMod2", C4SSC_LIGHT | C4SSC_BASE | C4SSC_OVERLAY | C4SSC_NORMAL | C4SSC_MOD2, pGroups, nullptr, nullptr))
759  return false;
760 
761  return true;
762 }
763 
765 {
766  return pMainCtx->Select();
767 }
768 
770 {
771  assert(pMainCtx);
772  // delete any previous objects
774 
775  // set states
776  Active = pMainCtx->Select();
778 
779  // lines texture
780  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
781  glGenTextures(1, &lines_tex);
782  glBindTexture(GL_TEXTURE_2D, lines_tex);
783  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
784  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
785  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
786  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
787  static const char * linedata = "\xff\xff\xff\x00\xff\xff\xff\xff";
788  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, linedata);
789 
790  MaxTexSize = 64;
791  GLint s = 0;
792  glGetIntegerv(GL_MAX_TEXTURE_SIZE, &s);
793  if (s>0) MaxTexSize = s;
794 
795  // Generic VBOs
796  glGenBuffers(N_GENERIC_VBOS, GenericVBOs);
797  for (unsigned int i = 0; i < N_GENERIC_VBOS; ++i)
798  {
800  glBindBuffer(GL_ARRAY_BUFFER, GenericVBOs[i]);
801  glBufferData(GL_ARRAY_BUFFER, GenericVBOSizes[i] * sizeof(C4BltVertex), nullptr, GL_STREAM_DRAW);
802  GenericVAOs[i] = GenVAOID();
804  }
805 
806  glBindBuffer(GL_ARRAY_BUFFER, 0);
807 
808  // reset blit states
809  dwBlitMode = 0;
810 
811  // done
812  return Active;
813 }
814 
816 {
817  bool fSuccess=true;
818  // deactivate
819  Active=false;
820  // invalidate font objects
821  // invalidate primary surfaces
822  if (lines_tex)
823  {
824  glDeleteTextures(1, &lines_tex);
825  lines_tex = 0;
826  }
827 
828  // invalidate generic VBOs
829  if (GenericVBOs[0] != 0)
830  {
831  glDeleteBuffers(N_GENERIC_VBOS, GenericVBOs);
832  GenericVBOs[0] = 0;
833  CurrentVBO = 0;
834  for (unsigned int i = 0; i < N_GENERIC_VBOS * 2; ++i)
836  }
837 
838  // invalidate shaders
839 
840  // TODO: We don't do this here because we cannot re-validate them in
841  // RestoreDeviceObjects. This should be refactored.
842 
843  /*SpriteShader.Clear();
844  SpriteShaderMod2.Clear();
845  SpriteShaderBase.Clear();
846  SpriteShaderBaseMod2.Clear();
847  SpriteShaderBaseOverlay.Clear();
848  SpriteShaderBaseOverlayMod2.Clear();
849  SpriteShaderLight.Clear();
850  SpriteShaderLightMod2.Clear();
851  SpriteShaderLightBase.Clear();
852  SpriteShaderLightBaseMod2.Clear();
853  SpriteShaderLightBaseOverlay.Clear();
854  SpriteShaderLightBaseOverlayMod2.Clear();
855  SpriteShaderLightBaseNormal.Clear();
856  SpriteShaderLightBaseNormalMod2.Clear();
857  SpriteShaderLightBaseNormalOverlay.Clear();
858  SpriteShaderLightBaseNormalOverlayMod2.Clear();*/
859  return fSuccess;
860 }
861 
862 bool CStdGL::Error(const char *szMsg)
863 {
864 #ifdef USE_WIN32_WINDOWS
865  DWORD err = GetLastError();
866 #endif
867  bool r = C4Draw::Error(szMsg);
868 #ifdef USE_WIN32_WINDOWS
869  wchar_t * lpMsgBuf;
870  FormatMessage(
871  FORMAT_MESSAGE_ALLOCATE_BUFFER |
872  FORMAT_MESSAGE_FROM_SYSTEM |
873  FORMAT_MESSAGE_IGNORE_INSERTS,
874  nullptr,
875  err,
876  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
877  (LPTSTR) &lpMsgBuf,
878  0, nullptr );
879  LogF(" gl: GetLastError() = %d - %s", err, StdStrBuf(lpMsgBuf).getData());
880  LocalFree(lpMsgBuf);
881 #endif
882  LogF(" gl: %s", glGetString(GL_VENDOR));
883  LogF(" gl: %s", glGetString(GL_RENDERER));
884  LogF(" gl: %s", glGetString(GL_VERSION));
885  LogF(" gl: %s", glGetString(GL_EXTENSIONS));
886  return r;
887 }
888 
889 const char* CStdGL::GLErrorString(GLenum code)
890 {
891  switch (code)
892  {
893  case GL_NO_ERROR: return "No error";
894  case GL_INVALID_ENUM: return "An unacceptable value is specified for an enumerated argument";
895  case GL_INVALID_VALUE: return "A numeric argument is out of range";
896  case GL_INVALID_OPERATION: return "The specified operation is not allowed in the current state";
897  case GL_INVALID_FRAMEBUFFER_OPERATION: return "The framebuffer object is not complete";
898  case GL_OUT_OF_MEMORY: return "There is not enough memory left to execute the command";
899  case GL_STACK_UNDERFLOW: return "An attempt has been made to perform an operation that would cause an internal stack to underflow";
900  case GL_STACK_OVERFLOW: return "An attempt has been made to perform an operation that would cause an internal stack to overflow";
901  default: assert(false); return "";
902  }
903 }
904 
905 bool CStdGL::CheckGLError(const char *szAtOp)
906 {
907  GLenum err = glGetError();
908  if (!err) return true;
909 
910  LogF("GL error with %s: %d - %s", szAtOp, err, GLErrorString(err));
911  return false;
912 }
913 
914 CStdGL *pGL=nullptr;
915 
916 bool CStdGL::OnResolutionChanged(unsigned int iXRes, unsigned int iYRes)
917 {
918  // Re-create primary clipper to adapt to new size.
919  CreatePrimaryClipper(iXRes, iYRes);
921  return true;
922 }
923 
925 {
926  C4Draw::Default();
927  pCurrCtx = nullptr;
928  iPixelFormat=0;
929  sfcFmt=0;
930  Workarounds.LowMaxVertexUniformCount = false;
931  Workarounds.ForceSoftwareTransform = false;
932 }
933 
934 unsigned int CStdGL::GenVAOID()
935 {
936  // Generate a new VAO ID. Make them sequential so that the actual
937  // VAOs in the context can be simply maintained with a lookup table.
938  unsigned int id;
939  if (NextVAOID == VAOIDs.begin())
940  {
941  // Insert at the beginning
942  id = 1;
943  }
944  else
945  {
946  // Insert at the end, or somewhere in the middle
947  std::set<unsigned int>::iterator iter = NextVAOID;
948  --iter;
949 
950  id = *iter + 1;
951  }
952 
953  // Actually insert the ID
954 #ifdef NDEBUG
955  std::set<unsigned int>::iterator inserted_iter = VAOIDs.insert(NextVAOID, id);
956 #else
957  std::pair<std::set<unsigned int>::iterator, bool> inserted = VAOIDs.insert(id);
958  assert(inserted.second == true);
959  std::set<unsigned int>::iterator inserted_iter = inserted.first;
960 #endif
961 
962  // Update next VAO ID: increment iterator until we find a gap
963  // in the sequence.
964  NextVAOID = inserted_iter;
965  unsigned int prev_id = id;
966  ++NextVAOID;
967  while(NextVAOID != VAOIDs.end() && prev_id + 1 == *NextVAOID)
968  {
969  prev_id = *NextVAOID;
970  ++NextVAOID;
971  }
972 
973  return id;
974 }
975 
976 void CStdGL::FreeVAOID(unsigned int vaoid)
977 {
978  std::set<unsigned int>::iterator iter = VAOIDs.find(vaoid);
979  assert(iter != VAOIDs.end());
980 
981  // Delete this VAO in the current context
982  if (pCurrCtx)
983  {
984  if (vaoid < pCurrCtx->hVAOs.size() && pCurrCtx->hVAOs[vaoid] != 0)
985  {
986  glDeleteVertexArrays(1, &pCurrCtx->hVAOs[vaoid]);
987  pCurrCtx->hVAOs[vaoid] = 0;
988  }
989  }
990 
991  // For all other contexts, mark it to be deleted as soon as we select
992  // that context. Otherwise we would need to do a lot of context
993  // switching at this point.
994  for (std::list<CStdGLCtx*>::iterator iter = CStdGLCtx::contexts.begin(); iter != CStdGLCtx::contexts.end(); ++iter)
995  {
996  CStdGLCtx* ctx = *iter;
997  if (ctx != pCurrCtx && vaoid < ctx->hVAOs.size() && ctx->hVAOs[vaoid] != 0)
998  if (std::find(ctx->VAOsToBeDeleted.begin(), ctx->VAOsToBeDeleted.end(), vaoid) == ctx->VAOsToBeDeleted.end())
999  ctx->VAOsToBeDeleted.push_back(vaoid);
1000  }
1001 
1002  // Delete the VAO ID from our list of VAO IDs in use
1003  // If the Next VAO ID is 1, then no matter what we delete we don't need
1004  // to update anything. If it is not at the beginning, then move it to the
1005  // gap we just created if it was at a higher place, to make sure we keep
1006  // the numbers as sequential as possible.
1007  unsigned int nextVaoID = 1;
1008  if (NextVAOID != VAOIDs.begin())
1009  {
1010  std::set<unsigned int>::iterator next_vao_iter = NextVAOID;
1011  --next_vao_iter;
1012  nextVaoID = *next_vao_iter + 1;
1013  }
1014 
1015  assert(vaoid != nextVaoID);
1016 
1017  if (vaoid < nextVaoID || iter == NextVAOID)
1018  NextVAOID = VAOIDs.erase(iter);
1019  else
1020  VAOIDs.erase(iter);
1021 }
1022 
1023 bool CStdGL::GetVAO(unsigned int vaoid, GLuint& vao)
1024 {
1025  assert(pCurrCtx != nullptr);
1026 
1027  if (vaoid >= pCurrCtx->hVAOs.size())
1028  {
1029  // Resize the VAO array so that all generated VAO IDs fit
1030  // in it, and not only the one requested in this call.
1031  // We hope to get away with fewer reallocations this way.
1032  assert(VAOIDs.find(vaoid) != VAOIDs.end());
1033  std::set<unsigned int>::iterator iter = VAOIDs.end();
1034  --iter;
1035 
1036  pCurrCtx->hVAOs.resize(*iter + 1);
1037  }
1038 
1039  if (pCurrCtx->hVAOs[vaoid] == 0)
1040  {
1041  glGenVertexArrays(1, &pCurrCtx->hVAOs[vaoid]);
1042  vao = pCurrCtx->hVAOs[vaoid];
1043  return false;
1044  }
1045 
1046  vao = pCurrCtx->hVAOs[vaoid];
1047  return true;
1048 }
1049 
1050 #endif // USE_CONSOLE
bool AssertMainThread()
Definition: C4App.h:123
float fty
Definition: C4Draw.h:64
int32_t DebugOpenGL
Definition: C4Config.h:118
C4Shader SpriteShaderLightBaseNormalOverlay
Definition: C4DrawGL.h:205
int MaxTexSize
Definition: C4Draw.h:99
C4Config Config
Definition: C4Config.cpp:837
virtual bool Select(bool verbose=false)
static std::list< CStdGLCtx * > contexts
Definition: C4DrawGL.h:135
#define C4GFXBLIT_MOD2
Definition: C4Surface.h:29
static const unsigned int N_GENERIC_VBOS
Definition: C4DrawGL.h:215
bool Active
Definition: C4Draw.h:96
unsigned int CurrentVBO
Definition: C4DrawGL.h:219
CStdGLCtx * pCurrCtx
Definition: C4DrawGL.h:179
void SetScriptCategories(const std::vector< std::string > &categories)
Definition: C4Shader.cpp:104
float ZoomY
Definition: C4Draw.h:112
float tx
Definition: C4Draw.h:62
C4ScriptUniform scriptUniform
Definition: C4Draw.h:100
#define GetGreenValue(rgb)
Definition: StdColors.h:30
virtual void Deselect()
unsigned char color[4]
Definition: C4Draw.h:63
const FLOAT_RECT & getViewportRegion() const
Definition: C4FoWRegion.h:52
C4Shader SpriteShaderBase
Definition: C4DrawGL.h:192
CStdGLCtx * pCtx
Definition: C4Surface.h:78
std::set< unsigned int >::iterator NextVAOID
Definition: C4DrawGL.h:227
C4Surface * pSurface
Definition: C4Window.h:279
C4Shader SpriteShaderLightBaseNormalMod2
Definition: C4DrawGL.h:204
GLint GetAttribute(int iAttribute) const
Definition: C4Shader.h:195
float gammaOut[3]
Definition: C4Draw.h:98
CStdGLCtx * pMainCtx
Definition: C4DrawGL.h:178
double GetBrightness() const
Definition: C4FoWAmbient.h:56
#define C4GFXBLIT_ADDITIVE
Definition: C4Surface.h:28
bool LoadFragmentSlices(C4GroupSet *pGroupSet, const char *szFile)
Definition: C4Shader.cpp:94
void FreeVAOID(unsigned int vaoid)
Definition: C4DrawGL.cpp:976
bool EnsureMainContextSelected() override
Definition: C4DrawGL.cpp:764
void Apply(C4ShaderCall &call)
Definition: C4Shader.cpp:830
void AddDefine(const char *name)
Definition: C4Shader.cpp:67
Definition: C4Rect.h:29
C4Shader SpriteShaderBaseOverlay
Definition: C4DrawGL.h:194
virtual void PerformMultiTris(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, const C4BltTransform *pTransform, C4TexRef *pTex, C4TexRef *pOverlay, C4TexRef *pNormal, DWORD dwOverlayClrMod, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:591
void FillBG(DWORD dwClr=0) override
Definition: C4DrawGL.cpp:153
const C4FoW * getFoW() const
Definition: C4FoWRegion.h:50
void ClearSlices()
Definition: C4Shader.cpp:326
std::vector< unsigned int > VAOsToBeDeleted
Definition: C4DrawGL.h:141
C4Shader SpriteShaderLightBaseOverlay
Definition: C4DrawGL.h:201
virtual CStdGLCtx * CreateContext(C4Window *pWindow, C4AbstractApp *pApp) override
Definition: C4DrawGL.cpp:291
#define GetRedValue(rgb)
Definition: StdColors.h:31
CStdGL()
Definition: C4DrawGL.cpp:107
float ty
Definition: C4Draw.h:62
GLuint GenericVBOs[N_GENERIC_VBOS]
Definition: C4DrawGL.h:217
int Hgt
Definition: C4Surface.h:67
C4Shader SpriteShaderLightBaseMod2
Definition: C4DrawGL.h:200
#define USERPARAM_CONST
Definition: C4DrawGL.cpp:88
const C4FoWRegion * pFoW
Definition: C4Draw.h:111
C4Shader SpriteShaderBaseMod2
Definition: C4DrawGL.h:193
bool CreatePrimaryClipper(unsigned int iXRes, unsigned int iYRes)
Definition: C4Draw.cpp:510
GLenum sfcFmt
Definition: C4DrawGL.h:177
C4ConfigGraphics Graphics
Definition: C4Config.h:254
int32_t Wdt
Definition: C4Rect.h:32
bool UpdateClipper() override
Definition: C4DrawGL.cpp:160
C4Shader SpriteShaderBaseOverlayMod2
Definition: C4DrawGL.h:195
void SetupMultiBlt(C4ShaderCall &call, const C4BltTransform *pTransform, GLuint baseTex, GLuint overlayTex, GLuint normalTex, DWORD dwOverlayModClr, StdProjectionMatrix *out_modelview)
Definition: C4DrawGL.cpp:370
void Default() override
Definition: C4DrawGL.cpp:924
void Clear() override
Definition: C4DrawGL.cpp:123
bool LogSilentF(const char *strMessage,...)
Definition: C4Log.cpp:263
int iPixelFormat
Definition: C4DrawGL.h:175
virtual bool PrepareSpriteShader(C4Shader &shader, const char *name, int ssc, C4GroupSet *pGroups, const char *const *additionalDefines, const char *const *additionalSlices) override
Definition: C4DrawGL.cpp:207
virtual void PerformMultiLines(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, float width, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:531
int32_t y
Definition: C4Rect.h:32
#define GetBlueValue(rgb)
Definition: StdColors.h:29
void Clear()
Definition: C4Shader.cpp:337
C4Shader SpriteShaderLightBaseNormalOverlayMod2
Definition: C4DrawGL.h:206
void SetUniformMatrix3x3Transpose(int iUniform, const StdMeshMatrix &matrix)
Definition: C4Shader.h:273
friend class CStdGLCtx
Definition: C4DrawGL.h:291
GLuint getSurfaceName() const
C4Shader SpriteShader
Definition: C4DrawGL.h:190
bool LoadVertexSlices(C4GroupSet *pGroupSet, const char *szFile)
Definition: C4Shader.cpp:99
bool GetVAO(unsigned int vaoid, GLuint &vao)
Definition: C4DrawGL.cpp:1023
GLuint lines_tex
Definition: C4DrawGL.h:181
#define BREAKPOINT_HERE
void SetUniformMatrix2x3fv(int iUniform, int iLength, const float *pVals) const
Definition: C4Shader.h:244
C4FoWAmbient Ambient
Definition: C4FoW.h:115
virtual bool Error(const char *szMsg)
Definition: C4Draw.cpp:503
C4Shader SpriteShaderMod2
Definition: C4DrawGL.h:191
unsigned int GenericVBOSizes[N_GENERIC_VBOS]
Definition: C4DrawGL.h:218
float ZoomX
Definition: C4Draw.h:112
unsigned int GenericVAOs[N_GENERIC_VBOS *2]
Definition: C4DrawGL.h:223
C4Shader SpriteShaderLightBaseOverlayMod2
Definition: C4DrawGL.h:202
DWORD BlitModulateClr
Definition: C4Draw.h:109
unsigned int texName
Definition: C4Surface.h:157
int32_t x
Definition: C4Rect.h:32
float Zoom
Definition: C4Draw.h:116
void SetUniform3fv(int iUniform, int iLength, const float *pVals) const
Definition: C4Shader.h:234
struct CStdGL::@10 Workarounds
const char * GLErrorString(GLenum code)
Definition: C4DrawGL.cpp:889
virtual bool OnResolutionChanged(unsigned int iXRes, unsigned int iYRes) override
Definition: C4DrawGL.cpp:916
bool Init(const char *szWhat, const char **szUniforms, const char **szAttributes)
Definition: C4Shader.cpp:350
void SetUniform1f(int iUniform, float gX) const
Definition: C4Shader.h:214
unsigned int GenVAOID()
Definition: C4DrawGL.cpp:934
static const unsigned int GENERIC_VBO_SIZE
Definition: C4DrawGL.h:216
virtual void Default()
Definition: C4Draw.cpp:172
virtual bool PrepareRendering(C4Surface *sfcToSurface) override
Definition: C4DrawGL.cpp:178
virtual bool Init(C4Window *pWindow, C4AbstractApp *pApp)
C4Shader SpriteShaderLightBaseNormal
Definition: C4DrawGL.h:203
bool RestoreDeviceObjects() override
Definition: C4DrawGL.cpp:769
C4Surface * RenderTarget
Definition: C4Draw.h:107
bool InitShaders(C4GroupSet *pGroups)
Definition: C4DrawGL.cpp:724
bool Log(const char *szMessage)
Definition: C4Log.cpp:195
float ftx
Definition: C4Draw.h:64
void GetFragTransform(const C4Rect &clipRect, const C4Rect &outRect, float lightTransform[6]) const
GLint AllocTexUnit(int iUniform)
Definition: C4Shader.cpp:670
C4Rect GetOutRect() const
Definition: C4Draw.cpp:742
void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char *label)
Definition: C4DrawGL.cpp:283
virtual void Clear()
Definition: C4Draw.cpp:187
DWORD dwBlitMode
Definition: C4Draw.h:110
virtual bool Error(const char *szMsg) override
Definition: C4DrawGL.cpp:862
void PerformMultiBlt(C4Surface *sfcTarget, DrawOperation op, const C4BltVertex *vertices, unsigned int n_vertices, bool has_tex, C4ShaderCall *shader_call)
Definition: C4DrawGL.cpp:607
void SetUniformMatrix4x4(int iUniform, const StdMeshMatrix &matrix)
Definition: C4Shader.h:288
bool ClipAll
Definition: C4Draw.h:105
~CStdGL()
Definition: C4DrawGL.cpp:117
bool IsRenderTarget()
Definition: C4Surface.cpp:154
virtual void PerformMultiPix(C4Surface *sfcTarget, const C4BltVertex *vertices, unsigned int n_vertices, C4ShaderCall *shader_call) override
Definition: C4DrawGL.cpp:504
std::set< unsigned int > VAOIDs
Definition: C4DrawGL.h:226
CStdGL * pGL
Definition: C4DrawGL.cpp:914
int32_t Hgt
Definition: C4Rect.h:32
C4Rect GetClipRect() const
Definition: C4Draw.cpp:733
bool NoPrimaryClipper()
Definition: C4Draw.cpp:240
int Locked
Definition: C4Surface.h:89
bool InvalidateDeviceObjects() override
Definition: C4DrawGL.cpp:815
void Start()
Definition: C4Shader.cpp:693
C4Shader SpriteShaderLight
Definition: C4DrawGL.h:197
C4Shader SpriteShaderLightBase
Definition: C4DrawGL.h:199
C4Shader * GetSpriteShader(int ssc)
Definition: C4DrawGL.cpp:683
uint32_t DWORD
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:253
StdProjectionMatrix ProjectionMatrix
Definition: C4DrawGL.h:184
bool BlitModulated
Definition: C4Draw.h:108
#define s
C4Window * pWindow
Definition: C4App.h:80
DrawOperation
Definition: C4Draw.h:87
void GetFragTransform(const struct FLOAT_RECT &vpRect, const C4Rect &clipRect, const C4Rect &outRect, float ambientTransform[6]) const
std::vector< GLuint > hVAOs
Definition: C4DrawGL.h:139
C4AbstractApp * pApp
Definition: C4Draw.h:95
void SetUniform4fv(int iUniform, int iLength, const float *pVals) const
Definition: C4Shader.h:238
bool CheckGLError(const char *szAtOp)
Definition: C4DrawGL.cpp:905
C4Shader SpriteShaderLightMod2
Definition: C4DrawGL.h:198