Create text textures only once

parent d40e5496
...@@ -22,11 +22,23 @@ ...@@ -22,11 +22,23 @@
#include <cmath> #include <cmath>
#include <string> #include <string>
#include <vector>
#include <SDL_ttf.h> #include <SDL_ttf.h>
#include <SDL_opengl.h> #include <SDL_opengl.h>
class Text class Text
{ {
private:
/** OpenGL textures containing the text */
std::vector<GLuint> textures;
/** Width of each text */
std::vector<int> width;
/** Height of each text */
std::vector<int> height;
/** Index of the next text, that should be rendered */
int nextText;
public: public:
Text() Text()
{ {
...@@ -45,6 +57,9 @@ public: ...@@ -45,6 +57,9 @@ public:
~Text() ~Text()
{ {
// We assume that std::vector is just an array ...
glDeleteTextures(textures.size(), &textures[0]);
instances--; instances--;
if (instances == 0) { if (instances == 0) {
...@@ -53,6 +68,34 @@ public: ...@@ -53,6 +68,34 @@ public:
} }
} }
void addText(const char* text)
{
if (!font)
return;
// Draw string
SDL_Color black = {0, 0, 0, 255};
SDL_Surface* surf = TTF_RenderText_Blended(font, text, black);
if (surf) {
GLuint texture;
/* Tell GL about our new texture */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, 4, surf->w, surf->h, 0, GL_BGRA,
GL_UNSIGNED_BYTE, surf->pixels);
width.push_back(surf->w);
height.push_back(surf->h);
textures.push_back(texture);
/* Clean up */
SDL_FreeSurface(surf);
}
}
void startTextMode() void startTextMode()
{ {
// Enable 2D mode // Enable 2D mode
...@@ -70,68 +113,60 @@ public: ...@@ -70,68 +113,60 @@ public:
glLoadIdentity(); glLoadIdentity();
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
nextText = 0;
} }
void showText(const char* text, SDL_Rect &location) /**
* @return True there are more textures
*/
bool showNextText(SDL_Rect &location)
{ {
if (!font) if (!font)
return; return false;
// Draw string if (nextText >= textures.size())
SDL_Color black = {0, 0, 0, 255}; // No more textures to show
SDL_Surface* surf = TTF_RenderText_Blended(font, text, black); return false;
if (surf) { /* GL_NEAREST looks horrible, if scaled... */
unsigned int texture; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* Tell GL about our new texture */
glGenTextures(1, &texture); /* prepare to render our texture */
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, textures[nextText]);
glTexImage2D(GL_TEXTURE_2D, 0, 4, surf->w, surf->h, 0, GL_BGRA,
GL_UNSIGNED_BYTE, surf->pixels); /* Draw a quad at location */
glBegin(GL_QUADS);
/* GL_NEAREST looks horrible, if scaled... */ /* Recall that the origin is in the lower-left corner
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); That is why the TexCoords specify different corners
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); than the Vertex coords seem to. */
glTexCoord2f(0.0f, 1.0f);
/* prepare to render our texture */ glVertex2f(location.x, location.y - height[nextText]);
glEnable(GL_TEXTURE_2D); glTexCoord2f(1.0f, 1.0f);
glBindTexture(GL_TEXTURE_2D, texture); glVertex2f(location.x + width[nextText], location.y - height[nextText]);
glColor3f(1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f);
glVertex2f(location.x + width[nextText], location.y);
/* Draw a quad at location */ glTexCoord2f(0.0f, 0.0f);
glBegin(GL_QUADS); glVertex2f(location.x, location.y);
/* Recall that the origin is in the lower-left corner glEnd();
That is why the TexCoords specify different corners
than the Vertex coords seem to. */ /* return the deltas in the unused w,h part of the rect */
glTexCoord2f(0.0f, 1.0f); location.w = width[nextText];
glVertex2f(location.x, location.y - surf->h); location.h = height[nextText];
glTexCoord2f(1.0f, 1.0f);
glVertex2f(location.x + surf->w, location.y - surf->h); nextText++;
glTexCoord2f(1.0f, 0.0f);
glVertex2f(location.x + surf->w, location.y); return nextText < textures.size();
glTexCoord2f(0.0f, 0.0f);
glVertex2f(location.x, location.y);
glEnd();
/* Bad things happen if we delete the texture before it finishes */
glFinish();
/* return the deltas in the unused w,h part of the rect */
location.w = surf->w;
location.h = surf->h;
/* Clean up */
SDL_FreeSurface(surf);
glDeleteTextures(1, &texture);
}
} }
void endTextMode() void endTextMode()
{ {
// Disable 2D mode // Disable 2D mode
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPopMatrix(); glPopMatrix();
......
...@@ -50,6 +50,21 @@ Visualization::Visualization(int windowWidth, int windowHeight, const char* wind ...@@ -50,6 +50,21 @@ Visualization::Visualization(int windowWidth, int windowHeight, const char* wind
initCUDA(); initCUDA();
#ifdef USESDLTTF #ifdef USESDLTTF
text = new Text(); text = new Text();
text->addText("Keys:");
#ifdef ASAGI
text->addText(" 1-7: Select scenario");
#else // ASAGI
text->addText(" 1-3: Select scenario");
#endif // ASAGI
text->addText(" Space: Pause/Resume");
text->addText(" ->: Next frame (when paused)");
text->addText(" r: Restart scenario");
text->addText(" +/-: Scale wave height");
text->addText("Mouse:");
text->addText(" Left button: rotate");
text->addText(" Right button: move");
text->addText(" Middle button: reset camera");
text->addText(" Wheel: zoom in/out");
#endif // USESDLTTF #endif // USESDLTTF
// Load camera and shaders // Load camera and shaders
...@@ -141,31 +156,8 @@ void Visualization::renderDisplay() { ...@@ -141,31 +156,8 @@ void Visualization::renderDisplay() {
#ifdef USESDLTTF #ifdef USESDLTTF
text->startTextMode(); text->startTextMode();
SDL_Rect location = {5, windowHeight-5, 0, 0}; SDL_Rect location = {5, windowHeight-5, 0, 0};
text->showText("Keys:", location); while (text->showNextText(location))
location.y -= location.h; location.y -= location.h;
#ifdef ASAGI
text->showText(" 1-7: Select scenario", location);
#else // ASAGI
text->showText(" 1-3: Select scenario", location);
#endif // ASAGI
location.y -= location.h;
text->showText(" Space: Pause/Resume", location);
location.y -= location.h;
text->showText(" ->: Next frame (when paused)", location);
location.y -= location.h;
text->showText(" r: Restart scenario", location);
location.y -= location.h;
text->showText(" +/-: Scale wave height", location);
location.y -= location.h;
text->showText("Mouse:", location);
location.y -= location.h;
text->showText(" Left button: rotate", location);
location.y -= location.h;
text->showText(" Right button: move", location);
location.y -= location.h;
text->showText(" Middle button: reset camera", location);
location.y -= location.h;
text->showText(" Wheel: zoom in/out", location);
text->endTextMode(); text->endTextMode();
#endif // USESDLTTF #endif // USESDLTTF
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment