Hello,
recently I’ve being toying with UBOs to pass light data (position, color, radius) to my fragment shader. After getting terrible performance results I’m starging to wonder if what I did makes sense at all.
Maybe someone here has more insights…
in my fragment shader I declared a uniform block to hold the light data:
#version 330
layout(std140) uniform light {
vec3 position[16];
vec3 color[16];
float radius[16];
} u_light;
And the GL UBO setupcode:
static GLuint uidx[3];
static GLint offset[3];
static GLint stride[3];
static const GLchar* unames[3] = {
"light.position",
"light.color",
"light.radius"
};
glGetUniformIndices(pgm, 3, unames, uidx);
blockIndex = glGetUniformBlockIndex(pgm, "light");
glGetActiveUniformsiv(pgm, 3, uidx, GL_UNIFORM_OFFSET, offset);
glGetActiveUniformsiv(pgm, 3, uidx, GL_UNIFORM_ARRAY_STRIDE, stride);
glGetActiveUniformBlockiv(pgm, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blocksize);
glGenBuffers(1, &buffer);
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, blocksize * maxlights, NULL, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 1, buffer);
glUniformBlockBinding(pgm, blockIndex, 1);
And the GL code to fill the UBO every frame:
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glUniformBlockBinding(pgm, blockIndex, bindingPoint);
GLint i, off;
// position
for(off = offset[0], i = 0; i < numlights; i++) {
....
glBufferSubData(GL_UNIFORM_BUFFER, off, stride[0] * sizeof(vec3f32_t), ((float32*)(data + off)));
off += stride[0];
}
// color
for(off = offset[1], i = 0; i < numlights; i++) {
....
glBufferSubData(GL_UNIFORM_BUFFER, off, stride[1] * sizeof(vec3f32_t), ((float32*)(data + off)));
off += stride[1];
}
// color
for(off = offset[2], i = 0; i < numlights; i++) {
// ....
glBufferSubData(GL_UNIFORM_BUFFER, off, stride[2] * sizeof(float32), ((float32*)(data + off)));
}
glBindBufferBase(GL_UNIFORM_BUFFER, bindingPoint, buffer);
Offset and stride reports that the UBO size is 768 bytes. Maybe I’m mistaken but looking up 768 bytes for every pixel means a huge(!) memory traffic. I guess this is why the frame rate drops?!
Is this an elegant way to pass light data to the fragment shader or are there better ways to do this?
Regards
Saski