Tutorial1: Creating a Cross Platform OpenGL 3.2 Context in SDL (C / SDL)

From OpenGL.org
Jump to: navigation, search

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.