GLSL: Uniform Buffer Object containing an array of struct

2.1k views Asked by At

I am using JOGL to develop small OpenGL applications in Java. I am facing the following issue: I have a Uniform Buffer Object "Light" declared in the fragment shader as follows:

struct PerLight
{
    vec4 cameraSpaceLightPos;
    vec4 lightIntensity;
};

const int numberOfLights = 4;

uniform Light
{
    vec4 ambientIntensity;
    float lightAttenuation;
    PerLight lights[numberOfLights];
} Lgt;

As I understand, the only not straightforward part when putting data inside the UBO is that the float "lightAttenuation" will need to be padded with 3 floats.

I put the data in my buffer as follows (all values except lightAttenuation are arrays with 4 float values):

gl.glBindBuffer(GL2.GL_UNIFORM_BUFFER, lightUniformBuffer[0]);

    FloatBuffer buffer = Buffers.newDirectFloatBuffer(2 * (2 + DynamicRangeLights.NUMBER_OF_LIGHTS * 2) * 4);
    buffer.put(lightData.ambientIntensity.getArray());
    buffer.put(new float[] { lightData.lightAttenuation, 0.0f, 0.0f, 0.0f });
    for (int i = 0; i < 4; ++i) {
        buffer.put(lightData.lights[i].cameraSpaceLightPos.getArray());
        buffer.put(lightData.lights[i].lightIntensity.getArray());
    }
    buffer.rewind();

    gl.glBufferSubData(GL2.GL_UNIFORM_BUFFER, 0, sizeLightBlock, buffer);

But the result I get is wrong: the colors and intensities of the lights are completely off.

If I rewrite the UBO in my fragment shader as follows, everything works fine:

uniform Light
{
    vec4 ambientIntensity;
    float lightAttenuation;
    vec4 cameraSpaceLightPos0;
    vec4 lightIntensity0;
    vec4 cameraSpaceLightPos1;
    vec4 lightIntensity1;
    vec4 cameraSpaceLightPos2;
    vec4 lightIntensity2;
    vec4 cameraSpaceLightPos3;
    vec4 lightIntensity3;
} Lgt;

According to me, the two UBOs should receive the same data and display the same result, but apparently I am wrong. What is the difference between these two UBOs, and how should I buffer the data in the first one to get the same result as the second one?

Edit: I forgot to mention it, but I use in my shaders

layout(std140) uniform;

So if I am not wrong, all uniforms use the std140 layout.

0

There are 0 answers