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

From OpenGL Wiki
Revision as of 18:58, 19 February 2011 by Sunnyps (talk | contribs) (→‎The Code)
Jump to navigation Jump to search

Overview

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

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.
  • gl3.h installed in a 'GL3' directory. (e.g. mkdir /usr/include/GL3 ; mv gl3.h /usr/include/GL3)
OR
  • 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 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.
  • If using GLEW, initialize GLEW so that it automatically loads all extensions for the current context.

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>

/* If using GLEW */
#include <GL/glew.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(char *msg)
{
    printf("%s: %s\n", msg, SDL_GetError());
    SDL_Quit();
    exit(1);
}

/* 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 an 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");

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

    /* If using GLEW */
    GLenum err = glewInit();
    if (err != GLEW_OK)
        sdldie("Unable to initialize GLEW");

    /* 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)

Execution

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