This is an automated email from the git hooks/post-receive script. odyx pushed a commit to branch upstream/latest in repository colobot.
commit a0c56f54cb3bc1c3d29b37daa8fdbeda6e52bbaa Author: Tomasz Kapuściński <[email protected]> Date: Mon Jun 1 17:21:10 2015 +0200 Shader and buffer optimizations --- src/graphics/opengl/gl21device.cpp | 189 +++++++++++----------------------- src/graphics/opengl/gl21device.h | 9 +- src/graphics/opengl/gl33device.cpp | 202 ++++++++++--------------------------- src/graphics/opengl/gl33device.h | 9 ++ src/graphics/opengl/glutil.cpp | 78 ++++++++++++++ src/graphics/opengl/glutil.h | 4 + 6 files changed, 211 insertions(+), 280 deletions(-) diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index c4a6067..528d781 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -261,10 +261,9 @@ bool CGL21Device::Create() else CLogger::GetInstance().Info("Using per-vertex lighting\n"); - // Create shader program - GLchar source[65536]; - const GLchar *sources[] = { source }; + // Create normal shader program + GLint shaders[2]; char filename[128]; if (m_perPixelLighting) @@ -272,147 +271,65 @@ bool CGL21Device::Create() else sprintf(filename, "shaders/vertex_shader_21_pervertex.glsl"); - PHYSFS_file *file = PHYSFS_openRead(filename); - if (file == nullptr) - { - CLogger::GetInstance().Error("Cannot read vertex shader code file!\n"); - CLogger::GetInstance().Error("Missing file \"%s\"\n", filename); - return false; - } - - int length = PHYSFS_read(file, source, 1, 65536); - source[length] = '\0'; - - PHYSFS_close(file); - - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, sources, nullptr); - glCompileShader(vertexShader); - - GLint status; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &len); - - GLchar *message = new GLchar[len + 1]; - glGetShaderInfoLog(vertexShader, len + 1, nullptr, message); - - GetLogger()->Error("Vertex shader compilation error occured!\n%s\n", message); - - delete[] message; - return false; - } + shaders[0] = LoadShader(GL_VERTEX_SHADER, filename); + if (shaders[0] == 0) return false; if (m_perPixelLighting) sprintf(filename, "shaders/fragment_shader_21_perpixel.glsl"); else sprintf(filename, "shaders/fragment_shader_21_pervertex.glsl"); - file = PHYSFS_openRead(filename); - if (file == nullptr) - { - CLogger::GetInstance().Error("Cannot read fragment shader code file!\n"); - CLogger::GetInstance().Error("Missing file \"%s\"\n", filename); - return false; - } - - length = PHYSFS_read(file, source, 1, 65536); - source[length] = '\0'; - - PHYSFS_close(file); - - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, sources, nullptr); - glCompileShader(fragmentShader); - - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &len); - - GLchar *message = new GLchar[len + 1]; - glGetShaderInfoLog(fragmentShader, len + 1, nullptr, message); - - GetLogger()->Error("Fragment shader compilation error occured!\n%s\n", message); - - delete[] message; - return false; - } - - m_shaderProgram = glCreateProgram(); - glAttachShader(m_shaderProgram, vertexShader); - glAttachShader(m_shaderProgram, fragmentShader); + shaders[1] = LoadShader(GL_FRAGMENT_SHADER, filename); + if (shaders[1] == 0) return false; - glLinkProgram(m_shaderProgram); + m_program = LinkProgram(2, shaders); + if (m_program == 0) return false; - glDetachShader(m_shaderProgram, vertexShader); - glDetachShader(m_shaderProgram, fragmentShader); + glDeleteShader(shaders[0]); + glDeleteShader(shaders[1]); - glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetProgramiv(m_shaderProgram, GL_INFO_LOG_LENGTH, &len); - - GLchar *message = new GLchar[len + 1]; - glGetProgramInfoLog(m_shaderProgram, len + 1, nullptr, message); - - GetLogger()->Error("Shader program linking error occured!\n%s\n", message); - - delete[] message; - return false; - } - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); - - glUseProgram(m_shaderProgram); // Obtain uniform locations - uni_ProjectionMatrix = glGetUniformLocation(m_shaderProgram, "uni_ProjectionMatrix"); - uni_ViewMatrix = glGetUniformLocation(m_shaderProgram, "uni_ViewMatrix"); - uni_ModelMatrix = glGetUniformLocation(m_shaderProgram, "uni_ModelMatrix"); - uni_NormalMatrix = glGetUniformLocation(m_shaderProgram, "uni_NormalMatrix"); - uni_ShadowMatrix = glGetUniformLocation(m_shaderProgram, "uni_ShadowMatrix"); + uni_ProjectionMatrix = glGetUniformLocation(m_program, "uni_ProjectionMatrix"); + uni_ViewMatrix = glGetUniformLocation(m_program, "uni_ViewMatrix"); + uni_ModelMatrix = glGetUniformLocation(m_program, "uni_ModelMatrix"); + uni_NormalMatrix = glGetUniformLocation(m_program, "uni_NormalMatrix"); + uni_ShadowMatrix = glGetUniformLocation(m_program, "uni_ShadowMatrix"); - uni_PrimaryTexture = glGetUniformLocation(m_shaderProgram, "uni_PrimaryTexture"); - uni_SecondaryTexture = glGetUniformLocation(m_shaderProgram, "uni_SecondaryTexture"); - uni_ShadowTexture = glGetUniformLocation(m_shaderProgram, "uni_ShadowTexture"); + uni_PrimaryTexture = glGetUniformLocation(m_program, "uni_PrimaryTexture"); + uni_SecondaryTexture = glGetUniformLocation(m_program, "uni_SecondaryTexture"); + uni_ShadowTexture = glGetUniformLocation(m_program, "uni_ShadowTexture"); for (int i = 0; i < 3; i++) { char name[64]; sprintf(name, "uni_TextureEnabled[%d]", i); - uni_TextureEnabled[i] = glGetUniformLocation(m_shaderProgram, name); + uni_TextureEnabled[i] = glGetUniformLocation(m_program, name); } - uni_AlphaTestEnabled = glGetUniformLocation(m_shaderProgram, "uni_AlphaTestEnabled"); - uni_AlphaReference = glGetUniformLocation(m_shaderProgram, "uni_AlphaReference"); + uni_AlphaTestEnabled = glGetUniformLocation(m_program, "uni_AlphaTestEnabled"); + uni_AlphaReference = glGetUniformLocation(m_program, "uni_AlphaReference"); - uni_FogEnabled = glGetUniformLocation(m_shaderProgram, "uni_FogEnabled"); - uni_FogRange = glGetUniformLocation(m_shaderProgram, "uni_FogRange"); - uni_FogColor = glGetUniformLocation(m_shaderProgram, "uni_FogColor"); + uni_FogEnabled = glGetUniformLocation(m_program, "uni_FogEnabled"); + uni_FogRange = glGetUniformLocation(m_program, "uni_FogRange"); + uni_FogColor = glGetUniformLocation(m_program, "uni_FogColor"); - uni_ShadowColor = glGetUniformLocation(m_shaderProgram, "uni_ShadowColor"); - uni_LightingEnabled = glGetUniformLocation(m_shaderProgram, "uni_LightingEnabled"); + uni_ShadowColor = glGetUniformLocation(m_program, "uni_ShadowColor"); + uni_LightingEnabled = glGetUniformLocation(m_program, "uni_LightingEnabled"); for (int i = 0; i < 8; i++) { char name[64]; sprintf(name, "uni_LightEnabled[%d]", i); - uni_LightEnabled[i] = glGetUniformLocation(m_shaderProgram, name); + uni_LightEnabled[i] = glGetUniformLocation(m_program, name); } // Set default uniform values Math::Matrix matrix; matrix.LoadIdentity(); + glUseProgram(m_program); + glUniformMatrix4fv(uni_ProjectionMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni_ViewMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni_ModelMatrix, 1, GL_FALSE, matrix.Array()); @@ -447,7 +364,7 @@ void CGL21Device::Destroy() // Delete the remaining textures // Should not be strictly necessary, but just in case glUseProgram(0); - glDeleteProgram(m_shaderProgram); + glDeleteProgram(m_program); DestroyAllTextures(); @@ -489,6 +406,7 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) if (type == TRANSFORM_WORLD) { m_worldMat = matrix; + glUniformMatrix4fv(uni_ModelMatrix, 1, GL_FALSE, m_worldMat.Array()); // normal transform @@ -503,11 +421,13 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) Math::Matrix scale; Math::LoadScaleMatrix(scale, Math::Vector(1.0f, 1.0f, -1.0f)); Math::Matrix temp = Math::MultiplyMatrices(scale, matrix); + glUniformMatrix4fv(uni_ViewMatrix, 1, GL_FALSE, temp.Array()); } else if (type == TRANSFORM_PROJECTION) { m_projectionMat = matrix; + glUniformMatrix4fv(uni_ProjectionMatrix, 1, GL_FALSE, m_projectionMat.Array()); } else if (type == TRANSFORM_SHADOW) @@ -967,6 +887,14 @@ void CGL21Device::UpdateTextureStatus() */ } +inline void CGL21Device::BindVBO(GLint vbo) +{ + if (m_currentVBO == vbo) return; + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + m_currentVBO = vbo; +} + /** Sets the texture parameters for the given texture stage. If the given texture was not set (bound) yet, nothing happens. @@ -1222,6 +1150,8 @@ void CGL21Device::SetTextureStageWrap(int index, TexWrapMode wrapS, TexWrapMode void CGL21Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int vertexCount, Color color) { + BindVBO(0); + Vertex* vs = const_cast<Vertex*>(vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -1247,6 +1177,8 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, Color color) { + BindVBO(0); + VertexTex2* vs = const_cast<VertexTex2*>(vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -1278,6 +1210,8 @@ void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, void CGL21Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) { + BindVBO(0); + VertexCol* vs = const_cast<VertexCol*>(vertices); glEnableClientState(GL_VERTEX_ARRAY); @@ -1304,9 +1238,8 @@ unsigned int CGL21Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(Vertex); glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + BindVBO(info.bufferId); glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); m_vboObjects[id] = info; @@ -1325,9 +1258,8 @@ unsigned int CGL21Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(VertexTex2); glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + BindVBO(info.bufferId); glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); m_vboObjects[id] = info; @@ -1346,9 +1278,8 @@ unsigned int CGL21Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(VertexCol); glGenBuffers(1, &info.bufferId); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + BindVBO(info.bufferId); glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); m_vboObjects[id] = info; @@ -1368,7 +1299,7 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit info.vertexType = VERTEX_TYPE_NORMAL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + BindVBO(info.bufferId); if (info.size < newSize) { @@ -1379,8 +1310,6 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit { glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, vertices); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) @@ -1395,8 +1324,8 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit info.vertexCount = vertexCount; int newSize = vertexCount * sizeof(VertexTex2); - - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + + BindVBO(info.bufferId); if (info.size < newSize) { @@ -1407,8 +1336,6 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit { glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, vertices); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) @@ -1424,7 +1351,7 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit int newSize = vertexCount * sizeof(VertexCol); - glBindBuffer(GL_ARRAY_BUFFER, info.bufferId); + BindVBO(info.bufferId); if (info.size < newSize) { @@ -1435,8 +1362,6 @@ void CGL21Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit { glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, vertices); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL21Device::DrawStaticBuffer(unsigned int bufferId) @@ -1446,7 +1371,7 @@ void CGL21Device::DrawStaticBuffer(unsigned int bufferId) return; glEnable(GL_VERTEX_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, (*it).second.bufferId); + BindVBO((*it).second.bufferId); if ((*it).second.vertexType == VERTEX_TYPE_NORMAL) { @@ -1510,7 +1435,6 @@ void CGL21Device::DrawStaticBuffer(unsigned int bufferId) glDisableClientState(GL_COLOR_ARRAY); } - glBindBuffer(GL_ARRAY_BUFFER, 0); glDisable(GL_VERTEX_ARRAY); } @@ -1520,6 +1444,9 @@ void CGL21Device::DestroyStaticBuffer(unsigned int bufferId) if (it == m_vboObjects.end()) return; + if (m_currentVBO == (*it).second.bufferId) + BindVBO(0); + glDeleteBuffers(1, &(*it).second.bufferId); m_vboObjects.erase(it); diff --git a/src/graphics/opengl/gl21device.h b/src/graphics/opengl/gl21device.h index 2f3dfa1..36d8c7b 100644 --- a/src/graphics/opengl/gl21device.h +++ b/src/graphics/opengl/gl21device.h @@ -152,6 +152,8 @@ private: void UpdateTextureParams(int index); //! Updates texture status void UpdateTextureStatus(); + //! Binds VBO + inline void BindVBO(GLint vbo); private: //! Current config @@ -217,6 +219,8 @@ private: std::map<unsigned int, VboObjectInfo> m_vboObjects; //! Last ID of VBO object unsigned int m_lastVboId; + //! Currently bound VBO + GLint m_currentVBO; // Offscreen buffer //! Framebuffer object @@ -230,11 +234,12 @@ private: //! true if offscreen rendering enabled bool m_offscreenRenderingEnabled; - //! Shader program - GLuint m_shaderProgram; //! true enables per-pixel lighting bool m_perPixelLighting; + //! Shader program + GLuint m_program; + // Uniforms //! Projection matrix GLint uni_ProjectionMatrix; diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index a4f31b6..bd31808 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -263,9 +263,7 @@ bool CGL33Device::Create() CLogger::GetInstance().Info("Using per-vertex lighting\n"); // Create shader program - GLchar source[65536]; - const GLchar *sources[] = { source }; - + GLint shaders[2]; char filename[64]; if (m_perPixelLighting) @@ -273,105 +271,22 @@ bool CGL33Device::Create() else sprintf(filename, "shaders/vertex_shader_33_pervertex.glsl"); - PHYSFS_file *file = PHYSFS_openRead(filename); - if (file == nullptr) - { - CLogger::GetInstance().Error("Cannot read vertex shader code file!\n"); - CLogger::GetInstance().Error("Missing file \"%s\"\n", filename); - return false; - } - - int length = PHYSFS_read(file, source, 1, 65536); - source[length] = '\0'; - - PHYSFS_close(file); - - GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertexShader, 1, sources, nullptr); - glCompileShader(vertexShader); - - GLint status; - glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &len); - - GLchar *message = new GLchar[len + 1]; - glGetShaderInfoLog(vertexShader, len + 1, nullptr, message); - - GetLogger()->Error("Vertex shader compilation error occured!\n%s\n", message); - - delete[] message; - return false; - } + shaders[0] = LoadShader(GL_VERTEX_SHADER, filename); + if (shaders[0] == 0) return false; if (m_perPixelLighting) sprintf(filename, "shaders/fragment_shader_33_perpixel.glsl"); else sprintf(filename, "shaders/fragment_shader_33_pervertex.glsl"); - file = PHYSFS_openRead(filename); - if (file == nullptr) - { - CLogger::GetInstance().Error("Cannot read fragment shader code file!\n"); - CLogger::GetInstance().Error("Missing file \"%s\"\n", filename); - return false; - } - - length = PHYSFS_read(file, source, 1, 65536); - source[length] = '\0'; - - PHYSFS_close(file); - - GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragmentShader, 1, sources, nullptr); - glCompileShader(fragmentShader); - - glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &len); - - GLchar *message = new GLchar[len + 1]; - glGetShaderInfoLog(fragmentShader, len + 1, nullptr, message); - - GetLogger()->Error("Fragment shader compilation error occured!\n%s\n", message); + shaders[1] = LoadShader(GL_FRAGMENT_SHADER, filename); + if (shaders[1] == 0) return false; - delete[] message; - return false; - } - - m_shaderProgram = glCreateProgram(); - glAttachShader(m_shaderProgram, vertexShader); - glAttachShader(m_shaderProgram, fragmentShader); - - glLinkProgram(m_shaderProgram); - - glDetachShader(m_shaderProgram, vertexShader); - glDetachShader(m_shaderProgram, fragmentShader); - - glGetProgramiv(m_shaderProgram, GL_LINK_STATUS, &status); - - if (status != GL_TRUE) - { - GLint len; - glGetProgramiv(m_shaderProgram, GL_INFO_LOG_LENGTH, &len); + m_shaderProgram = LinkProgram(2, shaders); + if (m_shaderProgram == 0) return false; - GLchar *message = new GLchar[len + 1]; - glGetProgramInfoLog(m_shaderProgram, len + 1, nullptr, message); - - GetLogger()->Error("Shader program linking error occured!\n%s\n", message); - - delete[] message; - return false; - } - - glDeleteShader(vertexShader); - glDeleteShader(fragmentShader); + glDeleteShader(shaders[0]); + glDeleteShader(shaders[1]); glUseProgram(m_shaderProgram); @@ -1245,8 +1160,8 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int unsigned int size = vertexCount * sizeof(Vertex); - glBindVertexArray(info.vao); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVAO(info.vao); + BindVBO(info.vbo); // If needed vertex data is too large, increase the size of buffer if (info.size >= size) @@ -1285,9 +1200,6 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const Vertex *vertices, int UpdateRenderingMode(); glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); } void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, int vertexCount, Color color) @@ -1297,8 +1209,8 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, unsigned int size = vertexCount * sizeof(VertexTex2); - glBindVertexArray(info.vao); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVAO(info.vao); + BindVBO(info.vbo); // If needed vertex data is too large, increase the size of buffer if (info.size >= size) @@ -1337,9 +1249,6 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexTex2 *vertices, UpdateRenderingMode(); glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); } void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int vertexCount) @@ -1349,8 +1258,8 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i unsigned int size = vertexCount * sizeof(VertexCol); - glBindVertexArray(info.vao); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVAO(info.vao); + BindVBO(info.vbo); // If needed vertex data is too large, increase the size of buffer if (info.size >= size) @@ -1387,9 +1296,6 @@ void CGL33Device::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, i UpdateRenderingMode(); glDrawArrays(TranslateGfxPrimitive(type), 0, vertexCount); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); } unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const Vertex* vertices, int vertexCount) @@ -1405,10 +1311,11 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(Vertex); glGenVertexArrays(1, &info.vao); - glBindVertexArray(info.vao); + BindVAO(info.vao); glGenBuffers(1, &info.vbo); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVBO(info.vbo); + glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); // Vertex coordinate @@ -1431,9 +1338,6 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const glDisableVertexAttribArray(4); glVertexAttrib2f(4, 0.0f, 0.0f); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - m_vboObjects[id] = info; return id; @@ -1452,10 +1356,11 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(VertexTex2); glGenVertexArrays(1, &info.vao); - glBindVertexArray(info.vao); + BindVAO(info.vao); glGenBuffers(1, &info.vbo); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVBO(info.vbo); + glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); // Vertex coordinate @@ -1478,9 +1383,6 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const glEnableVertexAttribArray(4); glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), reinterpret_cast<void*>(offsetof(VertexTex2, texCoord2))); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - m_vboObjects[id] = info; return id; @@ -1497,10 +1399,11 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const info.size = vertexCount * sizeof(VertexCol); glGenVertexArrays(1, &info.vao); - glBindVertexArray(info.vao); + BindVAO(info.vao); glGenBuffers(1, &info.vbo); - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVBO(info.vbo); + glBufferData(GL_ARRAY_BUFFER, info.size, vertices, GL_STATIC_DRAW); // Vertex coordinate @@ -1523,9 +1426,6 @@ unsigned int CGL33Device::CreateStaticBuffer(PrimitiveType primitiveType, const glDisableVertexAttribArray(4); glVertexAttrib2f(4, 0.0f, 0.0f); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - m_vboObjects[id] = info; return id; @@ -1547,7 +1447,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit info.vertexType = VERTEX_TYPE_NORMAL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVBO(info.vbo); if (info.size < size) { @@ -1562,7 +1462,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit if (changed) // Update vertex array bindings { - glBindVertexArray(info.vao); + BindVAO(info.vao); // Vertex coordinate glEnableVertexAttribArray(0); @@ -1583,11 +1483,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit // Texture coordinate 1 glDisableVertexAttribArray(4); glVertexAttrib2f(4, 0.0f, 0.0f); - - glBindVertexArray(0); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexTex2* vertices, int vertexCount) @@ -1605,7 +1501,8 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit info.primitiveType = primitiveType; info.vertexType = VERTEX_TYPE_TEX2; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + + BindVBO(info.vbo); if (info.size < size) { @@ -1620,7 +1517,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit if (changed) // Update vertex array bindings { - glBindVertexArray(info.vao); + BindVAO(info.vao); // Vertex coordinate glEnableVertexAttribArray(0); @@ -1641,11 +1538,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit // Texture coordinate 1 glEnableVertexAttribArray(4); glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(VertexTex2), reinterpret_cast<void*>(offsetof(VertexTex2, texCoord2))); - - glBindVertexArray(0); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primitiveType, const VertexCol* vertices, int vertexCount) @@ -1664,7 +1557,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit info.vertexType = VERTEX_TYPE_COL; info.vertexCount = vertexCount; - glBindBuffer(GL_ARRAY_BUFFER, info.vbo); + BindVBO(info.vbo); if (info.size < size) { @@ -1679,7 +1572,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit if (changed) // Update vertex array bindings { - glBindVertexArray(info.vao); + BindVAO(info.vao); // Vertex coordinate glEnableVertexAttribArray(0); @@ -1700,11 +1593,7 @@ void CGL33Device::UpdateStaticBuffer(unsigned int bufferId, PrimitiveType primit // Texture coordinate 1 glDisableVertexAttribArray(4); glVertexAttrib2f(4, 0.0f, 0.0f); - - glBindVertexArray(0); } - - glBindBuffer(GL_ARRAY_BUFFER, 0); } void CGL33Device::DrawStaticBuffer(unsigned int bufferId) @@ -1717,12 +1606,10 @@ void CGL33Device::DrawStaticBuffer(unsigned int bufferId) UpdateRenderingMode(); - glBindVertexArray(info.vao); + BindVAO(info.vao); GLenum mode = TranslateGfxPrimitive(info.primitiveType); glDrawArrays(mode, 0, info.vertexCount); - - glBindVertexArray(0); } void CGL33Device::DestroyStaticBuffer(unsigned int bufferId) @@ -1733,6 +1620,11 @@ void CGL33Device::DestroyStaticBuffer(unsigned int bufferId) VertexBufferInfo &info = (*it).second; + if (m_currentVAO == info.vao) + BindVAO(0); + if (m_currentVBO == info.vbo) + BindVBO(0); + glDeleteBuffers(1, &info.vbo); glDeleteVertexArrays(1, &info.vao); @@ -1846,9 +1738,9 @@ void CGL33Device::SetRenderState(RenderState state, bool enabled) else if (state == RENDER_STATE_OFFSCREEN_RENDERING) { if (m_framebuffer == 0) - InitOffscreenBuffer(2048, 2048); + InitOffscreenBuffer(1024, 1024); - m_offscreenRenderingEnabled = true; + m_offscreenRenderingEnabled = enabled; GLuint toBind = (enabled ? m_framebuffer : 0); @@ -2077,4 +1969,20 @@ void CGL33Device::UpdateRenderingMode() glUniform1i(uni_ShadowTextureEnabled, enabled ? 1 : 0); } +inline void CGL33Device::BindVBO(GLint vbo) +{ + if (m_currentVBO == vbo) return; + + glBindBuffer(GL_ARRAY_BUFFER, vbo); + m_currentVBO = vbo; +} + +inline void CGL33Device::BindVAO(GLint vao) +{ + if (m_currentVAO == vao) return; + + glBindVertexArray(vao); + m_currentVAO = vao; +} + } // namespace Gfx diff --git a/src/graphics/opengl/gl33device.h b/src/graphics/opengl/gl33device.h index 2d0f8ab..479b5bb 100644 --- a/src/graphics/opengl/gl33device.h +++ b/src/graphics/opengl/gl33device.h @@ -151,6 +151,11 @@ private: //! Updates rendering mode void UpdateRenderingMode(); + //! Binds VBO + inline void BindVBO(GLint vbo); + //! Binds VAO + inline void BindVAO(GLint vao); + private: //! Current config GLDeviceConfig m_config; @@ -214,6 +219,10 @@ private: std::map<unsigned int, VertexBufferInfo> m_vboObjects; //! Last ID of VBO object unsigned int m_lastVboId; + //! Currently bound VBO + GLint m_currentVBO; + //! Currently bound VAO + GLint m_currentVAO; // Offscreen buffer //! Framebuffer object diff --git a/src/graphics/opengl/glutil.cpp b/src/graphics/opengl/glutil.cpp index fd03b33..2465c5c 100644 --- a/src/graphics/opengl/glutil.cpp +++ b/src/graphics/opengl/glutil.cpp @@ -18,6 +18,8 @@ */ #include "graphics/opengl/glutil.h" +#include "common/logger.h" +#include <physfs.h> // Graphics module namespace namespace Gfx { @@ -159,4 +161,80 @@ GLenum TranslateTextureCoordinateGen(int index) return textureCoordGen[index]; } +GLint LoadShader(GLint type, const char* filename) +{ + PHYSFS_file *file = PHYSFS_openRead(filename); + if (file == nullptr) + { + CLogger::GetInstance().Error("Cannot read shader source file\n"); + CLogger::GetInstance().Error("Missing file \"%s\"\n", filename); + return 0; + } + + char source[65536]; + char *sources[] = { source }; + int length = PHYSFS_read(file, source, 1, 65536); + source[length] = '\0'; + + PHYSFS_close(file); + + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, sources, nullptr); + glCompileShader(shader); + + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + if (status != GL_TRUE) + { + GLint len; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len); + + GLchar *message = new GLchar[len + 1]; + glGetShaderInfoLog(shader, len + 1, nullptr, message); + + GetLogger()->Error("Shader compilation error occured!\n%s\n", message); + + delete[] message; + glDeleteShader(shader); + return 0; + } + + return shader; +} + +GLint LinkProgram(int count, GLint shaders[]) +{ + GLint program = glCreateProgram(); + + for (int i = 0; i < count; i++) + glAttachShader(program, shaders[i]); + + glLinkProgram(program); + + for (int i = 0; i < count; i++) + glDetachShader(program, shaders[i]); + + GLint status; + glGetProgramiv(program, GL_LINK_STATUS, &status); + + if (status != GL_TRUE) + { + GLint len; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &len); + + GLchar *message = new GLchar[len + 1]; + glGetProgramInfoLog(program, len + 1, nullptr, message); + + GetLogger()->Error("Shader program linking error occured!\n%s\n", message); + + delete[] message; + glDeleteProgram(program); + + return 0; + } + + return program; +} + } diff --git a/src/graphics/opengl/glutil.h b/src/graphics/opengl/glutil.h index b0f0606..54086ec 100644 --- a/src/graphics/opengl/glutil.h +++ b/src/graphics/opengl/glutil.h @@ -88,4 +88,8 @@ GLenum TranslateTextureCoordinate(int index); GLenum TranslateTextureCoordinateGen(int index); +GLint LoadShader(GLint type, const char* filename); + +GLint LinkProgram(int count, GLint shaders[]); + } // namespace Gfx -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/colobot.git _______________________________________________ Pkg-games-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-games-commits

