OpenGL Programming/Modern OpenGL Introduction

Introduction
Most of the documentation on OpenGL uses features that are being deprecated, in particular the "fixed pipeline". OpenGL 2.0 and later comes with a programmable pipeline, where the programmable part is done with shaders, written in the GLSL C-like language.

This document is for people who are learning OpenGL and want to use modern OpenGL from the start. The programmable pipeline is more flexible, but less intuitive than the fixed pipeline. We'll however make sure that we start with simple code first. We'll use an approach similar to NeHe's tutorials for OpenGL 1.x, with examples and tutorials to better understand the theory behind a programmable pipeline.

At first the vertex arrays and shaders look like a pain to work with compared to the old immediate mode and fixed rendering pipeline. However, in the end, especially if you are using buffer objects, your code will be much cleaner and the graphics will be faster.

The code examples in this page are in the public domain. Feel free to do what you want with them.

Share this document with your friends! Wikibooks deserves more recognition and contributions :)

Notes:
 * It is possible to mix fixed pipeline and programmable pipeline to some extent, but fixed pipeline is being deprecated, and not available at all in OpenGL ES 2.0 (or its WebGL derivative), so we won't use it.
 * There is now OpenGL 3 and 4, which notably introduce geometry shaders, but this time it is only a light evolution compared to the previous version. Since it is not available on mobile platforms as of 2012, for now we'll concentrate on OpenGL 2.0.

Base libraries
You will need to make sure OpenGL, SDL2 and GLEW are ready to use.

The installation pages describe how you can setup your system.

To situate these libraries in the OpenGL stack, check APIs, Libraries and acronyms.

Note: we chose SDL2 because it is very portable and targets both desktop and mobile platforms. We won't use advanced features, and almost all of our code will be plain OpenGL, so you'll have no trouble moving to another library such as FreeGLUT, GLFW or SFML. We may write specific tutorials covering how to switch to these libraries.

Code samples
You can download the source code samples using Git from the gitlab repository.

You may directly run them, or craft your first OpenGL app step by step by following the instructions.

Displaying a triangle in 2D
Let's start simple :) Rather than struggling with a complex program that would take us a long time to hack until it works for the first time, the goal here is to get a basic but functional program that we can then improve upon step by step,

The triangle is the most basic unit in 3D programming. Actually, everything you see in video games is made of triangles! Small, textured triangles, but triangles nonetheless :)

To display a triangle in the programmable pipeline, we'll need at minimum:
 * a Makefile to build our application
 * initialize OpenGL and the helper libraries
 * an array with the coordinates of the 3 vertices (plural of vertex, i.e. a 3D point) of the triangle
 * a GLSL program with:
 * a vertex shader: we pass it each vertex individually, and it will compute their on-screen (2D) coordinates
 * a fragment (pixel) shader: OpenGL will pass it each pixel that is contained in our triangle, and it will compute its color
 * pass the vertices to the vertex shader

Makefile
The code examples repository (see link at the end of the page) uses Makefiles since they are the simplest build tool.

GNU/Linux or MinGW
It is very easy to configure 'make' for our example. Write this in a 'Makefile' file:

To compile your application, type in a terminal:

A little more portable Makefile looks like this:

This allows you to type make clean which removes the triangle binary and any intermediate object files that may have been generated. The .PHONY rule is there to tell make that "all" and "clean" are not files, so it will not get confused if you actually have files named like that in the same directory.

See Installation/Windows for additional MinGW/MXE setup.

Mac OS X
A Makefile for Mac OS X looks like this:

This makefile assumes that you installed glew using MacPorts.

If you want to use a different programming environment, see the Setting Up OpenGL section.

Other systems
Refer to the installation pages for hints on how to configure your build environment.

Initialization
Let's create a file :

In, we'll create our GLSL program. In, we'll draw the triangle. In, we'll destroy the GLSL program.

Vertex array
Our first triangle will be displayed in 2D − we'll move into something more complex soon. We describe the triangle with the 2D (x,y) coordinates of its 3 points. By default, OpenGL's coordinates are within the [-1, 1] range.

For now let's just keep this data structure in mind, we'll write it in the code later.

Note: the coordinates are between -1 and +1, but our window is not square! In the next lessons, we'll see how to fix the aspect ratio.

Vertex shader
This is the GLSL program that will get each point of our array one by one, and tell where to put them on the screen. In this case, our points are already in 2D screen coordinates, so we don't change them. Our GLSL program looks like this:


 * means v1.20, the version of GLSL in OpenGL 2.1.
 * OpenGL ES 2's GLSL is also based on GLSL v1.20, but its version is 1.00.
 * is the current vertex; it's an input variable that we'll need to declare in our C code
 * is the resulting screen position; it's a built-in output variable
 * the  takes our x and y coordinates, then   for the z coordinate. The last one, w=  is for homogeneous coordinates (used for transformation matrices).

Now we need to make OpenGL compile this shader. Start the  above  :

We pass the source as a string to  (later we'll read the shader code differently and more conveniently). We specify the type.

Fragment shader
Once OpenGL has our 3 points screen position, it will fill the space between them to make a triangle. For each of the pixels between the 3 points, it will call the fragment shader. In our fragment shader, we'll tell that we want to color each pixel in blue (this sets RGB - red,green,blue color components):

We compile it similarly, with type. Let's continue our  procedure:

GLSL program
A GLSL program is the combination of the vertex and fragment shader. Usually they work together, and the vertex shader can even pass additional information to the fragment shader.

Create a global variable below  to store the program handle:

Here is how to link the vertex and fragment shaders in a program. Continue our  procedure with:

Passing the triangle vertices to the vertex shader
We mentioned that we pass each triangle vertex to the vertex shader using the  attribute. Here is how to declare it in the C code.

First, let's create a second global variable:

End our  procedure with:

Now we can pass our triangle vertices to the vertex shader. Let's write our  procedure. Each section is explained in the comments:

tells OpenGL to retrieve each vertex from the data buffer created in  and pass it to the vertex shader. These vertices define the on-screen position for each point, forming a triangle whose pixels are colored by the fragment shader.

Note: in the next tutorial we'll introduce Vertex Buffer Objects, a slightly more complex and newer way to store the vertices in the graphic card.

The only remaining part is, to clean-up when we quit the program. It's not critical in this particular case, but it's good to structure applications this way:

Our first OpenGL 2.0 program is complete!

If this fails
The next tutorial adds more robustness to our first, minimalist code. Make sure to try the  code (see link to code below).

Experiment!


Feel free to experiment with this code:
 * try to make a square by displaying 2 triangles
 * try to change the colors
 * read the OpenGL man pages for each function that we used:
 * OpenGL (ES 2.0)
 * GLUT
 * try to use this code in the fragment shader − what does it do?

In the next tutorial, we'll add a few utility functions to make it easier to write and debug shaders.