My demo renders a bunch of cubes to the screen, each with a random scale, rotation and position. Each one is textured, and tinted a certain shade of red. I've just figured out how to have multiple textures available in the same shader pass, so I was going have some of the cubes render with one texture, and some of them with the other. Here's the original instance structure I was using:
struct CubeInstance
{
glm::vec4 rotation;
glm::vec4 scale;
glm::vec4 position;
};
...
// quick and dirty way to fill the array with random data
srand(clock());
for(int i = 0; i < cubesData->totalInstances; i++)
{
float rotX = rand()%200-100;
float rotY = rand()%200-100;
float rotZ = rand()%200-100;
float rotS = (rand()%190 + 10)/100.0f;
float posX = (rand()%10000 - 5000)/100.0f;
float posY = (rand()%10000 - 5000)/100.0f;
float posZ = (rand()%10000 - 5000)/100.0f;
float scale = (rand()%400 + 10.0f)/100.0f;
cubesData->instances[i] = CubeInstance
{
glm::vec4(rotX, rotY, rotZ, rotS),
glm::vec4(scale, scale, scale, 1),
glm::vec4(posX, posY, posZ, 0)
};
}
...
// here's the bit of code with which I'm attaching the instance data to my shader program:
glGenBuffers(1, &cubesData->instanceBufferId);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, cubesData->instanceBufferId);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(cubesData->instances), &cubesData->instances, GL_STREAM_DRAW);
GLuint blockIndex = glGetProgramResourceIndex(cubesData->shaderProgramId, GL_SHADER_STORAGE_BLOCK, "instance_data");
glShaderStorageBlockBinding(cubesData->shaderProgramId, blockIndex, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, cubesData->instanceBufferId);
And in my shader:
struct InstanceData
{
vec4 rotation;
vec4 scale;
vec4 position;
};
layout (std430) buffer instance_data
{
InstanceData instances[];
};
...
void main(void)
{
InstanceData instance = instances[gl_InstanceID];
...
All good, that works fine. Here's what it looks like at this stage:
So then I went to introduce a fourth component to represent which texture each instance should use. Given that it starts on a 4-byte boundary, I figured it would be safe to just make it an int, in both the C++ code and the shader code. Obviously not, because I got a huge mess of screwed up rendering on the next run. Fair enough, so I added a padding vector of glm::vec3 at the end, and an equivalent padding vec3 in the shader code, and now for some really weird reason I'm ending up with a big stack of overlaid cubes rendering right at the origin for no apparent reason, in addition to the normal (albeit reduced-in-number) bunch of cubes normally found scattered around the screen.
My updated code has the following changes:
struct CubeInstance
{
glm::vec4 rotation;
glm::vec4 scale;
glm::vec4 position;
int material; // ADDED THIS
glm::vec3 _pad0; // ADDED THIS
};
...
// added to my random data generation:
int material = rand()%2; // ADDED THIS
cubesData->instances[i] = CubeInstance
{
glm::vec4(rotX, rotY, rotZ, rotS),
glm::vec4(scale, scale, scale, 1),
glm::vec4(posX, posY, posZ, 0),
material, // ADDED THIS
glm::vec3(0) // ADDED THIS
};
and my updated shader code:
struct InstanceData
{
vec4 rotation;
vec4 scale;
vec4 position;
int material; // ADDED THIS
vec3 _pad0; // ADDED THIS
};
And just from these changes, I now have a bunch of weird giant cubes appearing the centre of the scene.
Any ideas what I'm doing wrong?