Starting with GLSL and OpenGL
This chapter tries to depict a first programming example where the OpenGL functionality is made by GLSL shaders.
Introduction
A brief description about this is that Shaders access to part of the OpenGL state. In particular, Vertex Shaders can modify the geometry and Fragment Shaders can modify final rendering image, usually color and depth buffers.Tipically an application initializes light color, light position, modelview and projection matrices, etc. The shader needs to use these OpenGL states to replace the fixed functionality. The only thing you need is to be careful and not forget about these states.
Furthermore, when an application alters the subset of OpenGL state it is communicating with the shader.
In counterpart, the Shaders are flexible and we can pass specific aplicacation variables, for instante, timestep in an application of animation. The next sections describe a simple example of an Vertex and Fragment shaders in action.
On the GLSL side
A Simple Vertex Shader
This vertex just rotates the geometry by 45°. This is only a illustrative program to show how the vertex shaders can be modify the geometry.
All vertices of our primitive will go through this program. gl_Vertex is the current vertex which is being processed by this program. In fact, there are some processors (depending wich GPU) executing the same Vertex Shader at the same time. gl_Vertex has the same (untransformed) values like you specify in glVertex3f(x,y,z) in your C++ program. The gl_ModelViewProjectionMatrix is the concatenated modelview and projection matrix. I assume you know what the modelview and projection matrices are, otherwise you can look it up in the OpenGL documentation or Red Book OpenGL Programming Guide.
void main(){
float PI = 3.14159265358979323846264;
float angle = 45.0;
float rad_angle = angle*PI/180.0;
vec4 a = gl_Vertex;
vec4 b = a;
b.x = a.x*cos(rad_angle) - a.y*sin(rad_angle);
b.y = a.y*cos(rad_angle) + a.x*sin(rad_angle);
gl_Position = gl_ModelViewProjectionMatrix*b;
}
A Simple Fragment Shader
A fragment is basically a pixel before it is rasterized. If you render a fully visible triangle then all pixels between the three vertices must be drawn. Before those pixels are drawn they go through the fragment processor and for each possible pixel the fragment program is exectuted.
In this simple example every fragment is set to yellow color. gl_FragColor holds the output color.
void main(void){
gl_FragColor = vec4(1.0, 1.0,0.0, 1.0);
}
On the C++ side
GLSL Handlers
In recently GLSL and OpenGL versions handlers are attended by GLuint data type. So much, we need a program handler, which encloses one or both vertex and fragment shaders
GLuint program_object;
Additionally, you need a Vertex shader handler and a Fragment shader or only one.
GLuint vertex_shader;
GLuint fragment_shader;
Creating a GLSL Program
So far, we only declare the handlers, now create them
program_object = glCreateProgram();
vertex_shader = glCreateShader(GL_VERTEX_SHADER); fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
You see the difference between them.
Assigning shader source code
For each vertex and fragment shaders we need assign a source code. In this example this is made directly using a char*, but for more complex shaders is necessary implement a file reader class or function. Then the source code is assigned to shaders as follow.
glShaderSource(vertex_shader, 1, &vertex_source, NULL);
glShaderSource(fragment_shader, 1, &fragment_source, NULL);
Compiling and Attaching the Shaders
After assign the source code, is necessary compile each shader in the follow way
glCompileShader(vertex_shader);
glAttachShader(program_object, vertex_shader);
glCompileShader(fragment_shader); glAttachShader(program_object, fragment_shader);
Remember, also it is possible use only one vertex or fragment shader.
Finally, we must link the program
glLinkProgram(program_object);
To each stage should be check possible errors with
printProgramInfoLog(program_object);
Once you created, compiled and linked the program, it is very easy to use that shader with the OpenGL function glUseProgram with the program object as argument. To stop using the program you can call glUseProgram(0).
OpenGL 2.0 Initializer
In Linux you need assure thare is the glxext.h file in your include/GL path. Addiotinally, you need include a header for these file in your code as follow:
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glu.h>
#include <GL/glut.h>
...
However, in windows it doesn't work. In windows the best choice is to use a OpenGL extensions initializer library as GLew or GLee.
But, for a easy cross-platform compatibility, I recomend use GLee and compile on both, linux and windows, in the same way.
Source code
For easy understanding of this tutorial we provide the compilable (linux and windows) source code here.

