This is a very common question with developers new to OpenGL.
OpenGL is not a programming language, it is an API. An API is a software intermediary that makes it possible for different programs to interact with each other. In the case of OpenGL, it allows the interaction between the CPU and the GPU. In other words, with the OpenGL API, you can transmit data from the CPU to the GPU and vice-versa.
Think of OpenGL as a client-side and a server-side.
The client-side deals with loading data onto OpenGL buffers and then transferring them to the GPU. In order to send data to the GPU, you must create and bind what is known as OpenGL Objects. OpenGL Objects are structures composed of states and data and are responsible for transmitting data to and from the GPU. There are several types of OpenGL Objects. For example, a Vertex Buffer Object can store vertices of a character. Whereas a Texture, another kind of OpenGL Object, can store image data.
The client-side is where you use the OpenGL API extensively. For example, you can create an OpenGL Object by calling the following API call:
//Name of buffer object GLuint bufferName; //Create an OpenGL object of BUFFER type glGenBuffers(1, &bufferName); //Bind a OpenGL Buffer Object to the context glBindBuffer(GL_ARRAY_BUFFER, bufferName);
In the same manner, to load data to the GPU you can call the following method:
glBufferData(GL_ARRAY_BUFFER,sizeof(data), data, GL_STATIC_DRAW);
The server-side consists of shaders. A shader is a small program developed by you that lives in the GPU. A shader is written in a special graphics language called OpenGL Shading Language (GLSL).
The GLSL is based on the “C” programming language. As any other programming language, GLSL contains data types such as int, float, bool. It can handle loops and conditional statements like for-loops, while-loops and if-else statements. What makes it different from any other language is that it contains data types especifically designed to handle 3D mathematics. e.g., vec2, vec3, mat2, mat3.
The following discussion applies only to OpenGL ES 2.0
GLSL Data Types
The most common data-types in GLSL are: * Scalar Type * Vector Type * Matrix Type
Scalar Data Types
Scalar types include int, float and bool. Each representing the value of an integer, a floating point or a boolean, respectevely. For example:
int myInt=23; float myfloat=2.0; bool isTrue=true;
Vector Data Types
Vector types are data types designed to handle Vector operations. They are declared as: vec2, vec3, vec4. Each representing a vector with 2, 3 and 4 components, respectively. For example:
//Example of a vec2 vector vec2 position=vec2(4.0,3.0); //Example of a vec3 vector vec3 color=vec3(1.0,220.127.116.11); //Example of a vec4 vector vec4 light=vec4(1.0,0.0,1.0,1.0);
Accessing a Vector component
The components of a vector can be accessed by using the “.” notation and specifying the x, y, z or a component of the vector. For example:
//Declaring and defining a vec4 vector vec4 light=vec4(1.0,0.0,1.0,1.0); //Accessing the x-component of a vector float xValue=light.x; //Accessing the y-component of a vector float yValue=light.y; //Accessing the z-component of a vector float zValue=light.z; //Accessing the a-component of a vector float alphaValue=light.a;
Matrix Data Types
Matrix types are data types designed to handle Matrix operations. They are declared as: mat2, mat3, mat4. Each representing a matrix of 2x2, 3x3, and 4x4 dimensions, respectively. For example:
//Example of a 2x2 Matrix mat2 space=mat2(1.0,0.0, //1st column 0.0,1.0); //2nd column //Example of a 3x3 Matrix mat3 space=mat3(1.0,0.0,0.0, //1st column 0.0,1.0,0.0, //2nd column 0.0,0.0,1.0); // 3rd column //Example of a 4x4 Matrix mat4 space=mat4(1.0,0.0,0.0,0.0, //1st column 0.0,1.0,0.0,0.0, //2nd column 0.0,0.0,1.0,0.0, //3rd column 0.0,0.0,0.0,1.0); //4th column
Note: The components of the matrix are provided in column major order.
Accessing a Matrix component
mat3 space=mat3(1.0,0.0,0.0, 0.0,1.0,0.0, 0.0,0.0,1.0); space=3.0; //1 float value=space; //2 space=vec3(2.0,1.0,0.0); //3 vec3 newVector=space; //4
- Line 1. The bottom right component of a matrix is set to float value of 3.0.
- Line 2. A float variable is set with the value of the bottom right component of the matrix.
- Line 3. The first column vector of a matrix is set with a vector.
- Line 4. A vector is set with the first column vector of the matrix.
Variables in GLSL can take in different behaviors. Some variables can only receive data. Others can only provide data. Some variables can only be used in a vertex shader, while other variables can only be used in a fragment shader or both. To differentiate these type of variables, GLSL uses Type Qualifiers.
A variable that can only receive data in a vertex shader is declared with the Attribute qualifier.
//declaring an attribute in a shader attribute vec4 light;
As you recall, in the first stage of the rendering pipeline, all data goes through the Vertex Processing stage. If a variable in a vertex shader needs to be passed down to the fragment shader, it needs to be qualified with the varying qualifier. These type of variables are passed down between the vertex and fragment shader during each rendering.
//declaring a varying variable in a shader varying vec3 color;
Variables that are global and need to be used by both the vertex and fragment shader are qualified as Uniform.
//declaring a Uniform variable in a shader uniform mat4 MVPMatrix;
Precision of variables
Variables can also be qualified with high, medium or low precision. For example:
//Declaring a vector with high precision highp vec3 color=vec3(1.0,0.0,0.0); //Declaring a vector with medium precision mediump vec3 color=vec3(1.0,0.0,0.0); //Declaring a vector with low precision lowp vec3 color=vec3(1.0,0.0,0.0);
In the vertex shader, the use of a precision qualifier is optional. In a fragment shader the precision of a variable must be declared. The actual range of a precision qualifier is dependent on the specific OpenGL implementation.
GLSL Built-in Variables
There are two very important built-in variables in GLSL. Without their use in shaders, no rendering will occur. They are:
The gl_Position is used by the vertex shader to hand over the transformed vertex position to the OpenGL pipeline.
The gl_FragColor is used by the fragment shader to hand over the color of the fragment to the OpenGL pipeline.
The gl_Position and gl_FragColor variables are mandatory in the vertex and fragment shaders, respectively.
Which programming language to learn?
So, which programming language should you learn to work with OpenGL?
OpenGL is language independent, so you can interact with the API by using any programming language like C, C++, Objective-C, etc. However, interacting with OpenGL also requires knowledge of the GLSL language.
So to work with OpenGL you need to know any of these languages C, C++, Objective-C, Python, etc, Plus GLSL.