From 688315ab76145a32d0aebf826fbbb7fc9ce24443 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 20 Oct 2012 23:06:56 +0200 Subject: ComputeSphereVisibility and fixes in CEngine TODOs - view frustum culling with ComputeSphereVisibility - game should run faster now - resolved/removed most TODOs from CEngine - fixed OpenGL tests --- src/graphics/opengl/gldevice.cpp | 80 ++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 35 deletions(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 94b0dbc..a6ba1eb 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -929,27 +929,25 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius) { - float distance = (originPlane + Math::DotProduct(normal, center)) / normal.Length(); + float distance = originPlane + Math::DotProduct(normal, center); if (distance < -radius) - return true; + return false; - return false; + return true; } -/* - The implementation of ComputeSphereVisibility is taken from libwine's device.c - Copyright of the WINE team, licensed under GNU LGPL v 2.1 - */ +/* Based on libwine's implementation */ -// TODO: testing int CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float radius) { Math::Matrix m; - m.LoadIdentity(); - m = Math::MultiplyMatrices(m, m_worldMat); - m = Math::MultiplyMatrices(m, m_viewMat); - m = Math::MultiplyMatrices(m, m_projectionMat); + m = Math::MultiplyMatrices(m_worldMat, m); + m = Math::MultiplyMatrices(m_viewMat, m); + Math::Matrix sc; + Math::LoadScaleMatrix(sc, Math::Vector(1.0f, 1.0f, -1.0f)); + m = Math::MultiplyMatrices(sc, m); + m = Math::MultiplyMatrices(m_projectionMat, m); Math::Vector vec[6]; float originPlane[6]; @@ -958,52 +956,64 @@ int CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float radius) vec[0].x = m.Get(4, 1) + m.Get(1, 1); vec[0].y = m.Get(4, 2) + m.Get(1, 2); vec[0].z = m.Get(4, 3) + m.Get(1, 3); - originPlane[0] = m.Get(4, 4) + m.Get(1, 4); + float l1 = vec[0].Length(); + vec[0].Normalize(); + originPlane[0] = (m.Get(4, 4) + m.Get(1, 4)) / l1; // Right plane vec[1].x = m.Get(4, 1) - m.Get(1, 1); vec[1].y = m.Get(4, 2) - m.Get(1, 2); vec[1].z = m.Get(4, 3) - m.Get(1, 3); - originPlane[1] = m.Get(4, 4) - m.Get(1, 4); - - // Top plane - vec[2].x = m.Get(4, 1) - m.Get(2, 1); - vec[2].y = m.Get(4, 2) - m.Get(2, 2); - vec[2].z = m.Get(4, 3) - m.Get(2, 3); - originPlane[2] = m.Get(4, 4) - m.Get(2, 4); + float l2 = vec[1].Length(); + vec[1].Normalize(); + originPlane[1] = (m.Get(4, 4) - m.Get(1, 4)) / l2; // Bottom plane - vec[3].x = m.Get(4, 1) + m.Get(2, 1); - vec[3].y = m.Get(4, 2) + m.Get(2, 2); - vec[3].z = m.Get(4, 3) + m.Get(2, 3); - originPlane[3] = m.Get(4, 4) + m.Get(2, 4); + vec[2].x = m.Get(4, 1) + m.Get(2, 1); + vec[2].y = m.Get(4, 2) + m.Get(2, 2); + vec[2].z = m.Get(4, 3) + m.Get(2, 3); + float l3 = vec[2].Length(); + vec[2].Normalize(); + originPlane[2] = (m.Get(4, 4) + m.Get(2, 4)) / l3; + + // Top plane + vec[3].x = m.Get(4, 1) - m.Get(2, 1); + vec[3].y = m.Get(4, 2) - m.Get(2, 2); + vec[3].z = m.Get(4, 3) - m.Get(2, 3); + float l4 = vec[3].Length(); + vec[3].Normalize(); + originPlane[3] = (m.Get(4, 4) - m.Get(2, 4)) / l4; // Front plane - vec[4].x = m.Get(3, 1); - vec[4].y = m.Get(3, 2); - vec[4].z = m.Get(3, 3); - originPlane[4] = m.Get(3, 4); + vec[4].x = m.Get(4, 1) + m.Get(3, 1); + vec[4].y = m.Get(4, 2) + m.Get(3, 2); + vec[4].z = m.Get(4, 3) + m.Get(3, 3); + float l5 = vec[4].Length(); + vec[4].Normalize(); + originPlane[4] = (m.Get(4, 4) + m.Get(3, 4)) / l5; // Back plane vec[5].x = m.Get(4, 1) - m.Get(3, 1); vec[5].y = m.Get(4, 2) - m.Get(3, 2); vec[5].z = m.Get(4, 3) - m.Get(3, 3); - originPlane[5] = m.Get(4, 4) - m.Get(3, 4); + float l6 = vec[5].Length(); + vec[5].Normalize(); + originPlane[5] = (m.Get(4, 4) - m.Get(3, 4)) / l6; int result = 0; if (InPlane(vec[0], originPlane[0], center, radius)) - result |= INTERSECT_PLANE_LEFT; + result |= FRUSTUM_PLANE_LEFT; if (InPlane(vec[1], originPlane[1], center, radius)) - result |= INTERSECT_PLANE_RIGHT; + result |= FRUSTUM_PLANE_RIGHT; if (InPlane(vec[2], originPlane[2], center, radius)) - result |= INTERSECT_PLANE_TOP; + result |= FRUSTUM_PLANE_BOTTOM; if (InPlane(vec[3], originPlane[3], center, radius)) - result |= INTERSECT_PLANE_BOTTOM; + result |= FRUSTUM_PLANE_TOP; if (InPlane(vec[4], originPlane[4], center, radius)) - result |= INTERSECT_PLANE_FRONT; + result |= FRUSTUM_PLANE_FRONT; if (InPlane(vec[5], originPlane[5], center, radius)) - result |= INTERSECT_PLANE_BACK; + result |= FRUSTUM_PLANE_BACK; return result; } -- cgit v1.2.3-1-g7c22 From 4811defca2eeea69e40346be6b1647f276db8c76 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 14 Dec 2012 21:30:35 +0100 Subject: Static objects using OpenGL VBOs and display lists --- src/graphics/opengl/gldevice.cpp | 222 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index a6ba1eb..2d284d0 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -73,6 +73,8 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config) { m_config = config; m_lighting = false; + m_lastVboId = 0; + m_useVbo = false; } @@ -109,6 +111,16 @@ bool CGLDevice::Create() GetLogger()->Error("GLEW reports required extensions not supported\n"); return false; } + + if (GLEW_ARB_vertex_buffer_object) + { + GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n"); + m_useVbo = true; + } + else + { + GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n"); + } } #endif @@ -174,6 +186,16 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig) Create(); } +void CGLDevice::SetUseVbo(bool useVbo) +{ + m_useVbo = useVbo; +} + +bool CGLDevice::GetUseVbo() +{ + return m_useVbo; +} + void CGLDevice::BeginScene() { Clear(); @@ -927,6 +949,206 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int glDisableClientState(GL_COLOR_ARRAY); } +unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) +{ + unsigned int id = 0; + if (m_useVbo) + { + id = ++m_lastVboId; + + VboObjectInfo info; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_NORMAL; + info.vertexCount = vertexCount; + info.bufferId = 0; + + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_vboObjects[id] = info; + } + else + { + id = glGenLists(1); + + glNewList(id, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } + + return id; +} + +unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) +{ + unsigned int id = 0; + if (m_useVbo) + { + id = ++m_lastVboId; + + VboObjectInfo info; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_TEX2; + info.vertexCount = vertexCount; + info.bufferId = 0; + + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_vboObjects[id] = info; + } + else + { + id = glGenLists(1); + + glNewList(id, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } + + return id; +} + +unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) +{ + unsigned int id = 0; + if (m_useVbo) + { + id = ++m_lastVboId; + + VboObjectInfo info; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_COL; + info.vertexCount = vertexCount; + info.bufferId = 0; + + glGenBuffers(1, &info.bufferId); + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_vboObjects[id] = info; + } + else + { + id = glGenLists(1); + + glNewList(id, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } + + return id; +} + +void CGLDevice::DrawStaticObject(unsigned int objectId) +{ + if (m_useVbo) + { + auto it = m_vboObjects.find(objectId); + if (it == m_vboObjects.end()) + return; + + glEnable(GL_VERTEX_ARRAY); + glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + + if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, coord)); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, normal)); + + glActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, texCoord)); + } + else if ((*it).second.vertexType == VERTEX_TYPE_TEX2) + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, coord)); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, normal)); + + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord)); + + glClientActiveTexture(GL_TEXTURE1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord2)); + } + else if ((*it).second.vertexType == VERTEX_TYPE_COL) + { + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, sizeof(VertexCol), static_cast(nullptr) + offsetof(VertexCol, coord)); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_FLOAT, sizeof(VertexCol), static_cast(nullptr) + offsetof(VertexCol, color)); + } + + GLenum mode = TranslateGfxPrimitive((*it).second.primitiveType); + glDrawArrays(GL_TRIANGLES, 0, (*it).second.vertexCount); + + if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) + { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE0 + } + else if ((*it).second.vertexType == VERTEX_TYPE_TEX2) + { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1 + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + else if ((*it).second.vertexType == VERTEX_TYPE_COL) + { + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glDisable(GL_VERTEX_ARRAY); + } + else + { + glCallList(objectId); + } +} + +void CGLDevice::DestroyStaticObject(unsigned int objectId) +{ + if (m_useVbo) + { + auto it = m_vboObjects.find(objectId); + if (it == m_vboObjects.end()) + return; + + glDeleteBuffers(1, &(*it).second.bufferId); + + m_vboObjects.erase(it); + } + else + { + glDeleteLists(objectId, 1); + } +} + bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius) { float distance = originPlane + Math::DotProduct(normal, center); -- cgit v1.2.3-1-g7c22 From 5574eccebd16ae38a2a21ed202d1f9d1ba8f67a4 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Wed, 26 Dec 2012 20:58:02 +0100 Subject: Engine optimization - rewritten model management - new class CModelManager - rewritten engine object structure in CEngine - created shared model data instead of separate objects per each model instance - minor refactoring --- src/graphics/opengl/gldevice.cpp | 99 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 9 deletions(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 2d284d0..c1e18d3 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -949,7 +949,7 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int glDisableClientState(GL_COLOR_ARRAY); } -unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) +unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) { unsigned int id = 0; if (m_useVbo) @@ -983,7 +983,7 @@ unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Ve return id; } -unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) +unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) { unsigned int id = 0; if (m_useVbo) @@ -1017,7 +1017,7 @@ unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Ve return id; } -unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) +unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) { unsigned int id = 0; if (m_useVbo) @@ -1051,11 +1051,92 @@ unsigned int CGLDevice::CreateStaticObject(PrimitiveType primitiveType, const Ve return id; } -void CGLDevice::DrawStaticObject(unsigned int objectId) +void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) { if (m_useVbo) { - auto it = m_vboObjects.find(objectId); + auto it = m_vboObjects.find(bufferId); + if (it == m_vboObjects.end()) + return; + + VboObjectInfo& info = (*it).second; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_NORMAL; + info.vertexCount = vertexCount; + + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(Vertex), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glNewList(bufferId, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } +} + +void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) +{ + if (m_useVbo) + { + auto it = m_vboObjects.find(bufferId); + if (it == m_vboObjects.end()) + return; + + VboObjectInfo& info = (*it).second; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_TEX2; + info.vertexCount = vertexCount; + + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexTex2), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glNewList(bufferId, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } +} + +void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) +{ + if (m_useVbo) + { + auto it = m_vboObjects.find(bufferId); + if (it == m_vboObjects.end()) + return; + + VboObjectInfo& info = (*it).second; + info.primitiveType = primitiveType; + info.vertexType = VERTEX_TYPE_COL; + info.vertexCount = vertexCount; + + glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + glBufferData(GL_ARRAY_BUFFER, vertexCount * sizeof(VertexCol), vertices, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + glNewList(bufferId, GL_COMPILE); + + DrawPrimitive(primitiveType, vertices, vertexCount); + + glEndList(); + } +} + +void CGLDevice::DrawStaticBuffer(unsigned int bufferId) +{ + if (m_useVbo) + { + auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) return; @@ -1127,15 +1208,15 @@ void CGLDevice::DrawStaticObject(unsigned int objectId) } else { - glCallList(objectId); + glCallList(bufferId); } } -void CGLDevice::DestroyStaticObject(unsigned int objectId) +void CGLDevice::DestroyStaticBuffer(unsigned int bufferId) { if (m_useVbo) { - auto it = m_vboObjects.find(objectId); + auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) return; @@ -1145,7 +1226,7 @@ void CGLDevice::DestroyStaticObject(unsigned int objectId) } else { - glDeleteLists(objectId, 1); + glDeleteLists(bufferId, 1); } } -- cgit v1.2.3-1-g7c22 From 3582f107a5e77bc12fc61e4fd99c572a5985254b Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 27 Dec 2012 14:18:16 +0100 Subject: Fixes and refactoring --- src/graphics/opengl/gldevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index c1e18d3..024a523 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -1151,7 +1151,7 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, normal)); - glActiveTexture(GL_TEXTURE0); + glClientActiveTexture(GL_TEXTURE0); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, texCoord)); } -- cgit v1.2.3-1-g7c22 From 2c0c5ddda16dd38fed39438d1e43d8e3589e8d93 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Thu, 3 Jan 2013 23:50:17 +0100 Subject: Fixed stupid debug code Terrain VBOs should work now --- src/graphics/opengl/gldevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 024a523..9460e07 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -1181,7 +1181,7 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) } GLenum mode = TranslateGfxPrimitive((*it).second.primitiveType); - glDrawArrays(GL_TRIANGLES, 0, (*it).second.vertexCount); + glDrawArrays(mode, 0, (*it).second.vertexCount); if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) { -- cgit v1.2.3-1-g7c22 From 8818a8e5db86f140230d789427373e1771747f5d Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 5 Jan 2013 23:03:06 +0100 Subject: Corrected OpenGL extension detection - corrected multitexture and VBO detection - GLEW is now a required library - minor CMakeLists refactoring --- src/graphics/opengl/gldevice.cpp | 204 +++++++++++++++++++++------------------ 1 file changed, 110 insertions(+), 94 deletions(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 9460e07..c535609 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -24,22 +24,9 @@ #include "math/geometry.h" -#if defined(USE_GLEW) - -// When using GLEW, only glew.h is needed +// Using GLEW so only glew.h is needed #include -#else - -// Should define prototypes of used extensions as OpenGL functions -#define GL_GLEXT_PROTOTYPES - -#include -#include -#include - -#endif // if defined(GLEW) - #include #include @@ -74,7 +61,8 @@ CGLDevice::CGLDevice(const GLDeviceConfig &config) m_config = config; m_lighting = false; m_lastVboId = 0; - m_useVbo = false; + m_multitextureAvailable = false; + m_vboAvailable = false; } @@ -93,7 +81,6 @@ bool CGLDevice::Create() { GetLogger()->Info("Creating CDevice\n"); -#if defined(USE_GLEW) static bool glewInited = false; if (!glewInited) @@ -106,26 +93,16 @@ bool CGLDevice::Create() return false; } - if ( (! GLEW_ARB_multitexture) || (! GLEW_EXT_texture_env_combine) ) - { - GetLogger()->Error("GLEW reports required extensions not supported\n"); - return false; - } + m_multitextureAvailable = glewIsSupported("GL_ARB_multitexture GL_ARB_texture_env_combine"); + if (!m_multitextureAvailable) + GetLogger()->Error("GLEW reports multitexturing not supported - graphics quality will be degraded!\n"); - if (GLEW_ARB_vertex_buffer_object) - { + m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object"); + if (m_vboAvailable) GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n"); - m_useVbo = true; - } else - { GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n"); - } } -#endif - - /* NOTE: when not using GLEW, extension testing is not performed, as it is assumed that - glext.h is up-to-date and the OpenGL shared library has the required functions present. */ // This is mostly done in all modern hardware by default // DirectX doesn't even allow the option to turn off perspective correction anymore @@ -135,6 +112,9 @@ bool CGLDevice::Create() // To avoid problems with scaling & lighting glEnable(GL_RESCALE_NORMAL); + // Minimal depth bias to avoid Z-fighting + SetDepthBias(0.001f); + // Set just to be sure glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glMatrixMode(GL_PROJECTION); @@ -186,14 +166,14 @@ void CGLDevice::ConfigChanged(const GLDeviceConfig& newConfig) Create(); } -void CGLDevice::SetUseVbo(bool useVbo) +void CGLDevice::SetUseVbo(bool vboAvailable) { - m_useVbo = useVbo; + m_vboAvailable = vboAvailable; } bool CGLDevice::GetUseVbo() { - return m_useVbo; + return m_vboAvailable; } void CGLDevice::BeginScene() @@ -610,7 +590,7 @@ void CGLDevice::DestroyAllTextures() m_allTextures.clear(); } -int CGLDevice::GetMaxTextureCount() +int CGLDevice::GetMaxTextureStageCount() { return m_currentTextures.size(); } @@ -621,17 +601,21 @@ int CGLDevice::GetMaxTextureCount() The setting is remembered, even if texturing is disabled at the moment. */ void CGLDevice::SetTexture(int index, const Texture &texture) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); bool same = m_currentTextures[index].id == texture.id; m_currentTextures[index] = texture; // remember the new value + if (!m_multitextureAvailable && index != 0) + return; + if (same) return; // nothing to do - glActiveTexture(GL_TEXTURE0 + index); + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0 + index); + glBindTexture(GL_TEXTURE_2D, texture.id); // Params need to be updated for the new bound texture @@ -640,15 +624,19 @@ void CGLDevice::SetTexture(int index, const Texture &texture) void CGLDevice::SetTexture(int index, unsigned int textureId) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); if (m_currentTextures[index].id == textureId) return; // nothing to do m_currentTextures[index].id = textureId; - glActiveTexture(GL_TEXTURE0 + index); + if (!m_multitextureAvailable && index != 0) + return; + + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0 + index); + glBindTexture(GL_TEXTURE_2D, textureId); // Params need to be updated for the new bound texture @@ -659,16 +647,14 @@ void CGLDevice::SetTexture(int index, unsigned int textureId) Returns the previously assigned texture or invalid texture if the given stage is not enabled. */ Texture CGLDevice::GetTexture(int index) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); return m_currentTextures[index]; } void CGLDevice::SetTextureEnabled(int index, bool enabled) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); bool same = m_texturesEnabled[index] == enabled; @@ -677,7 +663,12 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled) if (same) return; // nothing to do - glActiveTexture(GL_TEXTURE0 + index); + if (!m_multitextureAvailable && index != 0) + return; + + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0 + index); + if (enabled) glEnable(GL_TEXTURE_2D); else @@ -686,8 +677,7 @@ void CGLDevice::SetTextureEnabled(int index, bool enabled) bool CGLDevice::GetTextureEnabled(int index) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); return m_texturesEnabled[index]; } @@ -698,17 +688,36 @@ bool CGLDevice::GetTextureEnabled(int index) The settings are remembered, even if texturing is disabled at the moment. */ void CGLDevice::SetTextureStageParams(int index, const TextureStageParams ¶ms) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); // Remember the settings m_textureStageParams[index] = params; + if (!m_multitextureAvailable && index != 0) + return; + // Don't actually do anything if texture not set if (! m_currentTextures[index].Valid()) return; - glActiveTexture(GL_TEXTURE0 + index); + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0 + index); + + if (params.wrapS == TEX_WRAP_CLAMP) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + else if (params.wrapS == TEX_WRAP_REPEAT) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else assert(false); + + if (params.wrapT == TEX_WRAP_CLAMP) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + else if (params.wrapT == TEX_WRAP_REPEAT) + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else assert(false); + + // Texture env setting is silly without multitexturing + if (!m_multitextureAvailable) + return; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, params.factor.Array()); @@ -812,26 +821,12 @@ after_tex_color: glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_CONSTANT); else assert(false); - -after_tex_operations: - - if (params.wrapS == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - else if (params.wrapS == TEX_WRAP_REPEAT) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else assert(false); - - if (params.wrapT == TEX_WRAP_CLAMP) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - else if (params.wrapT == TEX_WRAP_REPEAT) - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else assert(false); +after_tex_operations: ; } void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wrapT) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); // Remember the settings m_textureStageParams[index].wrapS = wrapS; @@ -841,7 +836,11 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr if (! m_currentTextures[index].Valid()) return; - glActiveTexture(GL_TEXTURE0 + index); + if (!m_multitextureAvailable && index != 0) + return; + + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0 + index); if (wrapS == TEX_WRAP_CLAMP) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); @@ -858,8 +857,7 @@ void CGLDevice::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode wr TextureStageParams CGLDevice::GetTextureStageParams(int index) { - assert(index >= 0); - assert(index < static_cast( m_currentTextures.size() )); + assert(index >= 0 && index < static_cast( m_currentTextures.size() )); return m_textureStageParams[index]; } @@ -890,7 +888,9 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int ve glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(Vertex), reinterpret_cast(&vs[0].normal)); - glClientActiveTexture(GL_TEXTURE0); + if (m_multitextureAvailable) + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), reinterpret_cast(&vs[0].texCoord)); @@ -914,13 +914,18 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].normal)); - glClientActiveTexture(GL_TEXTURE0); + if (m_multitextureAvailable) + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord)); - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); + if (m_multitextureAvailable) + { + glClientActiveTexture(GL_TEXTURE1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), reinterpret_cast(&vs[0].texCoord2)); + } glColor4fv(color.Array()); @@ -929,8 +934,11 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, in glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1 - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + if (m_multitextureAvailable) + { + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } } void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) @@ -952,7 +960,7 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) { unsigned int id = 0; - if (m_useVbo) + if (m_vboAvailable) { id = ++m_lastVboId; @@ -986,7 +994,7 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) { unsigned int id = 0; - if (m_useVbo) + if (m_vboAvailable) { id = ++m_lastVboId; @@ -1020,7 +1028,7 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) { unsigned int id = 0; - if (m_useVbo) + if (m_vboAvailable) { id = ++m_lastVboId; @@ -1053,7 +1061,7 @@ unsigned int CGLDevice::CreateStaticBuffer(PrimitiveType primitiveType, const Ve void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) { - if (m_useVbo) + if (m_vboAvailable) { auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) @@ -1080,7 +1088,7 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) { - if (m_useVbo) + if (m_vboAvailable) { auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) @@ -1107,7 +1115,7 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) { - if (m_useVbo) + if (m_vboAvailable) { auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) @@ -1134,7 +1142,7 @@ void CGLDevice::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiv void CGLDevice::DrawStaticBuffer(unsigned int bufferId) { - if (m_useVbo) + if (m_vboAvailable) { auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) @@ -1151,7 +1159,9 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, normal)); - glClientActiveTexture(GL_TEXTURE0); + if (m_multitextureAvailable) + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), static_cast(nullptr) + offsetof(Vertex, texCoord)); } @@ -1163,13 +1173,18 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, normal)); - glClientActiveTexture(GL_TEXTURE0); + if (m_multitextureAvailable) + glClientActiveTexture(GL_TEXTURE0); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord)); - glClientActiveTexture(GL_TEXTURE1); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord2)); + if (m_multitextureAvailable) + { + glClientActiveTexture(GL_TEXTURE1); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, sizeof(VertexTex2), static_cast(nullptr) + offsetof(VertexTex2, texCoord2)); + } } else if ((*it).second.vertexType == VERTEX_TYPE_COL) { @@ -1194,8 +1209,11 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); // GL_TEXTURE1 - glClientActiveTexture(GL_TEXTURE0); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + if (m_multitextureAvailable) + { + glClientActiveTexture(GL_TEXTURE0); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } } else if ((*it).second.vertexType == VERTEX_TYPE_COL) { @@ -1214,7 +1232,7 @@ void CGLDevice::DrawStaticBuffer(unsigned int bufferId) void CGLDevice::DestroyStaticBuffer(unsigned int bufferId) { - if (m_useVbo) + if (m_vboAvailable) { auto it = m_vboObjects.find(bufferId); if (it == m_vboObjects.end()) @@ -1355,7 +1373,6 @@ void CGLDevice::SetRenderState(RenderState state, bool enabled) case RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break; case RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break; case RENDER_STATE_CULLING: flag = GL_CULL_FACE; break; - case RENDER_STATE_DITHERING: flag = GL_DITHER; break; default: assert(false); break; } @@ -1380,7 +1397,6 @@ bool CGLDevice::GetRenderState(RenderState state) case RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break; case RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break; case RENDER_STATE_CULLING: flag = GL_CULL_FACE; break; - case RENDER_STATE_DITHERING: flag = GL_DITHER; break; default: assert(false); break; } -- cgit v1.2.3-1-g7c22 From edb1c0cbd62bfe7c620d7c8399f49acb98994b85 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 6 Jan 2013 23:13:05 +0100 Subject: GLEW fix for some graphics drivers --- src/graphics/opengl/gldevice.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index c535609..80fa9a1 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -87,6 +87,8 @@ bool CGLDevice::Create() { glewInited = true; + glewExperimental = GL_TRUE; + if (glewInit() != GLEW_OK) { GetLogger()->Error("GLEW initialization failed\n"); @@ -95,7 +97,7 @@ bool CGLDevice::Create() m_multitextureAvailable = glewIsSupported("GL_ARB_multitexture GL_ARB_texture_env_combine"); if (!m_multitextureAvailable) - GetLogger()->Error("GLEW reports multitexturing not supported - graphics quality will be degraded!\n"); + GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n"); m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object"); if (m_vboAvailable) @@ -415,7 +417,9 @@ Texture CGLDevice::CreateTexture(ImageData *data, const TextureCreateParams &par result.size.y = data->surface->h; // Use & enable 1st texture stage - glActiveTexture(GL_TEXTURE0); + if (m_multitextureAvailable) + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_2D); glGenTextures(1, &result.id); -- cgit v1.2.3-1-g7c22 From bc859c4c597f106d40f07380bf255f180d565577 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sun, 10 Mar 2013 15:44:21 +0100 Subject: VBO override option; argv parsing using getopt * added -vbo option to override autodetection of OpenGL VBO extension * refactored argument parsing to use getopt() * fixed failing UTs --- src/graphics/opengl/gldevice.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 80fa9a1..beeb85e 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -51,6 +51,8 @@ void GLDeviceConfig::LoadDefault() greenSize = 8; alphaSize = 8; depthSize = 24; + + vboMode = VBO_MODE_AUTO; } @@ -99,11 +101,26 @@ bool CGLDevice::Create() if (!m_multitextureAvailable) GetLogger()->Warn("GLEW reports multitexturing not supported - graphics quality will be degraded!\n"); - m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object"); - if (m_vboAvailable) - GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n"); + if (m_config.vboMode == VBO_MODE_ENABLE) + { + GetLogger()->Info("VBO enabled by override - using VBOs\n"); + m_vboAvailable = true; + } + else if (m_config.vboMode == VBO_MODE_DISABLE) + { + GetLogger()->Info("VBO disabled by override - using display lists\n"); + m_vboAvailable = false; + } else - GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n"); + { + GetLogger()->Info("Auto-detecting VBO support\n"); + m_vboAvailable = glewIsSupported("GL_ARB_vertex_buffer_object"); + + if (m_vboAvailable) + GetLogger()->Info("Detected ARB_vertex_buffer_object extension - using VBOs\n"); + else + GetLogger()->Info("No ARB_vertex_buffer_object extension present - using display lists\n"); + } } // This is mostly done in all modern hardware by default -- cgit v1.2.3-1-g7c22 From 4a30800cf16d403a7c25d78388e2822aa396ac86 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Fri, 22 Mar 2013 18:19:53 +0100 Subject: Fixes for compiling on MSYS * fixed SDL_main() and putenv() issues * disabled desktop subdir for MSYS * disabled building CBot_console for now --- src/graphics/opengl/gldevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/graphics/opengl/gldevice.cpp') diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index beeb85e..df64e34 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -27,7 +27,7 @@ // Using GLEW so only glew.h is needed #include -#include +#include #include -- cgit v1.2.3-1-g7c22