How OpenGL Works - OpenGL Pipeline

Kerem TAN
6 min readSep 8, 2023

--

Hello dear readers,
It would be better to explain what is the OpenGL before explaining the OpenGL Pipeline.

OpenGL is a library that can work cross-platform and helps to communicate between the graphics card and programmers. The operations that 2D and 3D graphics require such as video games, simulations, and visual effects can be performed thanks to this library that can work independently on different operating systems and video cards.

The OpenGL library does not do the work of communicating between the programmer and the graphics card alone. There are some auxiliary libraries that help it with this. Below are some of OpenGL’s helper libraries and brief information about them.

GLFW is an auxiliary library of OpenGL that can work cross-platform. The GLFW library communicates between OpenGL and the operating system and it helps us to manage windows, control input-output operations, and similar processes in OpenGL.

GLAD and GLEW are auxiliary libraries of OpenGL that can work cross-platform.

Programs that use OpenGL need to connect with OpenGL’s dynamic library in the background while they run. OpenGL uses the dynamic loading method for the programs can connect its dynamic library. The GLAD and GLEW libraries help us here. They are used to connect with the dynamic library of OpenGL. It is enough to use only one of the two libraries.

The working way of GLAD, the programmer tells to GLAD library the function it needs instead of directly capturing the needed function addresses in the dynamic library of OpenGL, and the GLAD library gives the address of the function needed to the programmer.

The working way of GLEW, giving programmers an easier-to-use interface by wrapping functions in the OpenGL dynamic library.

Steps of OpenGL Pipeline

  • Certain steps have to be followed when a shape is drawn with OpenGL.
  • These certain steps are called the OpenGL Pipeline.
  • A program object which is in the OpenGL library contains these steps which is called the OpenGL Pipeline. Thus, we can manage the OpenGL Pipeline thanks to a program object and we can program some specific steps as we want.

The steps of the OpenGL Pipeline which the contained in a program object for us to be able to draw a shape with OpenGL are briefly described below.

Step 1 - Vertex Specification

The programmer can not make any changes or interventions in Vertex Specification.

For example, we want to draw a triangle on the monitor.

Each corner point of the triangle to be drawn is called a vertex and each vertex has x, y and z coordinates data in the drawing area.

Simple shapes drawn using vertices are called primitives.
For example, the triangle shape that we wanted to draw is a primitive.

The vertices data are set as a bit series for the primitive/primitives that will be rendered in Vertex Specification.

Step 2 - Vertex Processing

Points called vertex in the previous step begin to be processed for rendering in this step.
This step consists of several sub-steps. Technically, some other steps contain several sub-steps, but their sub-steps will not be explained separately. The reason for explaining the sub-steps in this step is that programmers can directly modify or intervene in the processing of vertexes with these sub-steps.

Step 2.1 - Vertex Shader

The programmer can make some changes or interventions in Vertex Shader.

The aim of Vertex Shader is to geometrically calculate the position and features of the 2D/3D model to be created by using vertices.
Some interventions are made using GLSL commands in this step.
The vertex data sent from the previous step to this step comes as a data series of bit type.
The type of the bit data can be labeled when writing GLSL commands in this step. For example, “layout(location=0)” command is used to indicate that the vertex data received in the previous step is a location data.

Moreover, the vector sent in the previous step is transformed from a 3-element vector (x, y, z coordinates) to a 4-element vector in this step. The 1 number is added to the end of the vertex data to do this transformation. In this way, the new vector is converted to [x, y, z, 1].

The purpose of this vector transformation is so that the matrix multiplication can be done correctly in the next steps.

The reason for adding 1 to the end of the vertices data is that the number 1 is an ineffective element in the multiplication process.

In other words, the purpose is that the matrix multiplications for the next steps can be done without distorting the original data.

Step 2.2 - Tessellation

The programmer can make some changes or interventions in Tessellation.

The data sent from the previous step can be converted into smaller primitives in this step because more detail and complexity can be added dynamically to 3D surfaces by breaking the primitives into smaller pieces.

The model/shape that we wanted to create can be converted to more realistic in this way.

Step 2.3 - Geometry Shader

The programmer can make some changes or interventions in Geometry Shader.

Geometry Shader is logically similar to Vertex Shader.
More complex and new primitives are created by using the primitives sent from the previous step in the Geometry Shader, just like geometric shapes are created by using vertices in the Vertex Shader.

For example, a hexagon is created by using triangle shapes.

Step 3 - Vertex Post-Processing

The programmer can not make any changes or interventions in Vertex Post-Processing.

Values calculated in Vertex and Geometry Shader can be saved in this step if wish.

Sometimes, the drawing area that contains the shape wanted to create can be larger than the monitor on which the shape will be displayed. Unnecessary calculations are prevented by removing primitives that cannot be displayed on the monitor from the drawing screen in this step.

This processing is called clipping.

Step 4 - Primitive Assembly

The programmer can not make any changes or interventions in the Primitive Assembly.

Vertices are processed as a series and new shapes are rendered from these series in this step.
For example, drawing 3 triangles from a 9-element vertex series.

In addition, Face Culling is done in this step.
Face Culling processing means that invisible or too far to be seen in perspective primitives are in our drawing area removed from the drawing area.

Step 5 - Rasterization

The programmer can not make any changes or interventions in Rasterization.

Geometric shapes created in the previous step are converted into pixels called fragment data in this step.

Information such as the color and depth of each pixel of the shape/model to be wanted drawing is stored in the fragment data for the next step.

Step 6 - Fragment Shader

The programmer can make some changes or interventions in Fragment Shader.

Pixels named as fragment data in the previous step are processed in this step. In particular, the coloring of each pixel of the created shape/model is done at this stage.

In addition to coloring the pixels in this step, operations such as shading and lighting of each pixel are also processed.

GLSL commands are used at this stage, just like in Vertex Shader to perform the operations mentioned above.

Step 7 - Per-Sample Operations

The programmer can not make any changes or interventions in Per-Sample Operations.

First of all, the Depth Test is performed in this step. The Depth Test is the stage of whether the fragment data wanted drawing will be drawn or not.
For example; If there is another fragment of data in front of the fragment data to be wanted drawing, the fragment data to be drawn will fail for the depth test.

Moreover, Color Blending is performed in this step. Using the operations described in the previous steps, the colors in the fragment data are mixed with each other and interact with overlapping fragment data in this stage.

As a result of all these steps, the rendering process of the scene is completed and the final 2D/3D shape is created.

Thank you for reading this far.

You can follow code examples in here:

To learn more about the OpenGL, you can go to the video here:

You can reach the Turkish version of this article in here:

--

--