finally i´ve got it working. I am now using the same mesh to draw as many instances of the same object as i want. It is still somewhat slower than i thought and i cant change the textures within the instances yet.
This is my mesh loading code:
glCreateVertexArrays(1, &StaticModelData::vaoID);
glCreateBuffers(1, &StaticModelData::vboID);
glCreateBuffers(1, &StaticModelData::iboID);
glCreateBuffers(1, &StaticModelData::instanceDataID);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 0);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 1);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 2);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 3);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 4);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 5);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 6);
//associate vertexArray with vboID and indexArray with iboID
glNamedBufferStorage(StaticModelData::vboID, sizeof(Vertex)*StaticModelData::vertexNum, &allVert[0], 0);
glNamedBufferStorage(StaticModelData::iboID, sizeof(unsigned int)*StaticModelData::indexNum, &allInd[0], 0);
glVertexArrayElementBuffer(StaticModelData::vaoID, StaticModelData::iboID);
//vaoID vertex attrib array binding location 0 -> vboID
glVertexArrayVertexBuffer(StaticModelData::vaoID, 0, StaticModelData::vboID, 0, sizeof(Vertex));
//vao binding location 0 -> attribute 0
glVertexArrayAttribBinding(StaticModelData::vaoID, 0, 0);
glVertexArrayAttribFormat(StaticModelData::vaoID, 0, 3, GL_FLOAT, GL_FALSE, offsetof(Vertex, position));
glVertexArrayAttribBinding(StaticModelData::vaoID, 1, 0);
glVertexArrayAttribFormat(StaticModelData::vaoID, 1, 2, GL_FLOAT, GL_FALSE, offsetof(Vertex, uv));
glVertexArrayAttribBinding(StaticModelData::vaoID, 2, 0);
glVertexArrayAttribFormat(StaticModelData::vaoID, 2, 3, GL_FLOAT, GL_FALSE, offsetof(Vertex, normal));
glNamedBufferStorage(StaticModelData::instanceDataID, sizeof(InstanceData)*MAX_INSTANCES, nullptr, GL_DYNAMIC_STORAGE_BIT);
glVertexArrayAttribBinding(StaticModelData::vaoID, 3, 1);
glVertexArrayAttribFormat(StaticModelData::vaoID, 3, 4, GL_FLOAT, GL_FALSE, offsetof(InstanceData, modelMatrix));
glVertexArrayAttribBinding(StaticModelData::vaoID, 4, 1);
glVertexArrayAttribFormat(StaticModelData::vaoID, 4, 4, GL_FLOAT, GL_FALSE, offsetof(InstanceData, modelMatrix) + sizeof(float) * 4);
glVertexArrayAttribBinding(StaticModelData::vaoID, 5, 1);
glVertexArrayAttribFormat(StaticModelData::vaoID, 5, 4, GL_FLOAT, GL_FALSE, offsetof(InstanceData, modelMatrix) + sizeof(float) * 8);
glVertexArrayAttribBinding(StaticModelData::vaoID, 6, 1);
glVertexArrayAttribFormat(StaticModelData::vaoID, 6, 4, GL_FLOAT, GL_FALSE, offsetof(InstanceData, modelMatrix) + sizeof(float) * 12);
glVertexArrayAttribBinding(StaticModelData::vaoID, 7, 1);
glVertexArrayAttribFormat(StaticModelData::vaoID, 7, 1, GL_UNSIGNED_INT, GL_FALSE, offsetof(InstanceData, textureUnitIndex));
glVertexArrayVertexBuffer(StaticModelData::vaoID, 1, StaticModelData::instanceDataID, 0, sizeof(InstanceData));
glVertexArrayBindingDivisor(StaticModelData::vaoID, 1, 1);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 0);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 1);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 2);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 3);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 4);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 5);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 6);
glEnableVertexArrayAttrib(StaticModelData::vaoID, 7);
And this is how i render:
glBindVertexArray(StaticModelData::vaoID);
updateShader();
//FOR ALL PRELOADED MODELS
for (auto it = StaticModelData::allModelDatas.begin(); it != StaticModelData::allModelDatas.end(); ++it) {
useGLSLProgram("TriangleShader");
std::vector<InstanceData> instanceDatas;
//FOR ALL INSTANCES OF THIS MODEL
for (std::vector<unsigned int>::iterator id = it->second.instances.begin(); id != it->second.instances.end(); ++id) {
//GET LOCATION OF THIS INSTANCE
std::unordered_multimap<GLuint, Location*>::iterator loc = Component::locations.find(*id);
//IF THERE IS A LOCATION FOR THIS INSTANCE
if (loc != Component::locations.end()) {
InstanceData instData;
loc->second->updateMatrix();
instData.modelMatrix = loc->second->modelMatrix;
//FIND THE TEXTURE THIS INSTANCE WANTS
std::unordered_multimap<GLuint, Texture*>::iterator tex = Component::textures.find(*id);
//IF THERE IS A TEXTURE FOR THIS INSTANCE
if (tex != Component::textures.end()) {
//FIND INSTANCE TEXTURE IN ALL TEXTURES
std::unordered_multimap<std::string, GLuint>::iterator texData = StaticModelData::allTextures.find(tex->second->texturePath);
if (texData != StaticModelData::allTextures.end()) {
//ACTIVATE THAT TEXTURE AND ADD ITS ID TO INSTANCEDATAS
int distance = std::distance(it->second.instances.begin(), id);
glActiveTexture(GL_TEXTURE0 + distance);
glBindTexture(GL_TEXTURE_2D, texData->second);
instData.textureUnitIndex = GL_TEXTURE0+distance;
}
}
instanceDatas.push_back(instData);
}
}
glNamedBufferSubData(StaticModelData::instanceDataID, 0, sizeof(InstanceData)*(instanceDatas.size()), &instanceDatas[0]);
glVertexArrayBindingDivisor(StaticModelData::vaoID, 1, 1);
glDrawElementsInstanced(GL_TRIANGLES, it->second.modelIndexNum, GL_UNSIGNED_INT, (void*)(sizeof(int)*(it->second.indexOffset)), it->second.instances.size());
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(0);
if (renderNormals) {
useGLSLProgram("NormalShader");
glDrawElementsInstanced(GL_TRIANGLES, it->second.modelIndexNum, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int)*it->second.indexOffset), it->second.instances.size());
}
glInvalidateBufferData(StaticModelData::instanceDataID);
glNamedBufferSubData(StaticModelData::instanceDataID, 0, sizeof(InstanceData)*(instanceDatas.size()), nullptr);
}
glBindVertexArray(0);
It seems like this is still a little unefficient. as i reach ~50 instances my framerate starts to drop and when i am at ~70 instances i get 15 FPS… any way to optimize this?
i will keep on working on this and i will try to figure out how to send an array of samplers to my shaders for multitexturing.
But you guys helped me plenty already and the main reason for this post is that didnt want to let my last post stand like that and for archive, this one might help people in the future