OpenGL+SDL
最近、OpenGLを勉強してて、なんで今までDirectXとか使ってたんだろうとか思ってきた。最近のビデオカードの性能をフルにひきだしたいとか、HLSLを使いたいとかじゃなくて、単に高速に2Dを描画したいだけだったら、はるかにOpenGL+SDLのほうが楽だと思う。
ということで、以下、OpenGL+SDLで四角形を描画するサンプル。
#include <SDL.h> #include <SDL_opengl.h> #include <stdio.h> const int SCREEN_WIDTH = 640; // 画面の幅 const int SCREEN_HEIGHT = 480; // 画面の高さ // 初期化する // 成功したときは0を、失敗したときは-1を返す int Initialize() { // SDLを初期化する if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "SDLの初期化に失敗しました:%s\n", SDL_GetError()); return -1; } // タイトルを設定する SDL_WM_SetCaption("OpenGL Sample", NULL); // 画面を初期化する SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_Surface* screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_OPENGL); if (screen == NULL) { fprintf(stderr, "画面の初期化に失敗しました:%s\n", SDL_GetError()); SDL_Quit(); return -1; } // 画面をクリアする色を指定する glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // 射影マトリクスを設定する glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1.0, 1.0); return 0; } // 更新する void Update() { } // 描画する void Draw() { // 画面をクリアする glClear(GL_COLOR_BUFFER_BIT); // 四角形を描く glBegin(GL_QUADS); // 描画色を白に設定 glColor3f(1.0, 1.0f, 1.0); // 4つの頂点を指定 glVertex3f(100.0f, 100.0f, 0); glVertex3f(540.0f, 100.0f, 0); glVertex3f(540.0f, 380.0f, 0); glVertex3f(100.0f, 380.0f, 0); glEnd(); // 更新を画面に反映する SDL_GL_SwapBuffers(); } // メインループ void MainLoop() { SDL_Event event; double next_frame = SDL_GetTicks(); double wait = 1000.0 / 60; for (;;) { // すべてのイベントを処理する while (SDL_PollEvent(&event)) { // QUIT イベントが発生するか、ESC キーが押されたら終了する if ((event.type == SDL_QUIT) || (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE)) return; } // 1秒間に60回Updateされるようにする if (SDL_GetTicks() >= next_frame) { Update(); // 時間がまだあるときはDrawする if (SDL_GetTicks() < next_frame + wait) Draw(); next_frame += wait; SDL_Delay(0); } } } // 終了処理を行なう void Finalize() { SDL_Quit(); } // メイン関数 int main(int argc, char* argv[]) { if (Initialize() < 0) return 1; MainLoop(); Finalize(); return 0; }
さらにもうひとつ。リサジュー曲線。
#include <SDL.h> #include <SDL_opengl.h> #include <stdio.h> #include <math.h> const int SCREEN_WIDTH = 640; // 画面の幅 const int SCREEN_HEIGHT = 480; // 画面の高さ float t = 0; // 初期化する // 成功したときは0を、失敗したときは-1を返す int Initialize() { // SDLを初期化する if (SDL_Init(SDL_INIT_VIDEO) < 0) { fprintf(stderr, "SDLの初期化に失敗しました:%s\n", SDL_GetError()); return -1; } // タイトルを設定する SDL_WM_SetCaption("OpenGL Sample", NULL); // 画面を初期化する SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_Surface* screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_OPENGL); if (screen == NULL) { fprintf(stderr, "画面の初期化に失敗しました:%s\n", SDL_GetError()); SDL_Quit(); return -1; } // 画面をクリアする色を指定する glClearColor(1.0f, 0.5f, 0.0f, 0.0f); // 射影マトリクスを設定する glOrtho(0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, -1.0, 1.0); return 0; } // 更新する void Update() { t += 0.01f; } // 描画する void Draw() { const int N = 500; // 頂点の数 const float PI = 3.141592f; // 円周率 glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_LOOP); for (int i = 0; i < N; ++i) { glVertex3f(300*cos(3*2*PI*i/N + t) + 320, 220*sin(5*2*PI*i/N - PI/4 + t) + 240, 0.0); } glEnd(); // 更新を画面に反映する SDL_GL_SwapBuffers(); } // メインループ void MainLoop() { SDL_Event event; double next_frame = SDL_GetTicks(); double wait = 1000.0 / 60; for (;;) { // すべてのイベントを処理する while (SDL_PollEvent(&event)) { // QUIT イベントが発生するか、ESC キーが押されたら終了する if ((event.type == SDL_QUIT) || (event.type == SDL_KEYUP && event.key.keysym.sym == SDLK_ESCAPE)) return; } // 1秒間に60回Updateされるようにする if (SDL_GetTicks() >= next_frame) { Update(); // 時間がまだあるときはDrawする if (SDL_GetTicks() < next_frame + wait) Draw(); next_frame += wait; SDL_Delay(0); } } } // 終了処理を行なう void Finalize() { SDL_Quit(); } // メイン関数 int main(int argc, char* argv[]) { if (Initialize() < 0) return 1; MainLoop(); Finalize(); return 0; }