CLOSE
Updated on 04 Jul, 202510 mins read 53 views

Now that we have a working OpenGL context and a window open, it's time to draw something – finally! In this article, we will introduce the rendering pipeline, explain what VAO, VBO, and EBO are, and show you how to draw your first triangle using modern OpenGL.

The OpenGL Rendering Pipeline (Modern, Programmable)

OpenGL's rendering pipeline transforms 3D data into 2D pixels on your screen through a series of stages:

Vertex Data → Vertex Shader → Primitive Assembly → Rasterization → Fragment Shader → Output to Screen

Key Stages:

  • Vertex Shader: Transforms vertex positions.

  • Primitive Assembly: Forms triangles/lines/points.

  • Rasterization: Converts shapes to pixels.

  • Fragment Shader: Computes pixel color.

  • Framebuffer: Where final pixels are drawn.

In modern OpenGL, you control the pipeline by writing shaders and supplying data via buffers.

What Are VAO, VBO, and EBO?

These are the building blocks of sending data to the GPU.

ObjectStands ForPurpose
VAOVertex Array ObjectStores the state of vertex attribute configs
VBOVertex Buffer ObjectStores vertex data (positions, colors, etc.)
EBOElement Buffer ObjectStores indices for reusing vertex data

Drawing Your First Triangle

Let's break this down into steps.

Step 1: Define Vertex Data

float vertices[] = {
    -0.5f, -0.5f, 0.0f,  // bottom left
     0.5f, -0.5f, 0.0f,  // bottom right
     0.0f,  0.5f, 0.0f   // top center
};

Step 2: Create VAO and VBO

GLuint VAO, VBO;

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);

// Bind VAO first
glBindVertexArray(VAO);

// Bind and fill VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

// Vertex attribute setup
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

// Unbind for safety
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

Step 3: Write the Shaders

Vertex Shader (vertex.glsl):

#version 330 core
layout(location = 0) in vec3 aPos;

void main() {
    gl_Position = vec4(aPos, 1.0);
}

Fragment Shader (fragment.glsl)

#version 330 core
out vec4 FragColor;

void main() {
    FragColor = vec4(1.0, 0.0, 0.0, 1.0); // red
}

Compile and link these into a shader program (you will usually write a function for this).

Step 4: Render Loop

// In your main loop
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

glUseProgram(shaderProgram);  // your compiled shader
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);

How Drawing Works Internally

Here's what happens:

  • You store vertex data in the VBO.
  • You tell OpenGL how to interpret that data (via glVertexAttribPointer).
  • You bind the VAO to remember those settings.
  • In the render loop, OpenGL:
    • Pulls vertex data
    • Runs it through the vertex shader
    • Rasterizes it
    • Colors pixels with the fragment shader
    • Outputs it to the screen

Leave a comment

Your email address will not be published. Required fields are marked *