3/21
1.2. Loading OpenGL functions
Our second step is to setup the OpenGL context for the window, and load OpenGL functions.
OpenGL functions are not available by default on the system, they should be specifically loaded. Unfortunately, at the opposite of common code library providing a single implementation independent of the system and hardware, OpenGL implementations are directly related to the hardware and driver and need to adapt to various ecosystem.
As a result, there is not only one implementation of OpenGL, but several. For instance, NVIDIA, AMD, Intel are providing their own drivers and OpenGL implementation, and may propose different vendor-specific functionalities. Drivers allowing to use the GPU functionalities are also depending on the OS (Linux, Windows, MacOS, etc).
Furthermore, there exists multiple OpenGL versions that may be used (from OpenGL 1 to the last version OpenGL 4.x, as well as OpenGL ES for embedded systems).
To use OpenGL functionalities in your program, one must link the function call from the OpenGL specification, to low level pointers that are platform specific. While, this step can be performed manually, it is recommended to use cross-platform OpenGL loader library.
There exists several OpenGL loader library. The main differences between them are the following
-
Some load pre-defined OpenGL version, while others try to provide dynamically the latest possible on your system.
-
Some load core profile functions only, ie. load only functions from the current official OpenGL specifications, while others also load legacy functions allowing to use depreciated functions for compatibility with old code.
-
Some libraries propose C-type interface (as described in the official specification), while other encapsulate OpenGL functions in C++ namespace.
In our case, we are going to use the library Glad.
Glad is a recent loader following the official specifications from Khronos. A Webservice allows to generate pre-defined OpenGL function for a given OpenGL version and provide corresponding header and code. The files provided by Glad are stand-alone, and no extra library has to be installed on the system.
In our case, we will use OpenGL 4.3 core profile.
-
OpenGL 4.3 is a recent OpenGL version but widely available. At the opposite of the latest OpenGL version requiring vendor specific drivers, OpenGL 4.3 is implemented in Mesa, the Open Source driver implementation for generic GPU.
-
For good practice, we will only use core-profile functions, avoiding therefore to use depreciated features. When looking at code on internet, take into account that OpenGL has encountered large changes from its specification over years, and, unfortunately, it is very common to find online resources mixing legacy depreciated functions with newer one.
Code
Consider the following source code
#include <glad/glad.h> // glad.h should be included before glfw or any OpenGL related include
#include <GLFW/glfw3.h>
#include <iostream>
int main()
{
glfwInit();
auto window = glfwCreateWindow(500, 500, "My Window", nullptr, nullptr);
// Enable the window to handle OpenGL Context
glfwMakeContextCurrent(window);
// Load OpenGL Functions
gladLoadGL();
while( !glfwWindowShouldClose(window) ) {
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
-
Make sure that you are able to compile and execute the code. Note that you should obtain the same black window once executed. But this time, OpenGL functions are loaded and can be used after the call gladLoadGL().
Note that code and header files corresponding to Glad library are placed in external/glad directory.
Changing background color
Let us use our first OpenGL function in changing continuously the background color of the window.
In a common OpenGL scene with user interaction and/or animation, the image is rendered several times per seconds, meaning that the loop starting by the instruction
while( !glfwWindowShouldClose(window) ){ ... }
iterate continuously. At each iteration, it is common to completely clear the screen, and render a new image from scratch. Note that to obtain an impression of real-time animation, the new image should be rendered at most in 40ms, corresponding to 25 frames per second (fps).
-
Modify the loop to add this new code
while( !glfwWindowShouldClose(window) ) {
// Set the (R,G,B,A) color to clear the screen
glClearColor(1.0f, 1.0f, 0.5f, 1.0f);
// Clear the screen (designated by the color buffer)
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
Changing the background color is performed in two steps.
-
First, a color is setup in its RGBA form using glClearColor function. Each component should be a float value in [0,1]. Note that the A (alpha) component is not used by default, therefore its value will not influence the visual result [1].
-
Secondly, the buffer of color, i.e. the image in the window, is cleared with the previously setup color using the function glClear with argument GL_COLOR_BUFFER_BIT. glClear is a general function to efficiently clear an entire buffer, and can also be used in real scene to clear the depth buffer.
As a general remark on OpenGL naming conventions
-
OpenGL functions are named using the convention glFunctionName.
-
Constant predefined values related to OpenGL state are in capital letter and words are separated by underscore (ex.
GL_COLOR_BUFFER_BIT).
-
Now, adapt your code such that the background color varies continuously between different color.
Tips
-
You may create a float value varying periodically between [0,1] within the loop by small increments.
-
You may use math function in including the C math library
#include <cmath>, and use functions from thestdnamespace (ex.std::abs(), std::cos()), or create the periodicity using the modulo operator%applied on integer.