Uniform Block solve padding/alignment for vec3 in CPU struct

I have a struct on the CPU which I'm sending to a uniform block in my shader. After a bit frustration I finally got it to work. The problem I had was that vec3s are actually treated as 16-bytes, or in other words they need to have padding. So to solve this I added a dummy-float after each vec3 (see below).

I know I could just use vec4, but since I want to treat alpha as a separate component I don't want to type that 4th component for each vector every time. Furthermore, I would have to use swizzling in the shader as well to separate alpha.

Now to the question, is there any nicer/better way to solve the padding problem than having to add an extra float?

// CPU
struct Material
{
public:
vec3 Emissive; float p1;
vec3 Ambient; float p2;
vec3 Diffuse; float p3;
vec3 Specular;
float Shininess;
float Alpha;
};

layout(std140) uniform uniMaterial
{
vec3 Emissive;
vec3 Ambient;
vec3 Diffuse;
vec3 Specular;
float Shininess;
float Alpha;
};


Regards, Tobias

My solution:

struct GpuVec3
{
public:
GpuVec3() {}

GpuVec3& GpuVec3::operator=(const vec3& other)
{
v.x = other.x;
v.y = other.y;
v.z = other.z;
v.w = 1.0f;

return *this;
}

GpuVec3& GpuVec3::operator=(const vec4& other)
{
v.x = other.x;
v.y = other.y;
v.z = other.z;
v.w = other.w;

return *this;
}

private:
vec4 v;
};

typedef GpuVec3 GpuVec4;

• I suggest you accept the current answer. And ask a new question for your follow up question. – concept3d Nov 22 '14 at 14:07
• @concept3d ok, done. – Unresolved External Nov 22 '14 at 16:17

Tobias,

If you declare your vec3 class in C++ as having 16 byte alignment, you will have the matching offset.

struct vec3
{
float x,y,z;
} __attribute__ ((aligned(16)));


However this will align it everywhere. You might want a GPUVec3 which is aligned, and has copy constructor from your general vec3 so you don't burn that extra float everywhere.

I would, however, suggest stuffing your alpha into the w component of some of those vectors to improve bandwidth since you are just burning memory there. I wouldn't surprised that, in addition to losing a float per vector3, you are also losing 2 floats at the end of your uniform structure.

struct Material
{
public:
vec4 EmissiveAndShineness;
vec4 AmbientAndAlpha;
vec3 Specular;
};


or

struct Material
{
public:
GPUVec4 EmissiveAndShineness; // sizeof(GPUVec4) == 16
GPUVec4 AmbientAndAlpha; // sizeof(GPUVec4) == 16
GPUVec3 Diffuse; // sizeof(GPUVec3) == 16
GPUVec3 Specular; // sizeof(GPUVec3) == 16
};

• Thanks a lot @Steven, this solved my problem! However, now I have a follow-up question. Please have a look at update #1 above for my solution and follow-up question. – Unresolved External Nov 22 '14 at 13:21
• @UnresolvedExternal - if you have a follow-up question you should ask it as a separate question. – Maximus Minimus Nov 22 '14 at 15:21
• @DarthSatan ok, I've removed the follow-up question. – Unresolved External Nov 22 '14 at 16:17