Hi everyone,
I have an issue where my geometry color would flicker from red to black. I narrowed the issue down to it being caused by my Uniform Buffers, but for the life of me I cannot figure out why its happening.
So I have two Uniform Buffers. One for my camera matrices and the other is for my material colors.
This is my first buffer, the camera buffer and this is how it looks like
struct SystemBuffer
{
BF::Math::Matrix4 modelMatrix; // 0 + 4 bytes * 4 floats * 4 vector4 = 64 byte
BF::Math::Matrix4 viewMatrix; // 64 + 4 bytes * 4 floats * 4 vector4 = 128 byte
BF::Math::Matrix4 projectionMatrix; // 128 + 4 bytes * 4 floats * 4 vector4 = 192 byte
BF::Math::Vector4f cameraPosition; // 192 + 4 bytes * 4 floats = 208 byte
};
This is 208 bytes and is aligned perfectly for OpenGL std140 as far as I know.
This is my second buffer, the material buffer and this is how it looks like
struct ColorBuffer
{
Color ambientColor; // 0 + 4 bytes * 4 floats = 16 byte
Color diffuseColor; // 16 + 4 bytes * 4 floats = 32 byte
Color specularColor; // 32 + 4 bytes * 4 floats = 48 byte
float shininess = 0.0f; // 48 + 4 bytes = 52 byte
};
This is 52 bytes and is also aligned perfectly for OpenGL std140 as far as I know.
My issue is that if I remove the shininess variable from my color buffer, my geometry does not flicker to black at all and the problem is solved the flickering is reduced a lot but still does not get better. However, when I add that variable back it goes back to flickering. I tried to add padding as in add 3 more floats under the shininess variable to make my ColorBuffer a multiple of 16 bytes but that did not help at all.
This is how my uniform buffer class looks like
namespace BF
{
namespace Platform
{
namespace API
{
namespace OpenGL
{
GLConstantBuffer::GLConstantBuffer() :
buffer(0), bindingIndex(0)
{
}
GLConstantBuffer::~GLConstantBuffer()
{
GLCall(glDeleteBuffers(1, &buffer));
}
void GLConstantBuffer::Create(unsigned int size, unsigned int bindingIndex)
{
this->bindingIndex = bindingIndex;
GLCall(glGenBuffers(1, &buffer));
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindingIndex, buffer));
GLCall(glBufferData(GL_UNIFORM_BUFFER, size, nullptr, GL_STATIC_DRAW));
GLCall(glBindBuffer(GL_UNIFORM_BUFFER, 0));
}
void GLConstantBuffer::Update(const void* data, unsigned int size)
{
GLCall(glBindBufferBase(GL_UNIFORM_BUFFER, bindingIndex, buffer));
GLCall(glBufferSubData(GL_UNIFORM_BUFFER, 0, size, data));
GLCall(glBindBuffer(GL_UNIFORM_BUFFER, 0));
}
}
}
}
}
This is my usage for the buffers
void Camera::Initialize()
{
constantBuffer.Create(sizeof(SystemBuffer), 0);
}
void Camera::Update()
{
constantBuffer.Update(&systemBuffer, sizeof(SystemBuffer));
}
//------
void ForwardRenderer::Initialize()
{
materialConstantBuffer.Create(sizeof(MeshMaterial::ColorBuffer), 2);
}
void ForwardRenderer::Render()
{
// clear depth + color buffers
for (size_t i = 0; i < meshes.size(); i++)
{
//transform meshe
constantBuffer.Update(&systemBuffer, sizeof(SystemBuffer));
materialConstantBuffer.Update(&meshes[i]->material->colorBuffer, sizeof(MeshMaterial::ColorBuffer));
//draw
}
}
and this is how my shader looks like
vertexShader = R"(
#version 450 core
layout(location = 0) in vec3 inPosition;
layout (std140, binding = 0) uniform camera_data
{
mat4 buffer_modelMatrix;
mat4 buffer_viewMatrix;
mat4 buffer_projectionMatrix;
vec4 cameraPos;
};
void main()
{
vec4 worldSpace = buffer_modelMatrix * vec4(inPosition.xyz, 1.0f);
gl_Position = buffer_projectionMatrix * buffer_viewMatrix * worldSpace;
}
)";
pixelShader = R"(
#version 450 core
struct Material
{
vec4 ambientColor;
vec4 diffuseColor;
vec4 specularColor;
float shininess;
};
layout (std140, binding = 2) uniform MaterialUniform
{
Material material;
};
out vec4 color;
void main()
{
color = material.ambientColor * material.diffuseColor * material.specularColor;
}
)";
All these planes will flicker randomly to black then back to red.
Any help would be greatly appreciated.