Difference between revisions of "Tutorial1: Creating a Cross Platform OpenGL 3.2 Context in SDL (C / SDL)"

From OpenGL Wiki
Jump to navigation Jump to search
m (Added {{tutorial c sdl}})
 
(16 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
{{tutorial c sdl}}
 +
 
== Overview ==
 
== Overview ==
  
This tutorial is designed to help explain the process of creating an OpenGL 3.2 context using libsdl.
+
This tutorial is designed to help explain the process of creating an OpenGL 3.2 context using SDL.
  
 
This tutorial has the following requirements:
 
This tutorial has the following requirements:
  
<ul>
+
* An OpenGL 3.2 compatible video card. (Currently an NVDIA G80 or ATI R600 or newer GPU)
<li/>An OpenGL 3.2 compatible video card. (Currently an NVDIA G80 or ATI R600 or newer GPU)
+
* An OpenGL 3.2 video driver. (Most of the newer drivers)
<li/>An OpenGL 3.2 video driver. (Currently they are all beta versions)
+
* [http://www.libsdl.org/hg.php SDL 1.3] which is currently in development phase, but includes support for OpenGL 3 style contexts. On Windows machines you will need DirectX as a pre-requisite for this.
<li/>[http://www.libsdl.org/svn.php libsdl-1.3] which is currently in development phase, but includes support for OpenGL 3 style contexts.
+
* [http://www.opengl.org/registry/api/gl3.h gl3.h] installed in a 'GL3' directory. (e.g. mkdir /usr/include/GL3 ; mv gl3.h /usr/include/GL3 OR C:\Program Files\Microsoft Visual Studio 10.0\VC\include\GL3 etc.)
<li/>[http://www.opengl.org/registry/api/gl3.h gl3.h] installed in a 'GL3' directory. (e.g. mkdir /usr/include/GL3 ; mv gl3.h /usr/include/GL3)
+
:OR
</ul>
+
* [http://glew.sourceforge.net/index.html GLEW] may be required on certain systems in case gl3.h doesn't work <!-- and is a better option in the long run even if the gl3.h header works for your system. -->
  
The benefits of using libsdl are numerous, but in particular, it will allow our code to run on windows, mac, and unix / linux. My only computer which meets the above requirements runs linux, so I can guarantee compatibility with linux only. If you find problems compiling the code on other platforms, please make a note of it.
+
The benefits of using SDL are numerous, but in particular, it will allow our code to run on windows, mac, and unix / linux. This code has been tested on linux and windows only but should work fine on other systems also.
  
Creating a window in libsdl and binding an OpenGL 3.2 context to it uses these steps:
+
Creating a window in SDL and binding an OpenGL 3.2 context to it uses these steps:
  
<ul>
+
* Initialize the SDL video subsystem using SDL_Init or SDL_VideoInit. (We use SDL_Init in this example)
<li/>Initialize the SDL video subsystem using SDL_Init or SDL_VideoInit. (We use SDL_Init in this example)
+
* Set the parameters we require for opengl using SDL_GL_SetAttribute.
<li/>Set the parameters we require for opengl using SDL_GL_SetAttribute.
+
* Create a window using SDL_CreateWindow.
<li/>Create a window using SDL_CreateWindow.
+
* Bind an OpenGL context to the window using SDL_GL_CreateContext.
<li/>Bind an OpenGL context to the window using SDL_GL_CreateContext.
+
<!-- * If using GLEW, initialize GLEW so that it automatically loads all extensions for the current context. -->
</ul>
 
  
 
== The Code ==
 
== The Code ==
<pre>
+
<source lang="c">
 
#include <stdio.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <stdlib.h>
 +
/* If using gl3.h */
 
/* Ensure we are using opengl's core profile only */
 
/* Ensure we are using opengl's core profile only */
 
#define GL3_PROTOTYPES 1
 
#define GL3_PROTOTYPES 1
Line 36: Line 38:
 
/* A simple function that prints a message, the error code returned by SDL,
 
/* A simple function that prints a message, the error code returned by SDL,
 
  * and quits the application */
 
  * and quits the application */
void sdldie(char *msg)
+
void sdldie(const char *msg)
 
{
 
{
 
     printf("%s: %s\n", msg, SDL_GetError());
 
     printf("%s: %s\n", msg, SDL_GetError());
Line 42: Line 44:
 
     exit(1);
 
     exit(1);
 
}
 
}
 +
 +
 +
void checkSDLError(int line = -1)
 +
{
 +
#ifndef NDEBUG
 +
const char *error = SDL_GetError();
 +
if (*error != '\0')
 +
{
 +
printf("SDL Error: %s\n", error);
 +
if (line != -1)
 +
printf(" + line: %i\n", line);
 +
SDL_ClearError();
 +
}
 +
#endif
 +
}
 +
  
 
/* Our program's entry point */
 
/* Our program's entry point */
 
int main(int argc, char *argv[])
 
int main(int argc, char *argv[])
 
{
 
{
     SDL_WindowID mainwindow; /* Our window handle */
+
     SDL_Window *mainwindow; /* Our window handle */
 
     SDL_GLContext maincontext; /* Our opengl context handle */
 
     SDL_GLContext maincontext; /* Our opengl context handle */
  
Line 52: Line 70:
 
         sdldie("Unable to initialize SDL"); /* Or die on error */
 
         sdldie("Unable to initialize SDL"); /* Or die on error */
  
     /* Request an opengl 3.2 context.
+
     /* Request opengl 3.2 context.
 
     * SDL doesn't have the ability to choose which profile at this time of writing,
 
     * SDL doesn't have the ability to choose which profile at this time of writing,
 
     * but it should default to the core profile */
 
     * but it should default to the core profile */
Line 68: Line 86:
 
     if (!mainwindow) /* Die if creation failed */
 
     if (!mainwindow) /* Die if creation failed */
 
         sdldie("Unable to create window");
 
         sdldie("Unable to create window");
 +
 +
    checkSDLError(__LINE__);
  
 
     /* Create our opengl context and attach it to our window */
 
     /* Create our opengl context and attach it to our window */
 
     maincontext = SDL_GL_CreateContext(mainwindow);
 
     maincontext = SDL_GL_CreateContext(mainwindow);
 +
    checkSDLError(__LINE__);
 +
  
 
     /* This makes our buffer swap syncronized with the monitor's vertical refresh */
 
     /* This makes our buffer swap syncronized with the monitor's vertical refresh */
Line 102: Line 124:
 
     return 0;
 
     return 0;
 
}
 
}
</pre>
+
</source>
  
 
== Compilation ==
 
== Compilation ==
 
On linux:
 
On linux:
 
gcc tutorial1.c -o tutorial1 -lGL $(sdl-config --cflags --libs)
 
gcc tutorial1.c -o tutorial1 -lGL $(sdl-config --cflags --libs)
 +
 +
<!-- If you are using GLEW add -lGLEW so that the command becomes:
 +
gcc tutorial1.c -o tutorial1 -lGL -lGLEW $(sdl-config --cflags --libs) -->
  
 
If you have libsdl-1.2 and libsdl-1.3 both installed, make sure to run the appropriate version of sdl-config. For example if you installed sdl-1.3 to /usr/local:
 
If you have libsdl-1.2 and libsdl-1.3 both installed, make sure to run the appropriate version of sdl-config. For example if you installed sdl-1.3 to /usr/local:
  
 
gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs)
 
gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs)
 +
 +
If you didn't install the gl3.h header file to /usr/include/GL3, you also have to specify the include directory:
 +
 +
gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs) -I[DIRECTORY_TO_GL3_DIRECTORY]
 +
 +
e. g.: gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs) -I/home/someuser/local/include
  
 
== Execution ==
 
== Execution ==

Latest revision as of 12:26, 13 April 2014

Overview

This tutorial is designed to help explain the process of creating an OpenGL 3.2 context using SDL.

This tutorial has the following requirements:

  • An OpenGL 3.2 compatible video card. (Currently an NVDIA G80 or ATI R600 or newer GPU)
  • An OpenGL 3.2 video driver. (Most of the newer drivers)
  • SDL 1.3 which is currently in development phase, but includes support for OpenGL 3 style contexts. On Windows machines you will need DirectX as a pre-requisite for this.
  • gl3.h installed in a 'GL3' directory. (e.g. mkdir /usr/include/GL3 ; mv gl3.h /usr/include/GL3 OR C:\Program Files\Microsoft Visual Studio 10.0\VC\include\GL3 etc.)
OR
  • GLEW may be required on certain systems in case gl3.h doesn't work

The benefits of using SDL are numerous, but in particular, it will allow our code to run on windows, mac, and unix / linux. This code has been tested on linux and windows only but should work fine on other systems also.

Creating a window in SDL and binding an OpenGL 3.2 context to it uses these steps:

  • Initialize the SDL video subsystem using SDL_Init or SDL_VideoInit. (We use SDL_Init in this example)
  • Set the parameters we require for opengl using SDL_GL_SetAttribute.
  • Create a window using SDL_CreateWindow.
  • Bind an OpenGL context to the window using SDL_GL_CreateContext.

The Code

#include <stdio.h>
#include <stdlib.h>
/* If using gl3.h */
/* Ensure we are using opengl's core profile only */
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>

#include <SDL.h>
#define PROGRAM_NAME "Tutorial1"

/* A simple function that prints a message, the error code returned by SDL,
 * and quits the application */
void sdldie(const char *msg)
{
    printf("%s: %s\n", msg, SDL_GetError());
    SDL_Quit();
    exit(1);
}


void checkSDLError(int line = -1)
{
#ifndef NDEBUG
	const char *error = SDL_GetError();
	if (*error != '\0')
	{
		printf("SDL Error: %s\n", error);
		if (line != -1)
			printf(" + line: %i\n", line);
		SDL_ClearError();
	}
#endif
}
 

/* Our program's entry point */
int main(int argc, char *argv[])
{
    SDL_Window *mainwindow; /* Our window handle */
    SDL_GLContext maincontext; /* Our opengl context handle */

    if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
        sdldie("Unable to initialize SDL"); /* Or die on error */

    /* Request opengl 3.2 context.
     * SDL doesn't have the ability to choose which profile at this time of writing,
     * but it should default to the core profile */
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);

    /* Turn on double buffering with a 24bit Z buffer.
     * You may need to change this to 16 or 32 for your system */
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

    /* Create our window centered at 512x512 resolution */
    mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
    if (!mainwindow) /* Die if creation failed */
        sdldie("Unable to create window");

    checkSDLError(__LINE__);

    /* Create our opengl context and attach it to our window */
    maincontext = SDL_GL_CreateContext(mainwindow);
    checkSDLError(__LINE__);


    /* This makes our buffer swap syncronized with the monitor's vertical refresh */
    SDL_GL_SetSwapInterval(1);

    /* Clear our buffer with a red background */
    glClearColor ( 1.0, 0.0, 0.0, 1.0 );
    glClear ( GL_COLOR_BUFFER_BIT );
    /* Swap our back buffer to the front */
    SDL_GL_SwapWindow(mainwindow);
    /* Wait 2 seconds */
    SDL_Delay(2000);

    /* Same as above, but green */
    glClearColor ( 0.0, 1.0, 0.0, 1.0 );
    glClear ( GL_COLOR_BUFFER_BIT );
    SDL_GL_SwapWindow(mainwindow);
    SDL_Delay(2000);

    /* Same as above, but blue */
    glClearColor ( 0.0, 0.0, 1.0, 1.0 );
    glClear ( GL_COLOR_BUFFER_BIT );
    SDL_GL_SwapWindow(mainwindow);
    SDL_Delay(2000);

    /* Delete our opengl context, destroy our window, and shutdown SDL */
    SDL_GL_DeleteContext(maincontext);
    SDL_DestroyWindow(mainwindow);
    SDL_Quit();

    return 0;
}

Compilation

On linux: gcc tutorial1.c -o tutorial1 -lGL $(sdl-config --cflags --libs)


If you have libsdl-1.2 and libsdl-1.3 both installed, make sure to run the appropriate version of sdl-config. For example if you installed sdl-1.3 to /usr/local:

gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs)

If you didn't install the gl3.h header file to /usr/include/GL3, you also have to specify the include directory:

gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs) -I[DIRECTORY_TO_GL3_DIRECTORY]

e. g.: gcc tutorial1.c -o tutorial1 -lGL $(/usr/local/bin/sdl-config --cflags --libs) -I/home/someuser/local/include

Execution

./tutorial1 The result should be a 512x512 window centered on your display showing a red, green, then blue background.