--- gll.c.orig 2004-02-06 13:05:57.000000000 +0900 +++ gll.c 2004-02-06 13:00:45.000000000 +0900 @@ -10,11 +10,232 @@ #include #include +#include + #include #include static GLboolean should_rotate = GL_TRUE; +static int count; + +void SDL_GL_Enter2DMode() +{ + SDL_Surface *screen = SDL_GetVideoSurface(); + + /* Note, there may be other things you need to change, + depending on how you have your OpenGL state set up. + */ + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + + /* This allows alpha blending of 2D textures with the scene */ + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, screen->w, screen->h); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); +} + +void SDL_GL_Leave2DMode() +{ + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glPopAttrib(); +} + +/* Quick utility function for texture creation */ +static int power_of_two(int input) +{ + int value = 1; + + while ( value < input ) { + value <<= 1; + } + return value; +} + +GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) +{ + GLuint texture; + int w, h; + SDL_Surface *image, *_image; + SDL_Rect area; + Uint32 saved_flags; + Uint8 saved_alpha; + + /* Use the surface width and height expanded to powers of 2 */ + w = power_of_two(surface->w); + h = power_of_two(surface->h); + texcoord[0] = 0.0f; /* Min X */ + texcoord[1] = 0.0f; /* Min Y */ + texcoord[2] = (GLfloat)surface->w / w; /* Max X */ + texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ + + image = SDL_CreateRGBSurface( + SDL_SWSURFACE, + w, h, + 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + ); + if ( image == NULL ) { + return 0; + } + + /* Save the alpha blending attributes */ + saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + saved_alpha = surface->format->alpha; + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, 0, 0); + } + + /* Copy the surface into the GL texture image */ + area.x = 0; + area.y = 0; + area.w = surface->w; + area.h = surface->h; + SDL_BlitSurface(surface, &area, image, &area); + + /* Restore the alpha blending attributes */ + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, saved_flags, saved_alpha); + } + { + int xx, yy; + Uint32* ptr; + Uint32 key = image->format->colorkey; + for(yy = 0; yy < surface->h; yy++){ + ptr = (Uint32*)(image->pixels + image->pitch * yy); + for(xx = 0; xx < surface->w; xx++){ + if(*ptr == key){ + // alpha -> 0 + *ptr &= surface->format->Rmask | + surface->format->Gmask | + surface->format->Bmask; + } else { + *ptr |= surface->format->Amask; + } + ptr++; + } + } + } + /* Create an OpenGL texture for the image */ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + w, h, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + image->pixels); + SDL_FreeSurface(image); /* No longer needed */ + + return texture; +} + +static Kanji_Font* font; + +static void show_fps() +{ + static Uint32 tickOrigin = 0; + static char str[0x100]; + Uint32 tickNow, ticks; + SDL_Surface* text; + GLuint texture; + GLfloat texcoord[4]; + GLfloat texMinX, texMinY, texMaxX, texMaxY; + int x, y, w, h; + SDL_Color color; + + if(tickOrigin == 0){ + tickOrigin = SDL_GetTicks(); + } + tickNow = SDL_GetTicks(); + ticks = tickNow - tickOrigin; + if(ticks <= 0) return; + + sprintf(str, "%d frames in %d ticks (%d fps)", + count, + ticks, + (count * 1000/ ticks)); + color.r = color.g = 255; + color.b = 0; + + text = Kanji_CreateSurface(font, str, color, 32); + + if(text == NULL) return; + texture = SDL_GL_LoadTexture(text, texcoord); + texMinX = texcoord[0]; + texMinY = texcoord[1]; + texMaxX = texcoord[2]; + texMaxY = texcoord[3]; + { + SDL_Surface* screen = SDL_GetVideoSurface(); + x = screen->w - text->w; + y = screen->h - text->h; + w = text->w; + h = text->h; + x /= 2; + y /= 2; + } + + + SDL_FreeSurface(text); + + if(texture == 0) return; + SDL_GL_Enter2DMode(); + glBindTexture(GL_TEXTURE_2D, texture); + glBegin(GL_TRIANGLE_STRIP); +// glColor4d(0.0, 0.0, 0.0, 0.5); + glTexCoord2f(texMinX, texMinY); glVertex2i(x, y ); +// glColor4d(0.0, 0.0, 0.0, 0.5); + glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y ); +// glColor4d(0.0, 0.0, 0.0, 0.5); + glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y+h); +// glColor4d(0.0, 0.0, 0.0, 0.5); + glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h); + glEnd(); + SDL_GL_Leave2DMode(); +} + +static void setup_font() +{ + font = Kanji_OpenFont("6x12.bdf", 12); + if(font == NULL) return; + Kanji_SetCodingSystem(font, KANJI_EUC); +} + static void quit_tutorial( int code ) { /* @@ -215,6 +436,8 @@ glEnd( ); + count++; + show_fps(); /* * 練習: * 'Spc' で回転停止、'Esc' で終了することを @@ -337,7 +560,7 @@ * ウィンドウ状態で開始するオプションを作り、 * glViewPort でリサイズイベントを適切に処理せよ。 */ - flags = SDL_OPENGL | SDL_FULLSCREEN; + flags = SDL_OPENGL; /* * Set the video mode @@ -359,6 +582,8 @@ */ setup_opengl( width, height ); + setup_font(); + /* * さて、通常のアプリケーション処理 -- たくさんの再描画と * イベントループを始めたい。