SDL2とopenglの連携例

環境はwindows xp 32
以下のサイトを参考にしました
http://tacoika.blog87.fc2.com/blog-entry-322.html
http://d.hatena.ne.jp/yano-htn/20120226/1330263041
CMakeを使わず用意されているslnでコンパイルすることをお勧めします。CMakeは素人が触ればリンクエラーの宝庫です

#基本

```cpp:main.cpp
/* -*- coding:utf-8 -*- */

/**
 * sdl_with_opengl.cpp
 */
#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2main.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")

#include <SDL.h>
#include <SDL_opengl.h>
#include <GL/glu.h>

#include <iostream>
#include <string>

#include <cmath>

static const std::string WINDOW_CAPTION = "SDL with OpenGL";
static const Uint32 WINDOW_WIDTH = 640;
static const Uint32 WINDOW_HEIGHT = 480;
static const Uint32 WINDOW_BPP = 32;

static const Uint32 FPS = 60;

static SDL_Window* window;
static SDL_GLContext context;

bool init();
bool finalize();

void update();
void draw();
bool pollingEvent();

int main(int argc, char *argv[]) {
    // initialize
    if (!init()) {
        std::cerr << "ERROR: failed to initialize SDL" << std::endl;
        exit(1);
    }

    // mainloop
    static const Uint32 interval = 1000 / FPS;
    static Uint32 nextTime = SDL_GetTicks() + interval;
    bool skipDraw = false;
    while (true) {
        // check event
        if (!pollingEvent()) break;

        // update and draw
        update();
        if (!skipDraw) {
            draw();
            SDL_GL_SwapWindow(window);
        }

        int delayTime = (int)(nextTime - SDL_GetTicks());
        if (delayTime > 0) {
            SDL_Delay((Uint32)delayTime);
            skipDraw = false;
        } else {
            // skip next draw step because of no time
            skipDraw = true;
        }

        nextTime += interval;
    }

    // finalize
    finalize();
  
    return 0;
}

bool init() {
    // initialize SDL
    if( SDL_Init(SDL_INIT_VIDEO) < 0 ) return false;

    // enable double buffering
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    // create indow
    // set SDL_WINDOW_OPENGL to use opengl for drawing
    window = SDL_CreateWindow(WINDOW_CAPTION.c_str(),
                              SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
                              WINDOW_WIDTH, WINDOW_HEIGHT,
                              SDL_WINDOW_OPENGL);
    if (!window) return false;

    // create OpenGL context
    context = SDL_GL_CreateContext(window);
    if (!context) return false;

    // setup viewport
    glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glEnable(GL_DEPTH_TEST);

    // setup projection matrix
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, (GLdouble) WINDOW_WIDTH / (GLdouble) WINDOW_HEIGHT, 2.0, 200.0);

    // setup light
    static GLfloat position[] = {-10.0f, 10.0f, 10.0f, 1.0f};
    static GLfloat ambient [] = { 1.0f, 1.0f, 1.0f, 1.0f};
    static GLfloat diffuse [] = { 1.0f, 1.0f, 1.0f, 1.0f};
    static GLfloat specular[] = { 0.0f, 0.0f, 0.0f, 0.0f};
    glLightfv(GL_LIGHT0, GL_POSITION, position);
    glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
    glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    return true;
}

bool finalize() {
  // finalize SDL
  SDL_Quit();

  return true;
}

void update() {
}

void draw() {
    // clear
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // setup view
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt( 0.0f,  0.0f,-30.0f,
               0.0f,  0.0f, 0.0f,
               0.0f, -1.0f, 0.0f);

    // setup material
    GLfloat ambient  [] = { 0.1f, 0.1f, 0.1f, 1.0f};
    GLfloat diffuse  [] = { 1.0f, 0.0f, 0.0f, 1.0f};
    GLfloat specular [] = { 1.0f, 1.0f, 1.0f, 1.0f};
    GLfloat shininess[] = { 0.0f};
    glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, shininess);

    // draw sphere
    GLUquadric* quadric = gluNewQuadric();
    gluSphere(quadric, 10.0, 30, 30);
    gluDeleteQuadric(quadric);
}

// polling event and execute actions
bool pollingEvent()
{
    SDL_Event ev;
    SDL_Keycode key;
    while ( SDL_PollEvent(&ev) )
    {
        switch(ev.type){
        case SDL_QUIT:
            // raise when exit event is occur
            return false;
            break;
        case SDL_KEYDOWN:
        // raise when key down
        {
            key = ev.key.keysym.sym;
            // ESC
            if(key == SDLK_ESCAPE){
                return false;
            }
        }
        break;
        }
    }
    return true;
}
```

#分離(やってることは基本と同じ)
冗長だからSDLとopenglの結合部分をクラスにして隠蔽した。
このsdlglを継承してdrawの中身だけを書けばいい。

