SDL, Opengl and SDL_ttf

Started by
0 comments, last by wyrzy 19 years, 4 months ago
I'm having problems getting SDL_ttf to work properly in opengl. Basically what I'm doing is rendering each character to a texture and then drawing gl_quads with that texture, but it doesn't seem to load or draw the texture. I've been looking at this code for a while but I can't figure out. Here is the relevant section.

class Text
{
 public:
  Text();
  ~Text();
  bool load_font(const char* filename);
  void write(GLfloat x, GLfloat y, char c);
 private:
  TTF_Font* font;
  GLuint textures[256];
};



bool Text::load_font(const char* filename)
{
  font = TTF_OpenFont(filename, 32);
  if(font == NULL)
  {
    printf("Could not load font %s.\n", filename);
    return false;
  }


  SDL_Color colour;
  colour.r = 255;
  colour.g = 255;
  colour.b = 255;

  glGenTextures(256, textures);
  SDL_Surface* glyph;
  SDL_Surface* temp = SDL_CreateRGBSurface(SDL_SRCALPHA | SDL_HWSURFACE, 128, 128, 32, screen->format->Rmask, screen->format->Gmask,
                                           screen->format->Bmask, screen->format->Amask);
  SDL_Rect erase;
  erase.h = 128;
  erase.w = 128;
  string letter;

  for(char c = ' '; c <= '~'; c++)
  {
    letter = c;
    glyph = TTF_RenderText_Blended(font, letter.c_str(), colour);
    SDL_BlitSurface(glyph, NULL, temp, NULL);
    glBindTexture(GL_TEXTURE_2D, textures[c]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, temp->w, temp->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    SDL_FreeSurface(glyph);
    SDL_FillRect(temp, &erase, 0x00000000);
  }


}

void Text::write(GLfloat x, GLfloat y, char c)
{
  glBindTexture(GL_TEXTURE_2D, textures[c]);
  glBegin(GL_QUADS);
    glTexCoord2f(0, 0);
    glVertex2f(x, y);
    glTexCoord2f(1, 0);
    glVertex2f(x + 64, y);
    glTexCoord2f(1, 1);
    glVertex2f(x + 64, y + 64);
    glTexCoord2f(0, 1);
    glVertex2f(x, y + 64);
  glEnd();


}

Advertisement
I saw a thread about this a few weeks ago. It was actually a refrence thread, meaning that someone wanted to post the code that would act as a stand-alone app using SDL, OpenGL, and SDL_ttf.

Here's the code C-Junkie posted, let me know if this works for you.
/* adjust these accordingly */char fontpath[] = "data/font/font.ttf";/*****************************************************************/int round(double x){	return (int)(x + 0.5);}/*****************************************************************/int nextpoweroftwo(int x){	double logbase2 = log(x) / log(2);	return round(pow(2,ceil(logbase2)));}/*****************************************************************/char *init_sdl(SDL_Surface** screen){	if(SDL_Init(SDL_INIT_VIDEO))		return SDL_GetError();	atexit(SDL_Quit);		*screen = SDL_SetVideoMode(screenwidth, screenheight, 0, SDL_OPENGL);		SDL_WM_SetCaption("C-Junkie's SDLGL text example", 0);		if(TTF_Init()==-1)		return TTF_GetError();	atexit(TTF_Quit);		return 0;}/*****************************************************************/void OGL_RenderText(char *text,                       TTF_Font *font,                      SDL_Color color,                      SDL_Rect *location){	SDL_Surface *initial;	SDL_Surface *intermediary;	SDL_Rect rect;	int w,h;	int texture;		// Use SDL_TTF to render our text	initial = TTF_RenderText_Blended(font, text, color);		// Convert the rendered text to a known format	w = nextpoweroftwo(initial->w);	h = nextpoweroftwo(initial->h);		intermediary = SDL_CreateRGBSurface(0, w, h, 32, 			0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);	SDL_BlitSurface(initial, 0, intermediary, 0);		// Tell GL about our new texture	glGenTextures(1, &texture);	glBindTexture(GL_TEXTURE_2D, texture);	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_BGRA, 			GL_UNSIGNED_BYTE, intermediary->pixels );		// GL_NEAREST looks horrible, if scaled...	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);		// prepare to render our texture	glEnable(GL_TEXTURE_2D);	glBindTexture(GL_TEXTURE_2D, texture);	glColor3f(1.0f, 1.0f, 1.0f);		// Draw a quad at location	glBegin(GL_QUADS);		// Recall that the origin is in the lower-left corner		//   That is why the TexCoords specify different corners		//   than the Vertex coors seem to.		glTexCoord2f(0.0f, 1.0f); glVertex2f(location->x    , location->y);		glTexCoord2f(1.0f, 1.0f); glVertex2f(location->x + w, location->y);		glTexCoord2f(1.0f, 0.0f); glVertex2f(location->x + w, location->y + h);		glTexCoord2f(0.0f, 0.0f); glVertex2f(location->x    , location->y + h);	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 = initial->w;	location->h = initial->h;		// Clean up	SDL_FreeSurface(initial);	SDL_FreeSurface(intermediary);	glDeleteTextures(1, &texture);}/*****************************************************************/void glEnable2D(){	int vPort[4];  	glGetIntegerv(GL_VIEWPORT, vPort);  	glMatrixMode(GL_PROJECTION);	glPushMatrix();	glLoadIdentity();  	glOrtho(0, vPort[2], 0, vPort[3], -1, 1);	glMatrixMode(GL_MODELVIEW);	glPushMatrix();	glLoadIdentity();}/*****************************************************************/void glDisable2D(){	glMatrixMode(GL_PROJECTION);	glPopMatrix();   	glMatrixMode(GL_MODELVIEW);	glPopMatrix();	}/*****************************************************************/void init_gl(){	// Irrelevant stuff for this demo 	glShadeModel(GL_SMOOTH);	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	glClearDepth(1.0f);	glDepthFunc(GL_LEQUAL);	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);		// Required if you want alpha-blended textures (for our fonts)   	glBlendFunc(GL_ONE, GL_ONE);	glEnable(GL_BLEND);		// Required setup stuff 	glViewport(0, 0, 800, 600);	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	gluPerspective(45.0f, screenwidth / (float)screenheight, 0.1f, 50.0f);	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();	}/*****************************************************************/int main(){	SDL_Surface *screen;	TTF_Font* font;	char *err;	SDL_Color color;	SDL_Rect position;	SDL_Event event;	int done;		// Do boring initialization	if((err = init_sdl(&screen))) {		printf("Error while initializing: %s", err);		return 1;	}		if(!(font = TTF_OpenFont(fontpath, 20))) {		printf("Error loading font: %s", TTF_GetError());		return 1;	}		init_gl();	done = 0;	while(!done)   {		// render a fun litte quad		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		glLoadIdentity();		glTranslatef(0.0f, 0.0f, -5.0f);		glDisable(GL_TEXTURE_2D);				glBegin(GL_QUADS);			glNormal3f(0.0f, 0.0f, 1.0f);			glColor3f(0.5f, 0.0f, 0.0f); glVertex3f(-1.5f, -1.0f,  1.0f);			glColor3f(0.0f, 0.5f, 0.0f); glVertex3f( 1.0f, -2.0f,  1.0f);			glColor3f(0.0f, 0.0f, 0.5f); glVertex3f( 1.5f,  1.0f,  1.0f);			glColor3f(0.5f, 0.0f, 0.0f); glVertex3f(-2.0f,  1.0f, -1.0f);		glEnd();				// Go in HUD-drawing mode		glEnable2D();		glDisable(GL_DEPTH_TEST);				// Draw some text		color.r = 255;		color.g = 255;		color.b = 255;		/** A quick note about position.		 * Enable2D puts the origin in the lower-left corner of the		 * screen, which is different from the normal coordinate		 * space of most 2D api's. position, therefore,		 * gives the X,Y coordinates of the lower-left corner of the		 * rectangle **/		position.x = screenwidth / 3;		position.y = screenheight / 2;		SDL_GL_RenderText("Hello, World!", font, color, &position);		position.y -= position.h;		SDL_GL_RenderText("A line right underneath", font, color, &position);		position.y -= position.h;		SDL_GL_RenderText("Yay text rendering.", font, color, &position);		// Come out of HUD mode		glEnable(GL_DEPTH_TEST);		glDisable2D();				// Show the screen		SDL_GL_SwapBuffers( );				// Wait until you click the X			SDL_WaitEvent(&event);		switch(event.type) {		case SDL_QUIT:			done = 1;			break;		}	}		// Clean up (the atexit's take care of the rest)	TTF_CloseFont(font);		return 0;}

This topic is closed to new replies.

Advertisement