How to setup SDL2 OPENGL GLEW with codeblocks & mingw32

Last updated 4/5/2014

Tutorial Color Key

button or links in codeblocks, file directories , file names , Text that needs to be copied , console commands

Downloading required files

The first thing you will need to do is download codeblocks. You can find it here at codeblocks.org. You will want to download the correct one. Click first on "download" then "Download the binary release". Select one of the ones listing the mingw in the name. codeblocks-[version number]mingw-setup.exe download from either BerliOS or Sourcefore.net. As of me writing this 4/5/2014 the current release is 13.12 available at sourceforge here codeblocks-13.12mingw-setup.exe

The next thing you will need to do is download SDL 2.0. You can find it at www.libsdl.org Go to download SDL 2.0 and then select the version that reads like SDL2-devel-2.0.3-mingw.tar.gz the 2.0.3 is the version number in this case shown. As of this being written 2.0.3 has a bug in it SDL_platform.h file and will cause compile errors.
You can download 2.0.3 here SDL2-devel-2.0.3-mingw.tar.gz
You can download 2.0.2 here SDL2-devel-2.0.2-mingw.tar.gz
If you wish to use 2.0.3 you should replace the SDL_platform.h file in it with the one from 2.0.2. There should be a fix in the next revision for the current bug discussed here.

Next you will want to down load any libraries that you may choose to use with SDL such as image, mixer and so on. Those can be found here http://www.libsdl.org/projects/. The more common ones use include SDL_image, SDL_mixer, SDL_net and SDL_ttf. ttf is for font handling. Mixer is used for sound. Image is used for images. Net is used for network. For use with code blocks you will want to go in and download the perspective file that has "mingw.tar.gz" in the name.
The current versions are as follows.
SDL2_image-devel-2.0.0-mingw.tar.gz
SDL2_mixer-devel-2.0.0-mingw.tar.gz
SDL2_net-devel-2.0.0-mingw.tar.gz
SDL2_ttf-devel-2.0.12-mingw.tar.gz

Next download GLEW from glew.sourceforge.net/. Download the the TGZ version the windows binaries will not work they are for visual studio. The current version is 1.10 which you can download here TGZ.
You will also want to download compile.bat from here compile.bat.

Installation Codeblocks

It is important to install the files in the directories I specify when you are learning. This will save you from the headache of having to fix issues later on.
Installing codeblocks is simple install it to its default directory and accept the agreements and so on.
At this point you want to make sure code blocks is included in your system path. It will very depending on what windows system you are running as how to get to the path. You will want to add C:\Program Files (x86)\CodeBlocks\MinGW\bin; to the end of the path and then reboot your system to make use of it. This will need to be done so GLEW can be compiled for this system.
The simplest way under windows 7 and 8 maybe to use the command setx
setx PATH "%path%;C:\Program Files (x86)\CodeBlocks\MinGW\bin;"
If you find you are getting a message about the path being too long and being truncated you will need to edit the path variable. The best suggestion I can give here is to use an editor like notepad++ and switch directory names to 8dot3 format. Use dir /x to get the 8dot3 name of each directory. I did it to just the longest names saving about 25% You may not have this issue at all I happen to be running a lot of compilers and other software that needs it.

Installation SDL 2.0

Next create a directory in C: called SDL (case sensitive)
Copy all SDL downloads into C:\SDL
Extract them into the C:\SDL directory so that it looks like this.
If you need a utility to extract them you could I recommend 7-zip.

Installing and compiling GLEW for mingw

First create a directory called glew (case sensitive) in on your C: drive.
Next extract glew into the directory.
Next copy compile.bat into C:\glew\glew-1.10.0 or the perspective directory for your version
Next open a command terminal and change directories to C:\glew\glew-1.10.0
Run compile.bat. If you don't know how simply type compile.bat and press enter.
In your file manager got to C:\glew\glew-1.10.0\include\GL and copy all the files.
Then past them in C:\Program Files (x86)\CodeBlocks\MinGW\include\GL
Now go to C:\glew\glew-1.10.0\lib copy all files and paste them in C:\Program Files (x86)\CodeBlocks\MinGW\lib
Next go to C:\glew\glew-1.10.0\src copy glew.o and glew.mx.o and paste them in C:\Program Files (x86)\CodeBlocks\MinGW\lib
Finally copy the header files glew.h, glsew.h and wglew.h from C:\glew\glew-1.10.0\include\GL and place them in
C:\Program Files (x86)\CodeBlocks\MinGW\include\GL.

Setting up codeblocks to work with SDL2.0 GLEW and opengl

