Building blocks: the graphic contest
Introduction
This post explains how to set and initialize properly the GL graphic contest for a GPGPU project.
The following code uses some SDL functions, if you need to use some other library (like GLUT) look for the corresponding functions.
Basic settings
If we want to display the results of our computation we would set something like the clear color with glClearColor, enable the double buffer using SDL_GL_SetAttribute SDL function. Furthermore we have to enable 2D texturing with glEnable.
The complete code for those settings is:
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); glClearColor(0.0, 0.0, 0.0, 1.0); glEnable(GL_TEXTURE_2D);
The coordinate system
Two very important settings of the graphic contest are the coordinate system of the screen and the projection mode.
For the computational phase an orthogonal view is required so to have an exact correspondence between the texture texels and the screen pixels (so to avoid any interpolation), the function used for this is glOrtho. Another important setting is the viewport that represents the screen area affected by drawing operations, in order to have the right results the viewport has to be set to the texture dimensions with glViewport.
A good thing is that you can totally customize the coordinate system using glOrtho, so I’m used to set a coordinate system like this:
0,0----------w,0 | | | | | | 0,h-----------w,h
and use a texture that has the same dimensions of the screen, so to avoid any changes between the computational and visualization phases.
Of course you can use a texture that has dimensions different from the screen’s ones, but you have to manage the thing with glViewport.
The code I use to set the coordinate system is the following:
glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, w, h, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, w, h);
Computation and visualization
If you want to use properly the shaders for computational purposes and then display the results of your computation (draw the texture you get), you have to keep in mind that the coordinate system of the texture is different from the screen one, in fact it’s this one:
0,1----------1,1 | | | | | | | | | | 0,0-----------1,0
This involves that you have to use two different functions for the computation and the visualization.
Using the screen coordinate system described above, these are the two functions I use.
This function is used for the computation:
void ShaderDraw(GLfloat w, GLfloat h)
{
glBegin(GL_QUADS);
glTexCoord2f(0.0, 1.0);
glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex2f(w, 0);
glTexCoord2f(1.0, 0.0);
glVertex2f(w, h);
glTexCoord2f(0.0, 0.0);
glVertex2f(0.0, h);
glEnd();
}
This function is used for the visualization of the texture on screen
void ScreenDraw(GLfloat w, GLfloat h)
{
glBegin(GL_QUADS);
glTexCoord2d(0.0, 0.0);
glVertex2f(0.0, 0.0);
glTexCoord2d(1.0, 0.0);
glVertex2f(w, 0.0);
glTexCoord2d(1.0, 1.0);
glVertex2f(w, h);
glTexCoord2d(0.0, 1.0);
glVertex2f(0.0, h);
glEnd();
}
These functions draw the texture on the whole screen, if you want to change this you have to modify properly the parameters of the glVertex call.
Example code
This is the complete code I use for my init function:
void GLInit(int w, int h)
{
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
glClearColor(1.0, 0.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, w, h, 0.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, w, h);
}