[colobot] 379/390: Shader and buffer optimizations
Didier Raboud
odyx at moszumanska.debian.org
Fri Jun 12 14:22:07 UTC 2015
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 <tomaszkax86 at gmail.com>
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
More information about the Pkg-games-commits
mailing list