```cpp:sdlgl.h
#pragma	once
#pragma comment(lib,"SDL2.lib")
#pragma comment(lib,"SDL2main.lib")
#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")
#include <SDL.h>
#include <SDL_opengl.h>
#include <GL/glu.h>

class	SDLGL{
	void	setview(int w,int h){
		// setup viewport&projection
		glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		glEnable(GL_DEPTH_TEST);
		glViewport(0, 0, w, h);
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		perspective(w,h);
		//glOrtho(0 , w , h , 0 , 2 , 200);
	}
	bool finalize() {
	  // finalize SDL
	  SDL_Quit();
	  return true;
	}
	// polling event and execute actions
	bool pollingEvent(){
		SDL_Event ev;
		SDL_Keycode key;
		while ( SDL_PollEvent(&ev) )
		{
			switch(ev.type){
				case	SDL_WINDOWEVENT:
					if(ev.window.event==SDL_WINDOWEVENT_RESIZED)setview(ev.window.data1,ev.window.data2);
					break;
				case	SDL_QUIT:
					// raise when exit event is occur
					return false;
					break;
				case SDL_KEYDOWN:
				// raise when key down
				{
					key = ev.key.keysym.sym;
					// ESC
					if(key == SDLK_ESCAPE){
						return false;
					}
				}
				break;
			}
		}
		return true;
	}
public:
	signed	start(char*title,int w=600,int h=400){
		SDL_Window* window;
		SDL_GLContext context;
		// initialize SDL
		if( SDL_Init(SDL_INIT_VIDEO) < 0 ) return false;

		// enable double buffering
		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

		// create indow
		// set SDL_WINDOW_OPENGL to use opengl for drawing
		window = SDL_CreateWindow(title,
								  SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
								  w, h,
								  SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
		if (!window)return 1;

		// create OpenGL context
		context = SDL_GL_CreateContext(window);
		if (!context)return 1;

		// setup viewport&projection
		setview(w, h);

		// setup light
		static GLfloat position[] = {-10.0f, 10.0f, 10.0f, 1.0f};
		static GLfloat ambient [] = { 1.0f, 1.0f, 1.0f, 1.0f};
		static GLfloat diffuse [] = { 1.0f, 1.0f, 1.0f, 1.0f};
		static GLfloat specular[] = { 0.0f, 0.0f, 0.0f, 0.0f};
		glLightfv(GL_LIGHT0, GL_POSITION, position);
		glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
		glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
		glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
		glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
		glEnable(GL_LIGHTING);
		glEnable(GL_LIGHT0);

		// mainloop
		while (true) {
			// check event
			if (!pollingEvent()) break;
			//draw
		    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
			draw();
			SDL_GL_SwapWindow(window);
		}

		// finalize
		finalize();
		return	0;
	}
	virtual	void	draw(){
		// setup view
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt( 0.0f,  0.0f,-30.0f,
				   0.0f,  0.0f, 0.0f,
				   0.0f, -1.0f, 0.0f);

		// setup material
		GLfloat ambient  [] = { 0.1f, 0.1f, 0.1f, 1.0f};
		GLfloat diffuse  [] = { 1.0f, 0.0f, 0.0f, 1.0f};
		GLfloat specular [] = { 1.0f, 1.0f, 1.0f, 1.0f};
		GLfloat shininess[] = { 0.0f};
		glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
		glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
		glMaterialfv(GL_FRONT, GL_SHININESS, shininess);

		// draw sphere
		GLUquadric* quadric = gluNewQuadric();
		gluSphere(quadric, 10.0, 30, 30);
		gluDeleteQuadric(quadric);
	}
	virtual	void	perspective(int w,int h){
		gluPerspective(45.0, (GLdouble) w / (GLdouble) h, 2.0, 200.0);
	}
};
```

```cpp:main.cpp
#include"sdlgl.h"

struct	MYSDLGL:public	SDLGL{
	virtual	void	perspective(int w,int h){
		gluPerspective(45.0, (GLdouble) w / (GLdouble) h, 2.0, 200.0);
	}
	virtual	void	draw(){
		// setup view
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt( 0.0f,  0.0f,-30.0f,
				   0.0f,  0.0f, 0.0f,
				   0.0f, -1.0f, 0.0f);

		// setup material
		GLfloat ambient  [] = { 0.1f, 0.1f, 0.1f, 1.0f};
		GLfloat diffuse  [] = { 1.0f, 0.0f, 0.0f, 1.0f};
		GLfloat specular [] = { 1.0f, 1.0f, 1.0f, 1.0f};
		GLfloat shininess[] = { 0.0f};
		glMaterialfv(GL_FRONT, GL_AMBIENT, ambient);
		glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse);
		glMaterialfv(GL_FRONT, GL_SPECULAR, specular);
		glMaterialfv(GL_FRONT, GL_SHININESS, shininess);

		// draw sphere
		GLUquadric* quadric = gluNewQuadric();
		gluSphere(quadric, 10.0, 30, 30);
		gluDeleteQuadric(quadric);
	}
};
int main(int argc, char *argv[]){
	MYSDLGL	gl;
	gl.start("nemui");
	return	0;
}
```