SDLとOpenGLをとりあえず組み合わせてみる
SDLとOpenGLの連携
SDLでは描画部分にOpenGLを使うことができる。
試しにSDL2.0で使ってみる。
参考:
http://content.gpwiki.org/index.php/SDL:Tutorials:Using_SDL_with_OpenGL
http://www.ownway.info/Graphics/index.php?SDL%2BOpenGL
http://homepage3.nifty.com/li-chu/OpenGL/OpenGL04.html
初期化
とりあえずSDL2.0とOpenGLとの連携において初期がで気をつけることは次の3つぐらい?
DoubleBufferingの有効化
// enable double buffering SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_CreateWindowでSDL_WINDOW_OPENGLを指定する
SDL1.2ではSDL_SetVideoModeでやってた処理
static SDL_Window* window; /* --- skip --- */ // 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;
試しに書いてみた
赤い球体を表示するコード、SDL2.0の初期化以外は
http://www.ownway.info/Graphics/index.php?cmd=read&page=SDL%2BOpenGL%2F2.%B5%E5%A4%F2%C9%C1%B2%E8%A4%B9%A4%EB
で公開されているサンプルコードを利用。
/* -*- coding:utf-8 -*- */ /** * sdl_with_opengl.cpp */ #include <SDL.h> #include <SDL_opengl.h> #include <OpenGL/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() { // 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; }
コンパイルは次のようにする
$ g++ -o sdl_with_opengl sdl_with_opengl.cpp `sdl2-config --cflags` `sdl2-config --libs` -framework GLUT -framework OpenGL
<注意>開発環境はmacなので、Linuxとか他の環境だと方法が異なるはず。
違いは確かヘッダとコンパイルオプションで、Linuxの場合は
#include
-> #include
となって
g++ -o sdl_with_opengl sdl_with_opengl.cpp `sdl2-config --cflags` `sdl2-config --libs` -lGL -lGLU -lglut
とかだった気がする。
最低限の初期化の仕方はわかったけど、ビューポートとか視点とかOpenGLな部分がさっぱりなので、
そこを次は調べないといかんですね。
# 昔少しいじったはずなのにすっかり覚えてないorz