0
\$\begingroup\$

I have two separate UBO's for different types of lights (for a light stage in a deferred rendering system).

These are defined as follows:

//Pointlight UBO
m_pointLightBlockIndex = glGetUniformBlockIndex(shader.getShaderHandle(), "PointLights");
glGetActiveUniformBlockiv(shader.getShaderHandle(), m_pointLightBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &m_PointLightBlockSize);
glUniformBlockBinding(shader.getShaderHandle(), m_pointLightBlockIndex, 0);

//Spotlight UBO
m_splBlockIndex = glGetUniformBlockIndex(shader.getShaderHandle(), "SpotLights");
glGetActiveUniformBlockiv(shader.getShaderHandle(), m_splBlockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &m_SpotLightBlockSize);
glUniformBlockBinding(shader.getShaderHandle(), m_splBlockIndex, 0);

//create the buffers
glGenBuffers(1, &m_SLBuffer);
glGenBuffers(1, &m_PLBuffer);

glBindBuffer(GL_UNIFORM_BUFFER, m_SLBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SpotLightData)*m_MaxSpots, nullptr, GL_DYNAMIC_DRAW);

glBindBuffer(GL_UNIFORM_BUFFER, m_PLBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(LightData)*m_MaxPoints, nullptr, GL_DYNAMIC_DRAW);

glBindBuffer(GL_UNIFORM_BUFFER, 0);

To populate the UBO's I use the following:

void LightUniformBuffer::updatePointLights(int numLights, const LightData * data)
{
    glBindBuffer(GL_UNIFORM_BUFFER, m_PLBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(LightData)*numLights, data);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
}

void LightUniformBuffer::updateSpotLights(int numLights, const SpotLightData * data)
{
    glBindBuffer(GL_UNIFORM_BUFFER, m_SLBuffer);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SpotLightData)*numLights, data);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
}

And finally to bind them:

void LightUniformBuffer::bindPointLights()
{
    glBindBufferBase(GL_UNIFORM_BUFFER, m_pointLightBlockIndex, m_PLBuffer);
}

void LightUniformBuffer::bindSpotLights()
{
    glBindBufferBase(GL_UNIFORM_BUFFER, m_splBlockIndex, m_SLBuffer);
}

These buffers are represented as arrays of lights in GLSL, like so:

layout (std140) uniform PointLights
{
    LightData points[MAX_NUM_POINT_LIGHTS];
};

layout (std140) uniform SpotLights
{
    SpotLightData spots[MAX_NUM_POINT_LIGHTS];
};

Now, when I populate the buffers and use the shader, I found, through using Nsight, that both buffers are using the same set of data, i.e. the spotlight buffer is filled with point light data, and so is useless.

Why is this happening, and how can I fix it?

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

I figured out the problem:

glUniformBlockBinding(shader.getShaderHandle(), m_pointLightBlockIndex, 0); Requires a unique binding location for each buffer, so if I defined an enum like so:

enum bufferType
{
    Spotlight = 0,
    PointLight = 1
};

I can set each one like so:

glUniformBlockBinding(shader.getShaderHandle(), m_pointLightBlockIndex, PointLight); glUniformBlockBinding(shader.getShaderHandle(), m_splBlockIndex, Spotlight);

Because I was using the number 0 instead, they were pointing to the same memory addresses.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .