SDLの速度を試すと言うことでFPSを測る簡単なコードを書く。
開発には Eclipse + CDT を使った。
EclipseでSDLを使ったプログラムをコンパイルをする場合は
GCCに対して幾らかオプション指定の必要がある。
Project > Properties
から「C/C++ Build」を選び
「Configuration settings」内の
「GCC C++ Compiler」下にある
「Miscellaneous」を選び
「Other flags」のエディットボックスに
「`sdl-config --cflags`」と追記
「GCC C++ Linker」下にある
「Miscellaneous」を選び
「Linker flags」のエディットボックスに
「`sdl-config --libs`」と追記
…で動いたのだけど
何を意味しているのか良く分かっていない。
調べる必要があるなぁ。
で、簡単なソース。
ImageFunc の辺りはお遊び。
main.cpp
#include <stdlib.h>
#include "SDL.h"
#include "ImageFunc.h"
int main(int argc, char *argv[]) {
if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
exit(1);
}
atexit(SDL_Quit);
SDL_Surface *screen;
screen = SDL_SetVideoMode(640, 480, 16, SDL_SWSURFACE);
if ( screen == NULL ) {
exit(1);
}
// オフスクリーン作成
SDL_Surface* offscreen;
if (screen->format->BitsPerPixel == 16) {
offscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480,
screen->format->BitsPerPixel,
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask,
screen->format->Amask);
/*
printf("%d, %d, %d",
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask);
*/
} else {
offscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, 640, 480,
32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0);
}
int frames = 0;
Uint32 beginTime = SDL_GetTicks();
int hue = 0;
for (;;) {
// イベント処理
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
SDL_FreeSurface(offscreen);
exit(0);
}
}
// 描画部分
// SDL_MUSTLOCK(offscreen) の結果によってはロック不要らしい
SDL_LockSurface(offscreen);
double r, g, b;
HSVToRGB(&r, &g, &b, hue, 1.0, 1.0);
// offscreen->format に従ったフォーマットで書き込むこと
if (screen->format->BitsPerPixel == 16) {
Uint16 p = ((int)(31 * r) << 11)
| ((int)(63 * g) << 5)
| ((int)(31 * b) << 0);
for (int i=0; i<640*480; i++) {
((Uint16*)(offscreen->pixels))[i] = p;
}
} else {
Uint32 p = ((int)(255 * r) << 16)
| ((int)(255 * g) << 8)
| ((int)(255 * b) << 0);
for (int i=0; i<640*480; i++) {
((Uint32*)(offscreen->pixels))[i] = p;
}
}
hue++;
hue%=360;
SDL_UnlockSurface(offscreen);
// screenにbitmapを描画
SDL_BlitSurface(offscreen, NULL, screen, NULL);
// screenの全領域を更新
SDL_UpdateRect(screen,0,0,0,0);
frames++;
Uint32 t = SDL_GetTicks();
Uint32 d = t - beginTime;
if (d >= 1000) {
int fps = frames * 1000 / d;
char title[16];
sprintf(title, "%d", fps);
SDL_WM_SetCaption(title, NULL);
beginTime = t;
frames = 0;
}
}
SDL_FreeSurface(offscreen);
return 0;
}
ImageFunc.cpp
#include "ImageFunc.h"
#include <math.h>
#include <algorithm>
void RGBToHSV(double r, double g, double b, double* h, double *s, double *v)
{
// r, g, b それぞれ [0, 1]
// h は [0,360)
// s と v が [0, 1]
// ただし s = 0 の場合 h = UNDEF
const double UNDEF = 360.0;
double max = std::max( std::max(r, g), b);
double min = std::min( std::min(r, g), b);
*v = max; // バリュー
// 彩度の計算 r, g, b すべて 0 なら彩度は 0
*s = (max != 0.0) ? ((max - min) / max) : 0.0;
if(*s == 0.0){
*h = UNDEF;
}else{
double delta = max - min;
if(r == max){
*h = (g-b) / delta;
}else if(g == max){
*h = 2.0 + (b - r) / delta;
}else if(b == max){
*h = 4.0 + (r - g) / delta;
}
*h *= 60.0;
if(*h < 0.0) *h += 360.0;
}
}
bool HSVToRGB(double *r, double *g, double *b, double h, double s, double v)
{
// h は [0, 360] または UNDEF
// s と v は [0, 1]
// r, g, b それぞれ [0, 1]
//const double UNDEF = 360.0;
if(s == 0.0){
//if(h == UNDEF){
*r = v;
*g = v;
*b = v;
//}else{
// return false;
//}
}else{
double f, p, q, t;
int i;
if(h == 360.0) h = 0.0;
h /= 60.0; // h を [0, 6) とする
i = (int)floor(h); // floor() は最大整数 <= h を返す
f = h - i; // f は h の小数部分
p = v * (1.0 - s);
q = v * (1.0 - (s * f));
t = v * (1.0 - (s * (1.0 - f)));
switch(i){
case 0: *r = v; *g = t; *b = p; break;
case 1: *r = q; *g = v; *b = p; break;
case 2: *r = p; *g = v; *b = t; break;
case 3: *r = p; *g = q; *b = v; break;
case 4: *r = t; *g = p; *b = v; break;
case 5: *r = v; *g = p; *b = q; break;
}
}
return true;
}
ImageFunc.h
void RGBToHSV(double r, double g, double b, double* h, double *s, double *v);
bool HSVToRGB(double *r, double *g, double *b, double h, double s, double v);
実行するとウィンドウが出てキャプションにFPSが出ます。
僕の環境では11FPSでした。
…というのもVirtual PC上での実行だったので。