glDrawElementsInstanced Does Not Work
This is a demonstration of object instancing using a library I developed
to draw blender files into a C++ program. You can see it at
github.com.
This is the same program as the former with the objects being instanced.
To instance the objects I do a few things different. I am using a boolean
"instanced" to switch between instanced and uninstanced.
Here is where the shaders are switched over:
skyboxShader = new Shader();
skyboxShader->initShader("/usr/share/openglresources/shaders/skyboxshader.vs", "/usr/share/openglresources/shaders/skyboxshader.frag", "demoboxshader.bin");
shader = new Shader();
if (instanced)
{
shader->initShader("/usr/share/openglresources/shaders/assimpinstance.vs", "/usr/share/openglresources/shaders/diffspecbinorm.frag", "demomodelinstancedshader.bin");
}
else
{
shader->initShader("/usr/share/openglresources/shaders/diffspecbinorm.vs", "/usr/share/openglresources/shaders/diffspecbinorm.frag", "demomodelshader.bin");
}
The instancing shader is:
/********************************************************** * assimpinstance.vs: A shader to render the form * of a virtual object for an OpenGL program. It * passes along position, normals, and texcoords * and its original form was found on www.learnopengl.com. * Adapted by: Edward Charles Eberle * April 2020 San Diego, California USA * ********************************************************/ /** \class assimpinstance.vs * Vertex shader. */ #version 300 es
#define NUM_INSTANCES 10
precision highp float;
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoord;struct Location
{
vec3 Position;
vec3 Normal;
vec2 TexCoord;
};out Location locval;
uniform mat4 view;
uniform mat4 projection;layout (packed) uniform itemData{
mat4 location[NUM_INSTANCES];
};
void main()
{
gl_Position = projection * view * location[gl_InstanceID] * vec4(position, 1.0f);
locval.Position = vec4(location[gl_InstanceID] * vec4(position, 1.0f)).xyz;
locval.Normal = vec4(location[gl_InstanceID] * vec4(normal, 1.0)).xyz;
locval.TexCoord = texCoord;
}
The Instancing call is:
//! Draw the object.
void MeshTex::Draw(Shader *shader, mat4 view, mat4 projection, vectormodel, vectorlights, vectorspotLights, vec3 viewPos, int startIndex, bool diffOnly, float gamma)
{
mat4 *modelData = new mat4[quantity];
for (int x = 0; x < quantity; x++)
{
modelData[x] = model[x];
}
glBindVertexArray(VAO);
bool difftrigger = true;
bool spectrigger = true;
bool heighttrigger = true;
opacity = 1.0f;
shader->Use();
shader->setFloat(“gamma”, gamma);
shader->setBool(“diffOnly”, diffOnly);
shader->setInt(“debug”, debugVal);
//! Bind appropriate textures
//! Here we allow for the three types of textures: Diffuse, specular and binormal or bumpmap.
for( int x = 0; x < textures.size(); x++)
{
glActiveTexture(GL_TEXTURE0 + startIndex + x); // Active proper texture unit before binding
glBindTexture(GL_TEXTURE_2D, textures[x].id);
//! Texture present.
if (debug1)
{
cout << "\n\t Texture Path: " << textures[x].path << " Texture Type: " << textures[x].type
<< " Index: " << startIndex + x << " gamma " << gamma;
}
if ((textures[x].type == “diffuse”))
{
shader->setBool(“isDiffuse”, true);
if (!difftrigger)
{
if (debug1)
{
cout << “\n\n\tDrawing texture: " << textures[x].path << " to diffuse2.\n\n”;
}
shader->setInt(“diffuseTwo”, startIndex + x);
shader->setInt(“numDiffuse”, 2);
}
else
{
if (debug1)
{
cout << “\n\n\tDrawing texture: " << textures[x].path << " to diffuse1.\n\n”;
}
shader->setInt(“diffuseOne”, startIndex + x);
shader->setInt(“numDiffuse”, 1);
}difftrigger = false; } else if (((textures[x].type == "shininess") || (textures[x].type == "specular")) && (spectrigger)) { if (debug1) { cout << "\n\n\tDrawing texture: " << textures[x].path << " to specular1.\n\n"; } shader->setBool("isSpecular", true); shader->setInt("specularOne", startIndex + x); spectrigger = false; } else if (((textures[x].type == "height") || (textures[x].type == "normal")) && (heighttrigger)) { if (debug1) { cout << "\n\n\tDrawing texture: " << textures[x].path << " to binormal1.\n\n"; } shader->setBool("isBinormal", true); shader->setInt("binormalOne", startIndex + x); heighttrigger = false; } } if (difftrigger) { shader->setBool("isDiffuse", false); } if (spectrigger) { shader->setBool("isSpecular", false); } if (heighttrigger) { shader->setBool("isBinormal", false); } shader->setFloat("shininess", 10.0f); shader->setVec3("viewPos", viewPos); shader->setFloat("opacity", opacity); shader->setMat4("view", view); shader->setMat4("projection", projection); glBindBuffer(GL_UNIFORM_BUFFER, VBO[1]); //! Pass the image indices and cube distances. glBufferSubData(GL_UNIFORM_BUFFER, 0, quantity * sizeof(mat4), (void*) modelData); glBindBuffer(GL_UNIFORM_BUFFER, 0); shader->setVec3("colordiff", vec3(1.0f, 1.0f, 1.0f)); for (int x = 0; x < lights.size(); x++) { stringstream ss; ss << x; shader->setVec3("pointLights[" + ss.str() + "].position", lights[x].position); shader->setVec3("pointLights[" + ss.str() + "].ambient", lights[x].ambient); shader->setVec3("pointLights[" + ss.str() + "].diffuse", lights[x].diffuse); shader->setVec3("pointLights[" + ss.str() + "].specular", lights[x].specular); shader->setFloat("pointLights[" + ss.str() + "].constant", lights[x].constant); shader->setFloat("pointLights[" + ss.str() + "].linear", lights[x].linear); shader->setFloat("pointLights[" + ss.str() + "].quadratic", lights[x].quadratic); } for (int x = 0; x < spotLights.size(); x++) { stringstream ss; ss << x; shader->setVec3("spotLights[" + ss.str() + "].position", spotLights[x].position); shader->setVec3("spotLights[" + ss.str() + "].direction", spotLights[x].direction); shader->setFloat("spotLights[" + ss.str() + "].cutOff", spotLights[x].cutOff); shader->setFloat("spotLights[" + ss.str() + "].outerCutOff", spotLights[x].outerCutOff); shader->setVec3("spotLights[" + ss.str() + "].ambient", spotLights[x].ambient); shader->setVec3("spotLights[" + ss.str() + "].diffuse", spotLights[x].diffuse); shader->setVec3("spotLights[" + ss.str() + "].specular", spotLights[x].specular); shader->setFloat("spotLights[" + ss.str() + "].constant", spotLights[x].constant); shader->setFloat("spotLights[" + ss.str() + "].linear", spotLights[x].linear); shader->setFloat("spotLights[" + ss.str() + "].quadratic", spotLights[x].quadratic); } if (true) { debug(modelData); cout << "\n\tIs instanced: " << instanced; cout << "\n\tGamma: " << gamma; cout << "\n\tDiffOnly: " << diffOnly; cout << "\n\tDebug: " << debugVal; cout << "\n\tShininess " << 10.0f; cout << "\n\tViewPos: "; printVec3(viewPos); cout << "\n\tOpacity: " << opacity; cout << "\n\tView: "; printMat4(view); cout << "\n\tProjection: "; printMat4(projection); cout << "\n\tColordiff: "; printVec3(vec3(1.0f, 1.0f, 1.0f)); cout << "\n\tInstance quantity: " << quantity << ".\n\n"; //UniformPrinter uniforms(shader->Program); //dumpData(); cout << "\n\tVertex Size: " << vertSize << " Index Size: " << indexSize; } // Draw mesh. glDrawElementsInstanced(GL_TRIANGLES, indexSize, GL_UNSIGNED_INT, indices, quantity); if (debug1) { cout << "\n\n\t" << quantity << " instanced objects drawn.\n\n"; } glBindTexture(GL_TEXTURE_2D, 0); glBindVertexArray(0);
}
The output generated is the same as the regular demo but the instanced figures are not present.