1 #include "lc_global.h"
2 #include "lc_context.h"
3 #include "lc_glextensions.h"
4 #include "lc_mesh.h"
5 #include "lc_texture.h"
6 #include "lc_colors.h"
7 #include "lc_mainwindow.h"
8 #include "lc_library.h"
9 #include "texfont.h"
10 #include "lc_view.h"
11 #include "lc_viewsphere.h"
12 #include "lc_stringcache.h"
13 #include "lc_partselectionwidget.h"
14 #include <QOpenGLFunctions_3_2_Core>
15
16 #ifdef LC_OPENGLES
17 #define glEnableClientState(...)
18 #define glDisableClientState(...)
19 #define glVertexPointer(...)
20 #define glTexCoordPointer(...)
21 #define glColorPointer(...)
22 #define GL_ARRAY_BUFFER_ARB GL_ARRAY_BUFFER
23 #define GL_ELEMENT_ARRAY_BUFFER_ARB GL_ELEMENT_ARRAY_BUFFER
24 #define GL_STATIC_DRAW_ARB GL_STATIC_DRAW
25 #endif
26
27 std::unique_ptr<QOpenGLContext> lcContext::mOffscreenContext;
28 std::unique_ptr<QOffscreenSurface> lcContext::mOffscreenSurface;
29 std::unique_ptr<lcContext> lcContext::mGlobalOffscreenContext;
30 lcProgram lcContext::mPrograms[static_cast<int>(lcMaterialType::Count)];
31
lcContext()32 lcContext::lcContext()
33 {
34 mVertexBufferObject = 0;
35 mIndexBufferObject = 0;
36 mVertexBufferPointer = nullptr;
37 mIndexBufferPointer = nullptr;
38 mVertexBufferOffset = (char*)~0;
39
40 mNormalEnabled = false;
41 mTexCoordEnabled = false;
42 mColorEnabled = false;
43
44 mTexture2D = 0;
45 mTextureCubeMap = 0;
46 mPolygonOffset = lcPolygonOffset::None;
47 mDepthWrite = true;
48 mDepthFunction = lcDepthFunction::LessEqual;
49 mCullFace = false;
50 mLineWidth = 1.0f;
51 #ifndef LC_OPENGLES
52 mMatrixMode = GL_MODELVIEW;
53 mTextureEnabled = false;
54 #endif
55
56 mColor = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
57 mWorldMatrix = lcMatrix44Identity();
58 mViewMatrix = lcMatrix44Identity();
59 mProjectionMatrix = lcMatrix44Identity();
60 mViewProjectionMatrix = lcMatrix44Identity();
61 mHighlightParams[0] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
62 mHighlightParams[1] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
63 mHighlightParams[2] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
64 mHighlightParams[3] = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
65 mColorDirty = false;
66 mWorldMatrixDirty = false;
67 mViewMatrixDirty = false;
68 mProjectionMatrixDirty = false;
69 mViewProjectionMatrixDirty = false;
70 mHighlightParamsDirty = false;
71
72 mMaterialType = lcMaterialType::Count;
73 }
74
~lcContext()75 lcContext::~lcContext()
76 {
77 }
78
InitializeRenderer()79 bool lcContext::InitializeRenderer()
80 {
81 if (!CreateOffscreenContext())
82 return false;
83
84 mGlobalOffscreenContext = std::unique_ptr<lcContext>(new(lcContext));
85
86 lcContext* Context = mGlobalOffscreenContext.get();
87 Context->SetOffscreenContext();
88
89 lcInitializeGLExtensions(mOffscreenContext.get());
90
91 // TODO: Find a better place for the grid texture and font
92 gStringCache.Initialize(Context);
93 gTexFont.Initialize(Context);
94
95 Context->CreateResources();
96 lcView::CreateResources(Context);
97 lcViewSphere::CreateResources(Context);
98
99 if (!gSupportsShaderObjects && lcGetPreferences().mShadingMode == lcShadingMode::DefaultLights)
100 lcGetPreferences().mShadingMode = lcShadingMode::Flat;
101
102 if (!gSupportsShaderObjects && lcGetPreferences().mDrawConditionalLines)
103 lcGetPreferences().mDrawConditionalLines = false;
104
105 if (!gSupportsFramebufferObject)
106 gMainWindow->GetPartSelectionWidget()->DisableIconMode();
107
108 return true;
109 }
110
ShutdownRenderer()111 void lcContext::ShutdownRenderer()
112 {
113 if (!mGlobalOffscreenContext)
114 return;
115
116 mGlobalOffscreenContext->MakeCurrent();
117 lcContext* Context = mGlobalOffscreenContext.get();
118
119 gStringCache.Reset();
120 gTexFont.Reset();
121
122 lcView::DestroyResources(Context);
123 Context->DestroyResources();
124 lcViewSphere::DestroyResources(Context);
125
126 mGlobalOffscreenContext.reset();
127
128 lcContext::DestroyOffscreenContext();
129 }
130
GetGlobalOffscreenContext()131 lcContext* lcContext::GetGlobalOffscreenContext()
132 {
133 return mGlobalOffscreenContext.get();
134 }
135
CreateOffscreenContext()136 bool lcContext::CreateOffscreenContext()
137 {
138 std::unique_ptr<QOpenGLContext> OffscreenContext(new QOpenGLContext());
139
140 if (!OffscreenContext)
141 return false;
142
143 OffscreenContext->setShareContext(QOpenGLContext::globalShareContext());
144
145 if (!OffscreenContext->create() || !OffscreenContext->isValid())
146 return false;
147
148 std::unique_ptr<QOffscreenSurface> OffscreenSurface(new QOffscreenSurface());
149
150 if (!OffscreenSurface)
151 return false;
152
153 OffscreenSurface->create();
154
155 if (!OffscreenSurface->isValid())
156 return false;
157
158 if (!OffscreenContext->makeCurrent(OffscreenSurface.get()))
159 return false;
160
161 mOffscreenContext = std::move(OffscreenContext);
162 mOffscreenSurface = std::move(OffscreenSurface);
163
164 return true;
165 }
166
DestroyOffscreenContext()167 void lcContext::DestroyOffscreenContext()
168 {
169 mOffscreenSurface.reset();
170 mOffscreenContext.reset();
171 }
172
CreateShaderPrograms()173 void lcContext::CreateShaderPrograms()
174 {
175 const char* ShaderPrefix =
176 {
177 #ifndef LC_OPENGLES
178 "#version 110\n"
179 "#define mediump\n"
180 "#define LC_VERTEX_INPUT attribute\n"
181 "#define LC_VERTEX_OUTPUT varying\n"
182 "#define LC_PIXEL_INPUT varying\n"
183 "#define LC_PIXEL_OUTPUT\n"
184 "#define LC_SHADER_PRECISION\n"
185 #else
186 "#version 300 es\n"
187 "#define texture2D texture\n"
188 "#define LC_VERTEX_INPUT in\n"
189 "#define LC_VERTEX_OUTPUT out\n"
190 "#define LC_PIXEL_INPUT in mediump\n"
191 "#define gl_FragColor FragColor\n"
192 "#define LC_PIXEL_OUTPUT out mediump vec4 gl_FragColor;\n"
193 "#define LC_SHADER_PRECISION mediump\n"
194 #endif
195
196 "#define LC_PIXEL_FAKE_LIGHTING \\\n"
197 " LC_SHADER_PRECISION vec3 Normal = normalize(PixelNormal); \\\n"
198 " LC_SHADER_PRECISION vec3 LightDirection = normalize(PixelPosition - LightPosition); \\\n"
199 " LC_SHADER_PRECISION vec3 VertexToEye = normalize(EyePosition - PixelPosition); \\\n"
200 " LC_SHADER_PRECISION vec3 LightReflect = normalize(reflect(-LightDirection, Normal)); \\\n"
201 " LC_SHADER_PRECISION float Specular = abs(dot(VertexToEye, LightReflect)); \\\n"
202 " Specular = min(pow(Specular, 8.0), 1.0) * 0.25; \\\n"
203 " LC_SHADER_PRECISION vec3 SpecularColor = vec3(Specular, Specular, Specular); \\\n"
204 " LC_SHADER_PRECISION float Diffuse = min(abs(dot(Normal, LightDirection)) * 0.6 + 0.65, 1.0);\n"
205 };
206
207 const char* const VertexShaders[] =
208 {
209 ":/resources/shaders/unlit_color_vs.glsl", // UnlitColor
210 ":/resources/shaders/unlit_color_conditional_vs.glsl", // UnlitColorConditional
211 ":/resources/shaders/unlit_texture_modulate_vs.glsl", // UnlitTextureModulate
212 ":/resources/shaders/unlit_texture_decal_vs.glsl", // UnlitTextureDecal
213 ":/resources/shaders/unlit_vertex_color_vs.glsl", // UnlitVertexColor
214 ":/resources/shaders/unlit_view_sphere_vs.glsl", // UnlitViewSphere
215 ":/resources/shaders/fakelit_color_vs.glsl", // FakeLitColor
216 ":/resources/shaders/fakelit_texture_decal_vs.glsl" // FakeLitTextureDecal
217 };
218
219 LC_ARRAY_SIZE_CHECK(VertexShaders, lcMaterialType::Count);
220
221 const char* const FragmentShaders[] =
222 {
223 ":/resources/shaders/unlit_color_ps.glsl", // UnlitColor
224 ":/resources/shaders/unlit_color_conditional_ps.glsl", // UnlitColorConditional
225 ":/resources/shaders/unlit_texture_modulate_ps.glsl", // UnlitTextureModulate
226 ":/resources/shaders/unlit_texture_decal_ps.glsl", // UnlitTextureDecal
227 ":/resources/shaders/unlit_vertex_color_ps.glsl", // UnlitVertexColor
228 ":/resources/shaders/unlit_view_sphere_ps.glsl", // UnlitViewSphere
229 ":/resources/shaders/fakelit_color_ps.glsl", // FakeLitColor
230 ":/resources/shaders/fakelit_texture_decal_ps.glsl" // FakeLitTextureDecal
231 };
232
233 LC_ARRAY_SIZE_CHECK(FragmentShaders, lcMaterialType::Count);
234
235 const auto LoadShader = [this, ShaderPrefix](const char* FileName, GLuint ShaderType) -> GLuint
236 {
237 QFile ShaderFile(FileName);
238
239 if (!ShaderFile.open(QIODevice::ReadOnly))
240 return 0;
241
242 QByteArray Data = ShaderPrefix + ShaderFile.readAll();
243 const char* Source = Data.constData();
244
245 const GLuint Shader = glCreateShader(ShaderType);
246 glShaderSource(Shader, 1, &Source, nullptr);
247 glCompileShader(Shader);
248
249 #ifndef QT_NO_DEBUG
250 GLint ShaderCompiled = 0;
251 glGetShaderiv(Shader, GL_COMPILE_STATUS, &ShaderCompiled);
252
253 if (ShaderCompiled == GL_FALSE)
254 {
255 GLint Length = 0;
256 glGetShaderiv(Shader, GL_INFO_LOG_LENGTH, &Length);
257
258 QByteArray InfoLog;
259 InfoLog.resize(Length);
260 glGetShaderInfoLog(Shader, Length, &Length, InfoLog.data());
261
262 qDebug() << InfoLog;
263 }
264 #endif
265
266 return Shader;
267 };
268
269 for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
270 {
271 const GLuint VertexShader = LoadShader(VertexShaders[MaterialType], GL_VERTEX_SHADER);
272 const GLuint FragmentShader = LoadShader(FragmentShaders[MaterialType], GL_FRAGMENT_SHADER);
273
274 GLuint Program = glCreateProgram();
275
276 glAttachShader(Program, VertexShader);
277 glAttachShader(Program, FragmentShader);
278
279 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Position), "VertexPosition");
280 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Normal), "VertexNormal");
281 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::TexCoord), "VertexTexCoord");
282 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::Color), "VertexColor");
283
284 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint1), "VertexPosition1");
285 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint2), "VertexPosition2");
286 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint3), "VertexPosition3");
287 glBindAttribLocation(Program, static_cast<int>(lcProgramAttrib::ControlPoint4), "VertexPosition4");
288
289 glLinkProgram(Program);
290
291 glDetachShader(Program, VertexShader);
292 glDetachShader(Program, FragmentShader);
293 glDeleteShader(VertexShader);
294 glDeleteShader(FragmentShader);
295
296 GLint IsLinked = 0;
297 glGetProgramiv(Program, GL_LINK_STATUS, &IsLinked);
298
299 if (IsLinked == GL_FALSE)
300 {
301 GLint Length = 0;
302 glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &Length);
303
304 QByteArray InfoLog;
305 InfoLog.resize(Length);
306 glGetProgramInfoLog(Program, Length, &Length, InfoLog.data());
307
308 glDeleteProgram(Program);
309 Program = 0;
310 }
311
312 mPrograms[MaterialType].Object = Program;
313 mPrograms[MaterialType].WorldViewProjectionMatrixLocation = glGetUniformLocation(Program, "WorldViewProjectionMatrix");
314 mPrograms[MaterialType].WorldMatrixLocation = glGetUniformLocation(Program, "WorldMatrix");
315 mPrograms[MaterialType].MaterialColorLocation = glGetUniformLocation(Program, "MaterialColor");
316 mPrograms[MaterialType].LightPositionLocation = glGetUniformLocation(Program, "LightPosition");
317 mPrograms[MaterialType].EyePositionLocation = glGetUniformLocation(Program, "EyePosition");
318 mPrograms[MaterialType].HighlightParamsLocation = glGetUniformLocation(Program, "HighlightParams");
319
320 GLint TextureLocation = glGetUniformLocation(Program, "Texture");
321
322 if (TextureLocation != -1)
323 {
324 glUseProgram(Program);
325 glUniform1i(TextureLocation, 0);
326 glUseProgram(0);
327 }
328 }
329 }
330
CreateResources()331 void lcContext::CreateResources()
332 {
333 if (!gSupportsShaderObjects)
334 return;
335
336 CreateShaderPrograms();
337 }
338
DestroyResources()339 void lcContext::DestroyResources()
340 {
341 if (!gSupportsShaderObjects)
342 return;
343
344 for (int MaterialType = 0; MaterialType < static_cast<int>(lcMaterialType::Count); MaterialType++)
345 {
346 glDeleteProgram(mPrograms[MaterialType].Object);
347 mPrograms[MaterialType].Object = 0;
348 }
349 }
350
MakeCurrent()351 void lcContext::MakeCurrent()
352 {
353 if (mWidget)
354 mWidget->makeCurrent();
355 else
356 mOffscreenContext->makeCurrent(mOffscreenSurface.get());
357 }
358
SetGLContext(QOpenGLContext * Context,QOpenGLWidget * Widget)359 void lcContext::SetGLContext(QOpenGLContext* Context, QOpenGLWidget* Widget)
360 {
361 mContext = Context;
362 mWidget = Widget;
363
364 MakeCurrent();
365 initializeOpenGLFunctions();
366 }
367
SetOffscreenContext()368 void lcContext::SetOffscreenContext()
369 {
370 SetGLContext(mOffscreenContext.get(), nullptr);
371 }
372
SetDefaultState()373 void lcContext::SetDefaultState()
374 {
375 #ifndef LC_OPENGLES
376 if (QSurfaceFormat::defaultFormat().samples() > 1)
377 glEnable(GL_LINE_SMOOTH);
378 #endif
379
380 glEnable(GL_DEPTH_TEST);
381 glDepthFunc(GL_LEQUAL);
382 mDepthFunction = lcDepthFunction::LessEqual;
383
384 if (gSupportsBlendFuncSeparate)
385 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE);
386 else
387 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
388
389 if (gSupportsVertexBufferObject)
390 {
391 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
392 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
393 }
394
395 if (gSupportsShaderObjects)
396 {
397 SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
398 EnableVertexAttrib(lcProgramAttrib::Position);
399
400 DisableVertexAttrib(lcProgramAttrib::Normal);
401 SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
402 DisableVertexAttrib(lcProgramAttrib::TexCoord);
403 SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
404 DisableVertexAttrib(lcProgramAttrib::Color);
405 SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
406 }
407 else
408 {
409 #ifndef LC_OPENGLES
410 glEnableClientState(GL_VERTEX_ARRAY);
411 glDisableClientState(GL_NORMAL_ARRAY);
412 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
413 glDisableClientState(GL_COLOR_ARRAY);
414
415 glVertexPointer(3, GL_FLOAT, 0, nullptr);
416 glNormalPointer(GL_BYTE, 0, nullptr);
417 glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
418 glColorPointer(4, GL_FLOAT, 0, nullptr);
419
420 mNormalEnabled = false;
421 mTexCoordEnabled = false;
422 mColorEnabled = false;
423 #endif
424 }
425
426 mVertexBufferObject = 0;
427 mIndexBufferObject = 0;
428 mVertexBufferPointer = nullptr;
429 mIndexBufferPointer = nullptr;
430 mVertexBufferOffset = (char*)~0;
431
432 for (int AttribIndex = 0; AttribIndex < static_cast<int>(lcProgramAttrib::Count); AttribIndex++)
433 mVertexAttribState[AttribIndex] = lcVertexAttribState();
434
435 glBindTexture(GL_TEXTURE_2D, 0);
436 mTexture2D = 0;
437 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
438 mTextureCubeMap = 0;
439
440 glDisable(GL_POLYGON_OFFSET_FILL);
441 mPolygonOffset = lcPolygonOffset::None;
442
443 mDepthWrite = true;
444 glDepthMask(GL_TRUE);
445
446 glDisable(GL_CULL_FACE);
447 mCullFace = false;
448
449 glLineWidth(1.0f);
450 mLineWidth = 1.0f;
451
452 if (gSupportsShaderObjects)
453 {
454 glUseProgram(0);
455 mMaterialType = lcMaterialType::Count;
456 }
457 else
458 {
459 #ifndef LC_OPENGLES
460 glMatrixMode(GL_MODELVIEW);
461 mMatrixMode = GL_MODELVIEW;
462 glShadeModel(GL_FLAT);
463
464 glDisable(GL_TEXTURE_2D);
465 mTextureEnabled = false;
466 #endif
467 }
468 }
469
ClearColorAndDepth(const lcVector4 & ClearColor)470 void lcContext::ClearColorAndDepth(const lcVector4& ClearColor)
471 {
472 glClearColor(ClearColor[0], ClearColor[1], ClearColor[2], ClearColor[3]);
473 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
474 }
475
ClearDepth()476 void lcContext::ClearDepth()
477 {
478 glClear(GL_DEPTH_BUFFER_BIT);
479 }
480
ClearResources()481 void lcContext::ClearResources()
482 {
483 ClearVertexBuffer();
484 ClearIndexBuffer();
485 BindTexture2D(0);
486 }
487
SetMaterial(lcMaterialType MaterialType)488 void lcContext::SetMaterial(lcMaterialType MaterialType)
489 {
490 if (MaterialType == mMaterialType)
491 return;
492
493 mMaterialType = MaterialType;
494
495 if (gSupportsShaderObjects)
496 {
497 glUseProgram(mPrograms[static_cast<int>(MaterialType)].Object);
498 mColorDirty = true;
499 mWorldMatrixDirty = true; // todo: change dirty to a bitfield and set the lighting constants dirty here
500 mViewMatrixDirty = true;
501 mHighlightParamsDirty = true;
502 }
503 else
504 {
505 #ifndef LC_OPENGLES
506 switch (MaterialType)
507 {
508 case lcMaterialType::UnlitTextureModulate:
509 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
510
511 if (!mTextureEnabled)
512 {
513 glEnable(GL_TEXTURE_2D);
514 mTextureEnabled = true;
515 }
516 break;
517
518 case lcMaterialType::FakeLitTextureDecal:
519 case lcMaterialType::UnlitTextureDecal:
520 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
521
522 if (!mTextureEnabled)
523 {
524 glEnable(GL_TEXTURE_2D);
525 mTextureEnabled = true;
526 }
527 break;
528
529 case lcMaterialType::UnlitColor:
530 case lcMaterialType::UnlitColorConditional:
531 case lcMaterialType::UnlitVertexColor:
532 case lcMaterialType::FakeLitColor:
533 if (mTextureEnabled)
534 {
535 glDisable(GL_TEXTURE_2D);
536 mTextureEnabled = false;
537 }
538 break;
539
540 case lcMaterialType::UnlitViewSphere:
541 case lcMaterialType::Count:
542 break;
543 }
544 #endif
545 }
546 }
547
SetViewport(int x,int y,int Width,int Height)548 void lcContext::SetViewport(int x, int y, int Width, int Height)
549 {
550 glViewport(x, y, Width, Height);
551 }
552
SetPolygonOffset(lcPolygonOffset PolygonOffset)553 void lcContext::SetPolygonOffset(lcPolygonOffset PolygonOffset)
554 {
555 if (mPolygonOffset == PolygonOffset)
556 return;
557
558 switch (PolygonOffset)
559 {
560 case lcPolygonOffset::None:
561 glDisable(GL_POLYGON_OFFSET_FILL);
562 break;
563
564 case lcPolygonOffset::Opaque:
565 glPolygonOffset(0.5f, 0.1f);
566 glEnable(GL_POLYGON_OFFSET_FILL);
567 break;
568
569 case lcPolygonOffset::Translucent:
570 glPolygonOffset(0.25f, 0.1f);
571 glEnable(GL_POLYGON_OFFSET_FILL);
572 break;
573 }
574
575 mPolygonOffset = PolygonOffset;
576 }
577
SetDepthWrite(bool Enable)578 void lcContext::SetDepthWrite(bool Enable)
579 {
580 if (Enable == mDepthWrite)
581 return;
582
583 glDepthMask(Enable ? GL_TRUE : GL_FALSE);
584 mDepthWrite = Enable;
585 }
586
SetDepthFunction(lcDepthFunction DepthFunction)587 void lcContext::SetDepthFunction(lcDepthFunction DepthFunction)
588 {
589 if (DepthFunction == mDepthFunction)
590 return;
591
592 switch (DepthFunction)
593 {
594 case lcDepthFunction::Always:
595 glDepthFunc(GL_ALWAYS);
596 break;
597
598 case lcDepthFunction::LessEqual:
599 glDepthFunc(GL_LEQUAL);
600 break;
601 }
602
603 mDepthFunction = DepthFunction;
604 }
605
EnableCullFace(bool Enable)606 void lcContext::EnableCullFace(bool Enable)
607 {
608 if (Enable == mCullFace)
609 return;
610
611 if (Enable)
612 glEnable(GL_CULL_FACE);
613 else
614 glDisable(GL_CULL_FACE);
615
616 mCullFace = Enable;
617 }
618
SetLineWidth(float LineWidth)619 void lcContext::SetLineWidth(float LineWidth)
620 {
621 if (LineWidth == mLineWidth)
622 return;
623
624 glLineWidth(LineWidth);
625 mLineWidth = LineWidth;
626 }
627
SetSmoothShading(bool Smooth)628 void lcContext::SetSmoothShading(bool Smooth)
629 {
630 #ifndef LC_OPENGLES
631 if (gSupportsShaderObjects)
632 glShadeModel(Smooth ? GL_SMOOTH : GL_FLAT);
633 #endif
634 }
635
BindTexture2D(GLuint Texture)636 void lcContext::BindTexture2D(GLuint Texture)
637 {
638 if (mTexture2D == Texture)
639 return;
640
641 glBindTexture(GL_TEXTURE_2D, Texture);
642 mTexture2D = Texture;
643 }
644
BindTextureCubeMap(GLuint Texture)645 void lcContext::BindTextureCubeMap(GLuint Texture)
646 {
647 if (mTextureCubeMap == Texture)
648 return;
649
650 glBindTexture(GL_TEXTURE_CUBE_MAP, Texture);
651 mTextureCubeMap = Texture;
652 }
653
UnbindTexture2D(GLuint Texture)654 void lcContext::UnbindTexture2D(GLuint Texture)
655 {
656 if (mTexture2D != Texture)
657 return;
658
659 glBindTexture(GL_TEXTURE_2D, 0);
660 mTexture2D = 0;
661 }
662
UnbindTextureCubeMap(GLuint Texture)663 void lcContext::UnbindTextureCubeMap(GLuint Texture)
664 {
665 if (mTextureCubeMap != Texture)
666 return;
667
668 glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
669 mTextureCubeMap = 0;
670 }
671
SetColor(float Red,float Green,float Blue,float Alpha)672 void lcContext::SetColor(float Red, float Green, float Blue, float Alpha)
673 {
674 SetColor(lcVector4(Red, Green, Blue, Alpha));
675 }
676
SetColorIndex(int ColorIndex)677 void lcContext::SetColorIndex(int ColorIndex)
678 {
679 SetColor(gColorList[ColorIndex].Value);
680 }
681
SetColorIndexTinted(int ColorIndex,lcInterfaceColor InterfaceColor,float Weight)682 void lcContext::SetColorIndexTinted(int ColorIndex, lcInterfaceColor InterfaceColor, float Weight)
683 {
684 const lcVector3 Color(gColorList[ColorIndex].Value * Weight + gInterfaceColors[InterfaceColor] * (1.0f - Weight));
685 SetColor(lcVector4(Color, gColorList[ColorIndex].Value.w));
686 }
687
SetColorIndexTinted(int ColorIndex,const lcVector4 & Tint)688 void lcContext::SetColorIndexTinted(int ColorIndex, const lcVector4& Tint)
689 {
690 SetColor(gColorList[ColorIndex].Value * Tint);
691 }
692
SetEdgeColorIndex(int ColorIndex)693 void lcContext::SetEdgeColorIndex(int ColorIndex)
694 {
695 SetColor(gColorList[ColorIndex].Edge);
696 }
697
SetEdgeColorIndexTinted(int ColorIndex,const lcVector4 & Tint)698 void lcContext::SetEdgeColorIndexTinted(int ColorIndex, const lcVector4& Tint)
699 {
700 SetColor(gColorList[ColorIndex].Edge * Tint);
701 }
702
SetInterfaceColor(lcInterfaceColor InterfaceColor)703 void lcContext::SetInterfaceColor(lcInterfaceColor InterfaceColor)
704 {
705 SetColor(gInterfaceColors[InterfaceColor]);
706 }
707
CreateVertexBuffer(int Size,const void * Data)708 lcVertexBuffer lcContext::CreateVertexBuffer(int Size, const void* Data)
709 {
710 lcVertexBuffer VertexBuffer;
711
712 if (gSupportsVertexBufferObject)
713 {
714 glGenBuffers(1, &VertexBuffer.Object);
715 glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBuffer.Object);
716 glBufferData(GL_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
717
718 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0); // context remove
719 mVertexBufferObject = 0;
720 }
721 else
722 {
723 VertexBuffer.Pointer = malloc(Size);
724 if (VertexBuffer.Pointer)
725 memcpy(VertexBuffer.Pointer, Data, Size);
726 }
727
728 return VertexBuffer;
729 }
730
DestroyVertexBuffer(lcVertexBuffer & VertexBuffer)731 void lcContext::DestroyVertexBuffer(lcVertexBuffer& VertexBuffer)
732 {
733 if (!VertexBuffer.IsValid())
734 return;
735
736 if (gSupportsVertexBufferObject)
737 {
738 if (mVertexBufferObject == VertexBuffer.Object)
739 {
740 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
741 mVertexBufferObject = 0;
742 }
743
744 glDeleteBuffers(1, &VertexBuffer.Object);
745 }
746 else
747 {
748 free(VertexBuffer.Pointer);
749 }
750
751 VertexBuffer.Pointer = nullptr;
752 }
753
CreateIndexBuffer(int Size,const void * Data)754 lcIndexBuffer lcContext::CreateIndexBuffer(int Size, const void* Data)
755 {
756 lcIndexBuffer IndexBuffer;
757
758 if (gSupportsVertexBufferObject)
759 {
760 glGenBuffers(1, &IndexBuffer.Object);
761 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBuffer.Object);
762 glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, Size, Data, GL_STATIC_DRAW_ARB);
763
764 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // context remove
765 mIndexBufferObject = 0;
766 }
767 else
768 {
769 IndexBuffer.Pointer = malloc(Size);
770 if (IndexBuffer.Pointer)
771 memcpy(IndexBuffer.Pointer, Data, Size);
772 }
773
774 return IndexBuffer;
775 }
776
DestroyIndexBuffer(lcIndexBuffer & IndexBuffer)777 void lcContext::DestroyIndexBuffer(lcIndexBuffer& IndexBuffer)
778 {
779 if (!IndexBuffer.IsValid())
780 return;
781
782 if (gSupportsVertexBufferObject)
783 {
784 if (mIndexBufferObject == IndexBuffer.Object)
785 {
786 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
787 mIndexBufferObject = 0;
788 }
789
790 glDeleteBuffers(1, &IndexBuffer.Object);
791 }
792 else
793 {
794 free(IndexBuffer.Pointer);
795 }
796
797 IndexBuffer.Pointer = nullptr;
798 }
799
ClearVertexBuffer()800 void lcContext::ClearVertexBuffer()
801 {
802 mVertexBufferPointer = nullptr;
803 mVertexBufferOffset = (char*)~0;
804
805 if (mVertexBufferObject)
806 {
807 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
808 mVertexBufferObject = 0;
809 }
810
811 if (gSupportsShaderObjects)
812 {
813 SetVertexAttribPointer(lcProgramAttrib::Position, 3, GL_FLOAT, false, 0, nullptr);
814
815 DisableVertexAttrib(lcProgramAttrib::Normal);
816 SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, 0, nullptr);
817 DisableVertexAttrib(lcProgramAttrib::TexCoord);
818 SetVertexAttribPointer(lcProgramAttrib::TexCoord, 2, GL_FLOAT, false, 0, nullptr);
819 DisableVertexAttrib(lcProgramAttrib::Color);
820 SetVertexAttribPointer(lcProgramAttrib::Color, 4, GL_FLOAT, false, 0, nullptr);
821 }
822 else
823 {
824 #ifndef LC_OPENGLES
825 if (mNormalEnabled)
826 glDisableClientState(GL_NORMAL_ARRAY);
827
828 if (mTexCoordEnabled)
829 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
830
831 if (mColorEnabled)
832 glDisableClientState(GL_COLOR_ARRAY);
833
834 glVertexPointer(3, GL_FLOAT, 0, nullptr);
835 glNormalPointer(GL_BYTE, 0, nullptr);
836 glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
837 glColorPointer(4, GL_FLOAT, 0, nullptr);
838 #endif
839 }
840 }
841
SetVertexBuffer(lcVertexBuffer VertexBuffer)842 void lcContext::SetVertexBuffer(lcVertexBuffer VertexBuffer)
843 {
844 if (gSupportsVertexBufferObject)
845 {
846 const GLuint VertexBufferObject = VertexBuffer.Object;
847 mVertexBufferPointer = nullptr;
848
849 if (VertexBufferObject != mVertexBufferObject)
850 {
851 glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
852 mVertexBufferObject = VertexBufferObject;
853 mVertexBufferOffset = (char*)~0;
854 }
855 }
856 else
857 {
858 mVertexBufferPointer = (char*)VertexBuffer.Pointer;
859 mVertexBufferOffset = (char*)~0;
860 }
861 }
862
SetVertexBufferPointer(const void * VertexBuffer)863 void lcContext::SetVertexBufferPointer(const void* VertexBuffer)
864 {
865 if (gSupportsVertexBufferObject && mVertexBufferObject)
866 {
867 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
868 mVertexBufferObject = 0;
869 }
870
871 mVertexBufferPointer = (char*)VertexBuffer;
872 mVertexBufferOffset = (char*)~0;
873 }
874
SetVertexAttribPointer(lcProgramAttrib Attrib,GLint Size,GLenum Type,GLboolean Normalized,GLsizei Stride,const void * Pointer)875 void lcContext::SetVertexAttribPointer(lcProgramAttrib Attrib, GLint Size, GLenum Type, GLboolean Normalized, GLsizei Stride, const void* Pointer)
876 {
877 const int Index = static_cast<int>(Attrib);
878 lcVertexAttribState& State = mVertexAttribState[Index];
879
880 if (State.Size != Size || State.Type != Type || State.Normalized != Normalized || State.Stride != Stride || State.Pointer != Pointer || State.VertexBufferObject != mVertexBufferObject)
881 {
882 glVertexAttribPointer(Index, Size, Type, Normalized, Stride, Pointer);
883
884 State.Size = Size;
885 State.Type = Type;
886 State.Normalized = Normalized;
887 State.Stride = Stride;
888 State.Pointer = Pointer;
889 State.VertexBufferObject = mVertexBufferObject;
890 }
891 }
892
EnableVertexAttrib(lcProgramAttrib Attrib)893 void lcContext::EnableVertexAttrib(lcProgramAttrib Attrib)
894 {
895 const int Index = static_cast<int>(Attrib);
896 lcVertexAttribState& State = mVertexAttribState[Index];
897
898 if (!State.Enabled)
899 {
900 glEnableVertexAttribArray(Index);
901 State.Enabled = true;
902 }
903 }
904
DisableVertexAttrib(lcProgramAttrib Attrib)905 void lcContext::DisableVertexAttrib(lcProgramAttrib Attrib)
906 {
907 const int Index = static_cast<int>(Attrib);
908 lcVertexAttribState& State = mVertexAttribState[Index];
909
910 if (State.Enabled)
911 {
912 glDisableVertexAttribArray(Index);
913 State.Enabled = false;
914 }
915 }
916
SetVertexFormatPosition(int PositionSize)917 void lcContext::SetVertexFormatPosition(int PositionSize)
918 {
919 const int VertexSize = PositionSize * sizeof(float);
920 const char* VertexBufferPointer = mVertexBufferPointer;
921
922 if (gSupportsShaderObjects)
923 {
924 SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
925 DisableVertexAttrib(lcProgramAttrib::Normal);
926 DisableVertexAttrib(lcProgramAttrib::TexCoord);
927 DisableVertexAttrib(lcProgramAttrib::Color);
928 }
929 else
930 {
931 if (mVertexBufferOffset != mVertexBufferPointer)
932 {
933 glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
934 mVertexBufferOffset = VertexBufferPointer;
935 }
936
937 if (mNormalEnabled)
938 {
939 glDisableClientState(GL_NORMAL_ARRAY);
940 mNormalEnabled = false;
941 }
942
943 if (mTexCoordEnabled)
944 {
945 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
946 mTexCoordEnabled = false;
947 }
948
949 if (mColorEnabled)
950 {
951 glDisableClientState(GL_COLOR_ARRAY);
952 mColorEnabled = false;
953 }
954 }
955 }
956
SetVertexFormatConditional(int BufferOffset)957 void lcContext::SetVertexFormatConditional(int BufferOffset)
958 {
959 const int VertexSize = 12 * sizeof(float);
960 const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
961
962 if (gSupportsShaderObjects)
963 {
964 SetVertexAttribPointer(lcProgramAttrib::ControlPoint1, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer);
965 EnableVertexAttrib(lcProgramAttrib::ControlPoint1);
966 SetVertexAttribPointer(lcProgramAttrib::ControlPoint2, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 3 * sizeof(float));
967 EnableVertexAttrib(lcProgramAttrib::ControlPoint2);
968 SetVertexAttribPointer(lcProgramAttrib::ControlPoint3, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 6 * sizeof(float));
969 EnableVertexAttrib(lcProgramAttrib::ControlPoint3);
970 SetVertexAttribPointer(lcProgramAttrib::ControlPoint4, 3, GL_FLOAT, false, VertexSize, VertexBufferPointer + 9 * sizeof(float));
971 EnableVertexAttrib(lcProgramAttrib::ControlPoint4);
972 }
973 }
974
SetVertexFormat(int BufferOffset,int PositionSize,int NormalSize,int TexCoordSize,int ColorSize,bool EnableNormals)975 void lcContext::SetVertexFormat(int BufferOffset, int PositionSize, int NormalSize, int TexCoordSize, int ColorSize, bool EnableNormals)
976 {
977 const int VertexSize = (PositionSize + TexCoordSize) * sizeof(float) + NormalSize * sizeof(quint32) + ColorSize;
978 const char* VertexBufferPointer = mVertexBufferPointer + BufferOffset;
979
980 if (gSupportsShaderObjects)
981 {
982 int Offset = 0;
983
984 SetVertexAttribPointer(lcProgramAttrib::Position, PositionSize, GL_FLOAT, false, VertexSize, VertexBufferPointer);
985 EnableVertexAttrib(lcProgramAttrib::Position);
986
987 Offset += PositionSize * sizeof(float);
988
989 if (NormalSize && EnableNormals)
990 {
991 SetVertexAttribPointer(lcProgramAttrib::Normal, 4, GL_BYTE, true, VertexSize, VertexBufferPointer + Offset);
992 EnableVertexAttrib(lcProgramAttrib::Normal);
993 }
994 else
995 DisableVertexAttrib(lcProgramAttrib::Normal);
996
997 Offset += NormalSize * sizeof(quint32);
998
999 if (TexCoordSize)
1000 {
1001 SetVertexAttribPointer(lcProgramAttrib::TexCoord, TexCoordSize, GL_FLOAT, false, VertexSize, VertexBufferPointer + Offset);
1002 EnableVertexAttrib(lcProgramAttrib::TexCoord);
1003 }
1004 else
1005 DisableVertexAttrib(lcProgramAttrib::TexCoord);
1006
1007 Offset += TexCoordSize * sizeof(float);
1008
1009 if (ColorSize)
1010 {
1011 SetVertexAttribPointer(lcProgramAttrib::Color, ColorSize, GL_UNSIGNED_BYTE, true, VertexSize, VertexBufferPointer + Offset);
1012 EnableVertexAttrib(lcProgramAttrib::Color);
1013 }
1014 else
1015 DisableVertexAttrib(lcProgramAttrib::Color);
1016 }
1017 else
1018 {
1019 #ifndef LC_OPENGLES
1020 if (mVertexBufferOffset != VertexBufferPointer)
1021 {
1022 glVertexPointer(PositionSize, GL_FLOAT, VertexSize, VertexBufferPointer);
1023 mVertexBufferOffset = VertexBufferPointer;
1024 }
1025
1026 int Offset = PositionSize * sizeof(float);
1027
1028 if (NormalSize && EnableNormals)
1029 {
1030 glNormalPointer(GL_BYTE, VertexSize, VertexBufferPointer + Offset);
1031
1032 if (!mNormalEnabled)
1033 {
1034 glEnableClientState(GL_NORMAL_ARRAY);
1035 mNormalEnabled = true;
1036 }
1037 }
1038 else if (mNormalEnabled)
1039 {
1040 glDisableClientState(GL_NORMAL_ARRAY);
1041 mNormalEnabled = false;
1042 }
1043
1044 Offset += NormalSize * sizeof(quint32);
1045
1046 if (TexCoordSize)
1047 {
1048 glTexCoordPointer(TexCoordSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
1049
1050 if (!mTexCoordEnabled)
1051 {
1052 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1053 mTexCoordEnabled = true;
1054 }
1055
1056 Offset += 2 * sizeof(float);
1057 }
1058 else if (mTexCoordEnabled)
1059 {
1060 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1061 mTexCoordEnabled = false;
1062 }
1063
1064 if (ColorSize)
1065 {
1066 glColorPointer(ColorSize, GL_FLOAT, VertexSize, VertexBufferPointer + Offset);
1067
1068 if (!mColorEnabled)
1069 {
1070 glEnableClientState(GL_COLOR_ARRAY);
1071 mColorEnabled = true;
1072 }
1073 }
1074 else if (mColorEnabled)
1075 {
1076 glDisableClientState(GL_COLOR_ARRAY);
1077 mColorEnabled = false;
1078 }
1079 #endif
1080 }
1081 }
1082
ClearIndexBuffer()1083 void lcContext::ClearIndexBuffer()
1084 {
1085 if (mIndexBufferObject)
1086 {
1087 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1088 mIndexBufferObject = 0;
1089 }
1090 }
1091
SetIndexBuffer(lcIndexBuffer IndexBuffer)1092 void lcContext::SetIndexBuffer(lcIndexBuffer IndexBuffer)
1093 {
1094 if (gSupportsVertexBufferObject)
1095 {
1096 const GLuint IndexBufferObject = IndexBuffer.Object;
1097 mIndexBufferPointer = nullptr;
1098
1099 if (IndexBufferObject != mIndexBufferObject)
1100 {
1101 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
1102 mIndexBufferObject = IndexBufferObject;
1103 }
1104 }
1105 else
1106 {
1107 mIndexBufferPointer = (char*)IndexBuffer.Pointer;
1108 }
1109 }
1110
SetIndexBufferPointer(const void * IndexBuffer)1111 void lcContext::SetIndexBufferPointer(const void* IndexBuffer)
1112 {
1113 if (mIndexBufferObject)
1114 {
1115 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1116 mIndexBufferObject = 0;
1117 }
1118
1119 mIndexBufferPointer = (char*)IndexBuffer;
1120 }
1121
BindMesh(const lcMesh * Mesh)1122 void lcContext::BindMesh(const lcMesh* Mesh)
1123 {
1124 const lcPiecesLibrary* const Library = lcGetPiecesLibrary();
1125
1126 if (Mesh->mVertexCacheOffset != -1)
1127 {
1128 const GLuint VertexBufferObject = Library->mVertexBuffer.Object;
1129 const GLuint IndexBufferObject = Library->mIndexBuffer.Object;
1130
1131 if (VertexBufferObject != mVertexBufferObject)
1132 {
1133 glBindBuffer(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
1134 mVertexBufferObject = VertexBufferObject;
1135 mVertexBufferPointer = nullptr;
1136 mVertexBufferOffset = (char*)~0;
1137 }
1138
1139 if (IndexBufferObject != mIndexBufferObject)
1140 {
1141 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBufferObject);
1142 mIndexBufferObject = IndexBufferObject;
1143 mIndexBufferPointer = nullptr;
1144 }
1145 }
1146 else
1147 {
1148 if (mVertexBufferObject)
1149 {
1150 glBindBuffer(GL_ARRAY_BUFFER_ARB, 0);
1151 mVertexBufferObject = 0;
1152 }
1153
1154 if (mIndexBufferObject)
1155 {
1156 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1157 mIndexBufferObject = 0;
1158 }
1159
1160 mVertexBufferPointer = (char*)Mesh->mVertexData;
1161 mIndexBufferPointer = (char*)Mesh->mIndexData;
1162 mVertexBufferOffset = (char*)~0;
1163 }
1164 }
1165
FlushState()1166 void lcContext::FlushState()
1167 {
1168 if (gSupportsShaderObjects)
1169 {
1170 const lcProgram& Program = mPrograms[static_cast<int>(mMaterialType)];
1171
1172 if (mWorldMatrixDirty || mViewMatrixDirty || mProjectionMatrixDirty)
1173 {
1174 if (mViewProjectionMatrixDirty)
1175 {
1176 mViewProjectionMatrix = lcMul(mViewMatrix, mProjectionMatrix);
1177 mViewProjectionMatrixDirty = false;
1178 }
1179
1180 if (mWorldMatrixDirty)
1181 {
1182 if (Program.WorldMatrixLocation != -1)
1183 glUniformMatrix4fv(Program.WorldMatrixLocation, 1, false, mWorldMatrix);
1184 }
1185
1186 if (mViewMatrixDirty)
1187 {
1188 const lcMatrix44 InverseViewMatrix = lcMatrix44AffineInverse(mViewMatrix);
1189 lcVector3 ViewPosition = lcMul30(-mViewMatrix.GetTranslation(), InverseViewMatrix);
1190
1191 if (Program.LightPositionLocation != -1)
1192 {
1193 lcVector3 LightPosition = ViewPosition + lcMul30(lcVector3(300.0f, 300.0f, 0.0f), InverseViewMatrix);
1194 glUniform3fv(Program.LightPositionLocation, 1, LightPosition);
1195 }
1196
1197 if (Program.EyePositionLocation != -1)
1198 glUniform3fv(Program.EyePositionLocation, 1, ViewPosition);
1199 }
1200
1201 glUniformMatrix4fv(Program.WorldViewProjectionMatrixLocation, 1, false, lcMul(mWorldMatrix, mViewProjectionMatrix));
1202 mWorldMatrixDirty = false;
1203 mViewMatrixDirty = false;
1204 mProjectionMatrixDirty = false;
1205 }
1206
1207 if (mColorDirty && Program.MaterialColorLocation != -1)
1208 {
1209 glUniform4fv(Program.MaterialColorLocation, 1, mColor);
1210 mColorDirty = false;
1211 }
1212
1213 if (mHighlightParamsDirty && Program.HighlightParamsLocation != -1)
1214 {
1215 glUniform4fv(Program.HighlightParamsLocation, 4, mHighlightParams[0]);
1216 mHighlightParamsDirty = false;
1217 }
1218 }
1219 else
1220 {
1221 #ifndef LC_OPENGLES
1222 glColor4fv(mColor);
1223
1224 if (mWorldMatrixDirty || mViewMatrixDirty)
1225 {
1226 if (mMatrixMode != GL_MODELVIEW)
1227 {
1228 glMatrixMode(GL_MODELVIEW);
1229 mMatrixMode = GL_MODELVIEW;
1230 }
1231
1232 glLoadMatrixf(lcMul(mWorldMatrix, mViewMatrix));
1233 mWorldMatrixDirty = false;
1234 mViewMatrixDirty = false;
1235 }
1236
1237 if (mProjectionMatrixDirty)
1238 {
1239 if (mMatrixMode != GL_PROJECTION)
1240 {
1241 glMatrixMode(GL_PROJECTION);
1242 mMatrixMode = GL_PROJECTION;
1243 }
1244
1245 glLoadMatrixf(mProjectionMatrix);
1246 mProjectionMatrixDirty = false;
1247 }
1248 #endif
1249 }
1250 }
1251
DrawPrimitives(GLenum Mode,GLint First,GLsizei Count)1252 void lcContext::DrawPrimitives(GLenum Mode, GLint First, GLsizei Count)
1253 {
1254 FlushState();
1255 glDrawArrays(Mode, First, Count);
1256 }
1257
DrawIndexedPrimitives(GLenum Mode,GLsizei Count,GLenum Type,int Offset)1258 void lcContext::DrawIndexedPrimitives(GLenum Mode, GLsizei Count, GLenum Type, int Offset)
1259 {
1260 FlushState();
1261 glDrawElements(Mode, Count, Type, mIndexBufferPointer + Offset);
1262 }
1263