sgsrules's picture

Uniform Buffer Layout question

Hi, i've started using uniform buffer objects and have everything work right.... for the most part. It seems my layout is a bit fudged up for example if i have the following c# structure

 public struct LightProperties
    public Vector3 Position;
    public Vector3 Ambient;
    public Vector3 Diffuse;
    public Vector3 Specular;
LightProperties Light;
Light.Position = new Vector3(0,0,0);
Light.Ambient = new Vector3(1,1,1);
Light.Diffuse = new Vector3(1, 1, 1);
Light.Specular = new Vector3(1, 1, 1);

and pass the following in my shader

layout(std140) uniform lightProperties
 vec3 pos;
 vec3 amb;
 vec3 dif;
 vec3 spec;

for some reason things don't get mapped right what i get in the shader is the following:

pos = Position.X,Position.Y,Position.Z; //as it should
amb = 0,Ambient.r,Ambient.g; // wrong offset by one
dif = Ambient.b,0,Diffuse.r; // wrong again offset even more
spec = Diffuse.g, Diffuse.b,0; // wrong again

It looks like it's passing the Vector3 as Vector4 in fact if i change my struct to

     public struct LightProperties
            public Vector4 Position;
            public Vector4 Ambient;
            public Vector4 Diffuse;
            public Vector4 Specular;

and leave my shader code as is things seem to work as they should. but i don't want to spend the extra resources passing vector4 when i only need vector3. I'm updating my uniform buffer with the following code:

 GL.BindBuffer(BufferTarget.UniformBuffer, lightPropertiesBuf[0]);
 GL.BufferData(BufferTarget.UniformBuffer, (IntPtr)Marshal.SizeOf(Light), ref Light, BufferUsageHint.DynamicDraw);
 GL.BindBuffer(BufferTarget.UniformBuffer, 0);


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
the Fiddler's picture

There is a layout mismatch. I don't know if it is caused by .Net or the uniform buffer layout (check the specs), but you can control the layout on .Net using StructLayoutAttribute (try Pack=1 or Pack=16 depending on what the uniform buffer expects).

sgsrules's picture

Thanks for the quick reply, I had already tried using StructLayoutAttribute which didn't change anything. But i did go back and look at the spec for std140 and it states:

2. If the member is a two- or four-component vector with components consuming
N basic machine units, the base alignment is 2N or 4N, respectively.
3. If the member is a three-component vector with components consuming N
basic machine units, the base alignment is 4N.

so basically any vector3 are passed as as vec4. I guess i'll just use the extra space for something else.