Start codeblocks.
Click on Settings in the top menu. A menu box will open up.
In the menu box click on Linker Settings. In the other linker options panel type in the following:-lmingw32 -lSDL2main -lSDL2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lopengl32 -lglu32 -lglew32 -lglew32mx
so that it looks like this.


Next click Search directories next to the Linker Settings tab.
You need to enter in each of the following lines by clicking add then entering it in.
C:\SDL\SDL2-2.0.3\i686-w64-mingw32\include\SDL2
C:\SDL\SDL2_mixer-2.0.0\i686-w64-mingw32\include\SDL2
C:\SDL\SDL2_image-2.0.0\i686-w64-mingw32\include\SDL2
C:\SDL\SDL2_ttf-2.0.12\i686-w64-mingw32\include\SDL2
You will want it to look as follows.


Next click the Linker tab next to the compiler tab.
You need to enter in each of the following lines by clicking add then entering it in.
C:\SDL\SDL2-2.0.3\i686-w64-mingw32\lib
C:\SDL\SDL2_mixer-2.0.0\i686-w64-mingw32\lib
C:\SDL\SDL2_image-2.0.0\i686-w64-mingw32\lib
C:\SDL\SDL2_ttf-2.0.12\i686-w64-mingw32\lib
You will want it to look as follows.


A simple project to display a triangle

The following sections will cover how to create a project and how to code a simple window with a triangle in it. You can download the project from here SDLOGL01.zip

Creating a project

Start codeblocks. Then in the middle of the screen click Create a new project.

A menu should popup like this click Empyt project.

In this menu Name your project in Project title. Fill in Folder to create project in with the location you wan to save your projects. Then click Next.

Finally when you see this menu click Finish
.

DLL(s) Required for project

At this point you will want to go to all the following locations that you are using and grab all the DLL files and then either in your project directory or system location so they can be accessed when you run your projects. I tend to put them in my project folder this way when I go to ship something or bundle it they are right there.
C:\SDL\SDL2-2.0.3\i686-w64-mingw32\bin
C:\SDL\SDL2-2.0.2\i686-w64-mingw32\bin
C:\glew\glew-1.10.0\lib
The minimal files you should have SDL2.dll, glew32.dll, glew32mx.dll
If you are using SDL networking, font, image or mixer in a project you will also need to go to the following directories and get their perspective dll files.
C:\SDL\SDL2_image-2.0.0\i686-w64-mingw32\bin
C:\SDL\SDL2_mixer-2.0.0\i686-w64-mingw32\bin
C:\SDL\SDL2_net-2.0.0\i686-w64-mingw32\bin
C:\SDL\SDL2_ttf-2.0.12\i686-w64-mingw32\bin

Project Layout

There are a total of 14 files in this project. The shader files 2nd.fs and 2nd.vs are not visible in the project directory
SDLOGL.h, SDLOGL.cpp, globject.h, globject.cpp, globjectls.cpp, loadtextfile.h, loadtextfile.cpp, CApp_OnCleanup.cpp, CApp_OnEvent.cpp, CApp_OnInit.cpp, CApp_OnLoop.cpp, CApp_OnRender.cpp, 2nd.fs, 2nd.vs

At present the tutorial is imcomplete. The full set of code is provided below. You can also download the complete project from the link above or here SDLOGL01.zip This can be used to follow along with the video I will be completing this as soon as I can so please check back soon.

SDLOGL.h

#ifndef SDLOGL_H_INCLUDED
#define SDLOGL_H_INCLUDED
#include < SDL.h >
#include < SDL_image.h >
#include < GL / glew.h >
#include "globject.h"
class my_glObject;
class CApp
{
private :
bool Running; // flag to indicate program is running
SDL_Window * window; // Window
SDL_GLContext maincontext; // window context
my_glObject * myObect; // This is the OpenGL Object
public :
CApp () ;
int OnExecute () ;
bool OnInit () ;
void OnEvent ( SDL_Event * Event ) ;
void OnLoop () ;
void OnRender () ;
void OnCleanup () ;
} ;
#endif // SDLOGL_H_INCLUDED

SDLOGL.cpp

#include "SDLOGL.h"
CApp : : CApp () {
window = NULL;
Running = true;
}
int CApp : : OnExecute () {
if ( OnInit () = = false ) {
return - 1;
}
SDL_Event Event;
while ( Running ) {
while ( SDL_PollEvent ( & Event ) ) {
OnEvent ( & Event ) ;
}
OnLoop () ;
OnRender () ;
}
OnCleanup () ;
return 0;
}
int main ( int argc , char * argv [ ] ) {
CApp theApp;
return theApp.OnExecute () ;
}

