OpenGL, known as Open Graphics Library, is a graphics API that allows us to create and render 2D and 3D graphics in our applications. It has a set of functions that assist us in creating our graphic objects.
glDrawElements
functionThe glDrawElements
is a function in Open GL that allows us to draw shapes on the screen using vertices and indices. The vertices represent the corners of our shape while, indices represent the order in which vertices are connected in the shape.
The syntax of the function is following:
void glDrawElements(GLenum renderMode, GLsizei elementCount, GLenum indexType, const void* indices);
RenderMode
: It is the type of geometry to be drawn or rendered. It can be points, lines, or triangles.
elementCount
: It is the number of indices to be rendered.
indexType
: It is the type of indices.
indices
: These are the points to the array of indices that define the vertices to be rendered.
glDrawElements
draws nothingThere can be various reasons why our glDrawElements
function draws nothing. These reasons include the following:
When we draw shapes in OpenGL, we use shaders. Shaders are small programs that run on the graphics card and define how each vertex and fragment of an object should be rendered. We have to ensure the correct setup of the shader program. If the shaders setup is incorrect, the objects may not appear on the screen.
In the following code, we use glAttachShader
function to attach the vertexShader
and fragmentShader
to our shaderProgram
. Then we use the glLinkProgram
function to link our shaderProgram
to the code. The variable success
checks if we encounter any errors.
// Attaching and linking shadersglAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// Checking for any errorsint success;glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);if (success==false) {char errorMessage[512];glGetProgramInfoLog(shaderProgram, 512, NULL, errorMessage);cout << "Shader program linking error: " << errorMessage << endl;// Handling the error appropriately}
Before using glDrawElements
function, we bind the vertex buffer objects (VBO
) and element buffer objects (EBO
) correctly.
VBO
contains our vertex data or vertices.
EBO
contains our index data or indices.
In the following code, we use glBindBuffer
function to bind our buffer objects.
// Binding the vertex buffer objectglBindBuffer(GL_ARRAY_BUFFER, Vetrex_buffer_objects);// Binding the element buffer objectglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_objects);
Each vertex has its attributes, such as position and color. If the vertex attributes are not set up correctly, the vertices may not be interpreted correctly during rendering, which results in the glDrawElements
function drawing nothing.
In the following code, we set the attribute for a vertex with its attribute at position 0. The position of attributes starts from index 0. We use glVertexAttribPointer
function to interpret the vertex data for a specific attribute. Then we use glEnableVertexAttribArray
function to enable the attribute array for the specified attribute index so that it can be used during rendering.
// Specifying the vertex attribute pointersglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);
// Setting the view matrixglm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 3.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));glUniformMatrix4fv(viewUniformLocation, 1, GL_FALSE, glm::value_ptr(view));// Setting the projection matrixglm::mat4 projection = glm::perspective(glm::radians(45.0f), screenWidth / screenHeight, 0.1f, 100.0f);glUniformMatrix4fv(projectionUniformLocation, 1, GL_FALSE, glm::value_ptr(projection));
To check the proper working of our getIdrawElements
, we ensure that depth testing is enabled and face culling is disabled in our code. Depth testing and face culling are techniques used in 3D rendering to determine which objects should be visible on the screen.
We can enable depth testing and disable face culling using the following functions.
// Enabling depth testingglEnable(GL_DEPTH_TEST);// Disabling face cullingglDisable(GL_CULL_FACE);
Before calling the glDrawElements
function, we have to ensure we send correct data in the parameters of our function.
We have to ensure that the numIndices
and the indexType
matches our data. Moreover, we must check that we set the correct drawing mode to draw our desired shape. The offset
specifies the starting point from where the indices should be read.
// Drawing using glDrawElementsglDrawElements(renderMode, numIndices, indexType, offset);
glDrawElements
In the following code, we set up a basic OpenGL application that creates a window and renders a triangle on the screen.
#include <GL/glew.h> #include <GLFW/glfw3.h> int main() { // Initializing GLFW glfwInit(); // Creating a window GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL Window", NULL, NULL); if (window == NULL) { glfwTerminate(); return -1; } glfwMakeContextCurrent(window); // Initializing GLEW if (glewInit() != GLEW_OK) { glfwTerminate(); return -1; } // Setting up vertex data float vertices[] = { -0.5f, -0.5f, 0.0f, // Vertex 1 0.5f, -0.5f, 0.0f, // Vertex 2 0.0f, 0.5f, 0.0f // Vertex 3 }; // Setting up index data unsigned int indices[] = { 0, 1, 2 // Indices for drawing a triangle }; // Creating vertex buffer object (VBO) GLuint VBO; glGenBuffers(1, &VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // Creating element buffer object (EBO) GLuint EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); // Setting up vertex attributes glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // Rendering loop while (!glfwWindowShouldClose(window)) { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // Draw the triangle using glDrawElements glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0); glfwSwapBuffers(window); glfwPollEvents(); } // Cleaning up glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); // Terminate GLFW glfwTerminate(); return 0; }
When the glDrawElements
function in OpenGL draws nothing, there can be various negligence and inconsistencies causing the error. It is crucial to investigate each potential cause to identify the specific problem.
Free Resources