Hi!
I’ve a problem.
I’ve a set of tiles with one texture and another set of tiles with another texture, without instancing I can use bindless texturing and draw everything with one draw call only.
for (unsigned int i = 0; i < m_normals.size(); i++) {
if (m_normals[i].getAllVertices().getVertexCount() > 0) {
//std::cout<<"next frame draw normal"<<std::endl;
if (m_normals[i].getMaterial().getTexture() == nullptr) {
perPixelLinkedList2.setParameter("haveTexture", 0.f);
} else {
math::Matrix4f texMatrix = m_normals[i].getMaterial().getTexture()->getTextureMatrix();
//perPixelLinkedList2.setParameter("textureMatrix", texMatrix);
perPixelLinkedList2.setParameter("haveTexture", 1.f);
}
if (m_normals[i].getMaterial().getType() == Material::WATER) {
perPixelLinkedList2.setParameter("water", 1.0f);
} else {
perPixelLinkedList2.setParameter("water", 0.0f);
}
if (core::Application::app != nullptr) {
float time = core::Application::getTimeClk().getElapsedTime().asSeconds();
perPixelLinkedList2.setParameter("time", time);
}
unsigned int p = m_normals[i].getAllVertices().getPrimitiveType();
/*if (m_normals[i].getVertexArrays()[0]->getEntity()->getRootType() == "E_MONSTER") {
std::cout<<"tex coords : "<<(*m_normals[i].getVertexArrays()[0])[0].texCoords.x<<","<<(*m_normals[i].getVertexArrays()[0])[0].texCoords.y<<std::endl;
}*/
for (unsigned int j = 0; j < m_normals[i].getAllVertices().getVertexCount(); j++) {
vbBindlessTex[p].append(m_normals[i].getAllVertices()[j],(m_normals[i].getMaterial().getTexture() != nullptr) ? m_normals[i].getMaterial().getTexture()->getId() : 0);
}
}
}
currentStates.blendMode = sf::BlendNone;
currentStates.shader = &perPixelLinkedList2;
currentStates.texture = nullptr;
for (unsigned int p = 0; p < Batcher::nbPrimitiveTypes; p++) {
if (vbBindlessTex[p].getVertexCount() > 0) {
vbBindlessTex[p].update();
frameBuffer.drawVertexBuffer(vbBindlessTex[p], currentStates);
vbBindlessTex[p].clear();
}
}
I do batching to group all vertices of tiles 1 (instance1) and all vertices of tiles 2 (instance 2) into two vertex arrays and then I put every vertices of tiles1 and tiles2 in a vertex buffer with the right texture index and I draw everything with a single draw call!!!
The problem is where I want to use instanced rendering.
This’ll not work :
for (unsigned int i = 0; i < Batcher::nbPrimitiveTypes; i++) {
vbBindlessTex[i].clear();
}
std::vector<TransformMatrix*> tm;
for (unsigned int i = 0; i < m_instances.size(); i++) {
if (m_instances[i].getAllVertices().getVertexCount() > 0) {
if (m_instances[i].getMaterial().getType() == Material::WATER) {
perPixelLinkedList.setParameter("water", 1.0f);
} else {
perPixelLinkedList.setParameter("water", 0.0f);
}
if (core::Application::app != nullptr) {
float time = core::Application::getTimeClk().getElapsedTime().asSeconds();
perPixelLinkedList.setParameter("time", time);
}
matrices.clear();
tm = m_instances[i].getTransforms();
for (unsigned int j = 0; j < tm.size(); j++) {
tm[j]->update();
std::array<float, 16> matrix = tm[j]->getMatrix().transpose().toGlMatrix();
for (unsigned int n = 0; n < 16; n++) {
matrices.push_back(matrix[n]);
}
}
glCheck(glBindBuffer(GL_ARRAY_BUFFER, vboWorldMatrices));
glCheck(glBufferData(GL_ARRAY_BUFFER, matrices.size() * sizeof(float), &matrices[0], GL_DYNAMIC_DRAW));
glCheck(glBindBuffer(GL_ARRAY_BUFFER, 0));
if (m_instances[i].getVertexArrays().size() > 0) {
Entity* entity = m_instances[i].getVertexArrays()[0]->getEntity();
for (unsigned int j = 0; j < m_instances[i].getVertexArrays().size(); j++) {
if (entity == m_instances[i].getVertexArrays()[j]->getEntity()) {
unsigned int p = m_instances[i].getVertexArrays()[j]->getPrimitiveType();
for (unsigned int k = 0; k < m_instances[i].getVertexArrays()[j]->getVertexCount(); k++) {
vbBindlessTex[p].append((*m_instances[i].getVertexArrays()[j])[k], (m_instances[i].getMaterial().getTexture() != nullptr) ? m_instances[i].getMaterial().getTexture()->getId() : 0);
}
}
}
}
//std::cout<<"texture : "<<m_instances[i].getMaterial().getTexture()<<std::endl;
//std::cout<<"entity : "<<m_instances[i].getVertexArrays()[0]->getEntity()->getRootEntity()->getType()<<std::endl;
if (m_instances[i].getMaterial().getTexture() != nullptr) {
//std::cout<<"texture"<<std::endl;
math::Matrix4f texMatrix = m_instances[i].getMaterial().getTexture()->getTextureMatrix();
//perPixelLinkedList.setParameter("textureMatrix", texMatrix);
perPixelLinkedList.setParameter("haveTexture", 1.f);
} else {
//std::cout<<"no texture"<<std::endl;
perPixelLinkedList.setParameter("haveTexture", 0.f);
}
}
}
currentStates.blendMode = sf::BlendNone;
currentStates.shader = &perPixelLinkedList;
currentStates.texture = nullptr;
for (unsigned int p = 0; p < Batcher::nbPrimitiveTypes; p++) {
if (vbBindlessTex[p].getVertexCount() > 0) {
vbBindlessTex[p].update();
frameBuffer.drawInstanced(vbBindlessTex[p], vbBindlessTex[p].getPrimitiveType(), 0, vbBindlessTex[p].getVertexCount(), tm.size(), currentStates, vboWorldMatrices);
vbBindlessTex[p].clear();
}
}
Because I have to put every matrices and vertices of the first instances group and making a drawcall and then put every matrices and vertices of the second instances group and making a second draw call.
Isn’t there any way to make it with a single draw call ?
I mean put matrices and instances of the first and second group of instance and draw everything ?
So I pass an array of instance group1 vertices size and instance2 vertices size and an array of numInstances of instance1 and numInstances of instance2 to an opengl function.
Thank.
EDIT : I’ve seen glMultiDrawIndirect but this is for glDrawElements and glDrawBaseElementBaseInstanced and I really don’t know what glDrawBaseElementInstanced is compared to glDrawElementInstanced.