CApp_OnInit.cpp

#include "SDLOGL.h"
bool CApp : : OnInit () {
if ( SDL_Init ( SDL_INIT_EVERYTHING ) < 0 ) {
return false;
}
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MAJOR_VERSION , 4 ) ;
SDL_GL_SetAttribute ( SDL_GL_CONTEXT_MINOR_VERSION , 0 ) ;
SDL_GL_SetAttribute ( SDL_GL_DOUBLEBUFFER , 1 ) ;
SDL_GL_SetAttribute ( SDL_GL_DEPTH_SIZE , 24 ) ;
if ( ( window = SDL_CreateWindow ( "SDL opengl 3.3 + " , 100 , 100 , 640 , 480 , SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN ) ) = = NULL ) {
return false;
}
maincontext = SDL_GL_CreateContext ( window ) ;
SDL_GL_SetSwapInterval ( 1 ) ;
glewExperimental = true;
GLenum err = glewInit () ;
myObect = new my_glObject;
myObect - > init () ;
return true;
}

CApp_OnEvent.cpp

#include "SDLOGL.h"
void CApp : : OnEvent ( SDL_Event * Event ) {
if ( Event - > type = = SDL_QUIT ) {
Running = false;
}
}

CApp_OnLoop.cpp

#include "SDLOGL.h"
void CApp : : OnLoop () {
}

CApp_OnRender.cpp

#include "SDLOGL.h"
void CApp : : OnRender () {
myObect - > display () ;
SDL_GL_SwapWindow ( window ) ;
}

CApp_OnCleanup.cpp

#include "SDLOGL.h"
void CApp : : OnCleanup () {
myObect - > cleanup () ;
SDL_GL_DeleteContext ( maincontext ) ;
SDL_DestroyWindow ( window ) ;
SDL_Quit () ;
}

globject.h

#ifndef GKOBJECT_H_INCLUDED
#define GKOBJECT_H_INCLUDED
#include < stdio.h >
#include < string >
#include < vector >
#include "SDLOGL.h"
class CApp;
class my_glObject
{
protected :
GLuint VertexArrayID;
GLuint programID;
GLfloat vertexBufferData [ 9 ] ;
GLuint vertexbuffer;
public :
bool init () ;
bool LoadShaders ( std : : string vs , std : : string fs ) ;
GLuint getVertexArrayID () { return VertexArrayID; }
GLuint getprogramID () { return programID; }
bool display () ;
void cleanup () ;
} ;
#endif // GKOBJECT_H_INCLUDED

globject.cpp

#include"globject.h"
bool my_glObject : : init ()
{
glGenVertexArrays ( 1 , & VertexArrayID ) ;
glBindVertexArray ( VertexArrayID ) ;
LoadShaders ( "2nd.vs" , "fragmentshader.fs" ) ;
float f [ ] = {
- 1.0 , - 1.0 , 0.0 ,
1.0 , - 1.0 , 0.0 ,
0.0 , 1.0 , 0.0 ,
} ;
for ( int c = 0;c < 9;c + + )
{
vertexBufferData [ c ] = f [ c ] ;
}
glGenBuffers ( 1 , & vertexbuffer ) ;
glBindBuffer ( GL_ARRAY_BUFFER , vertexbuffer ) ;
glBufferData ( GL_ARRAY_BUFFER , sizeof ( vertexBufferData ) , vertexBufferData , GL_STATIC_DRAW ) ;
return 0;
}
bool my_glObject : : display ()
{
// Clear the screen
glClear ( GL_COLOR_BUFFER_BIT ) ;
// Use our shader
glUseProgram ( programID ) ;
// 1rst attribute buffer : vertices
glEnableVertexAttribArray ( 0 ) ;
glBindBuffer ( GL_ARRAY_BUFFER , vertexbuffer ) ;
glVertexAttribPointer (
0 , // attribute 0. No particular reason for 0 , but must match the layout in the shader.
3 , // size
GL_FLOAT , // type
GL_FALSE , // normalized ?
0 , // stride
( void * ) 0 // array buffer offset
) ;
// Draw the triangle !
glDrawArrays ( GL_TRIANGLES , 0 , 3 ) ; // 3 indices starting at 0 - > 1 triangle
glDisableVertexAttribArray ( 0 ) ;
return 0;
}
void my_glObject : : cleanup ()
{
glDeleteBuffers ( 1 , & vertexbuffer ) ;
glDeleteVertexArrays ( 1 , & VertexArrayID ) ;
}

globjectls.cpp

#include"globject.h"
#include "common / loadtextfile.h"
bool my_glObject : : LoadShaders ( std : : string vs , std : : string fs )
{
bool fail = 0;
GLuint VertexShaderID = glCreateShader ( GL_VERTEX_SHADER ) ;
GLuint FragmentShaderID = glCreateShader ( GL_FRAGMENT_SHADER ) ;
std : : string vShaderCode;
std : : string fShaderCode;
vShaderCode = LoadTextFromFile ( vs ) ;
// can check for error later
fShaderCode = LoadTextFromFile ( fs ) ;
// can check for error later
GLint Result = GL_FALSE;
int InfoLogLength;
// compiling vs
const char * VertexSourcePointer = vShaderCode.c_str () ;
glShaderSource ( VertexShaderID , 1 , & VertexSourcePointer , NULL ) ;
glCompileShader ( VertexShaderID ) ;
// Check Vertex Shader
glGetShaderiv ( VertexShaderID , GL_COMPILE_STATUS , & Result ) ;
glGetShaderiv ( VertexShaderID , GL_INFO_LOG_LENGTH , & InfoLogLength ) ;
if ( InfoLogLength > 0 ) {
std : : vector < char > VertexShaderErrorMessage ( InfoLogLength + 1 ) ;
glGetShaderInfoLog ( VertexShaderID , InfoLogLength , NULL , & VertexShaderErrorMessage [ 0 ] ) ;
printf ( " % s\n" , & VertexShaderErrorMessage [ 0 ] ) ;
}
char const * FragmentSourcePointer = fShaderCode.c_str () ;
glShaderSource ( FragmentShaderID , 1 , & FragmentSourcePointer , NULL ) ;
glCompileShader ( FragmentShaderID ) ;
// Check Fragment Shader
glGetShaderiv ( FragmentShaderID , GL_COMPILE_STATUS , & Result ) ;
glGetShaderiv ( FragmentShaderID , GL_INFO_LOG_LENGTH , & InfoLogLength ) ;
if ( InfoLogLength > 0 ) {
std : : vector < char > FragmentShaderErrorMessage ( InfoLogLength + 1 ) ;
glGetShaderInfoLog ( FragmentShaderID , InfoLogLength , NULL , & FragmentShaderErrorMessage [ 0 ] ) ;
printf ( " % s\n" , & FragmentShaderErrorMessage [ 0 ] ) ;
}
programID = glCreateProgram () ;
glAttachShader ( programID , VertexShaderID ) ;
glAttachShader ( programID , FragmentShaderID ) ;
glLinkProgram ( programID ) ;
// Check the program
glGetProgramiv ( programID , GL_LINK_STATUS , & Result ) ;
glGetProgramiv ( programID , GL_INFO_LOG_LENGTH , & InfoLogLength ) ;
if ( InfoLogLength > 0 ) {
std : : vector < char > ProgramErrorMessage ( InfoLogLength + 1 ) ;
glGetProgramInfoLog ( programID , InfoLogLength , NULL , & ProgramErrorMessage [ 0 ] ) ;
printf ( " % s\n" , & ProgramErrorMessage [ 0 ] ) ;
}
glDeleteShader ( VertexShaderID ) ;
glDeleteShader ( FragmentShaderID ) ;
return fail;
}

loadtextfile.h

#ifndef LOADTEXTFILE_H_INCLUDED
#define LOADTEXTFILE_H_INCLUDED
#include < fstream >
std : : string LoadTextFromFile ( std : : string path ) ;
#endif // LOADTEXTFILE_H_INCLUDED

loadtextfile.cpp

#include "loadtextfile.h"
std : : string LoadTextFromFile ( std : : string path )
{
std : : ifstream sourceFile ( path.c_str () , std : : ios : : in ) ;
if ( sourceFile.is_open () )
{
std : : string content;
content.assign ( ( std : : istreambuf_iterator < char > ( sourceFile ) ) , std : : istreambuf_iterator < char > () ) ;
sourceFile.close () ;
return content;
}
else
{
return "error";
}
}

2nd.fs

#version 400
in vec4 ex_Color;
out vec4 out_Color;
void main ( void )
{
out_Color = ex_Color;
}

2nd.vs

#version 400
layout ( location = 0 ) in vec4 in_Position;
layout ( location = 1 ) in vec4 in_Color;
out vec4 ex_Color;
void main ( void )
{
gl_Position = in_Position;
ex_Color = in_Color;
}