LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   SDL's TTF API doesn't work with OpenGL (https://www.linuxquestions.org/questions/programming-9/sdls-ttf-api-doesnt-work-with-opengl-468448/)

pda_h4x0r 07-28-2006 01:06 AM

SDL's TTF API doesn't work with OpenGL
 
Hello everyone,

I'm writing a simple game using both OpenGL (for the graphics) and SDL (for event handling and keyboard input). I can initilize the TTF API, I can load a TTF, I can use TTF_RenderText_* functions, but no matter what I do, no text appears whenever I attempt to blit a surface created by a TTF_RenderText_* function to the main SDL_Surface. Here's the (relevant) code:

int DrawStr(TTF_Font* fnt, char* str, int x, int y, SDL_Surface* dest, SDL_Color color) {

if(fnt == NULL) return 0;
SDL_Surface* tmp = TTF_RenderText_Solid(fnt, str, color);
if(!tmp) return 0;
if(SDL_BlitSurface(tmp, NULL, dest, &(SDL_Rect){x,y,0,0})) return 0;
SDL_FreeSurface(tmp);
return 1;

}

The above function always returns 1, but no text appears.

It is called as follows:

SDL_Surface* GLSCREEN;
TTF_Font fnt_sans12;

#define random(x) (rand() % (x))

//...

if(!DrawStr(fnt_sans12, "Linux", 20, 20, GLSCREEN, &(SDL_Color){random(255), random(255), random(255), random(255)}) printf("Unable to render text!\n");

GLSCREEN has the SDL_OPENGL, SDL_GL_DOUBLEBUFFER, SDL_HWPALETTE, SDL_RESIZABLE, and SDL_HWACCEL options enabled. I am using SDL 2.0 (i.e. the latest libs in Debian Etch).

Thank you in advance for your response(s).

pda_h4x0r 07-29-2006 02:26 AM

It seems I found a solution from an SDL tutorial at http://osdl.sourceforge.net/OSDL/OSD...libraries.html.

TTF_RenderText_Solid() doesn't work in GNU/Linux. TTF_RenderText_Shaded(), however, does.

How about that. Please see the signature...

pda_h4x0r 08-02-2006 01:55 AM

Hmmm...TTF_RenderText_* isn't failing--SDL_BlitSurface is. I think this may be because 32-bit SDL surfaces have an ARGB pixel format, whereas OpenGL's 32-bit pixel format is RGBA. Because I explicitly initilized SDL to use OpenGL for graphics (i.e. by enabling the SDL_OPENGL option), SDL_BlitSurface is simply unable to perform blits. Crap.

vharishankar 08-02-2006 01:59 AM

You can initialize with the SDL_OPENGLBLIT flag instead of SDL_OPENGL in SDL_SetVideoMode. That will allow SDL blits in an OpenGL surface.

dmail 08-02-2006 04:13 AM

Use this option at your own peril.
http://twomix.devolution.com/piperma...er/039852.html

pda_h4x0r 08-03-2006 11:53 PM

Thank you for the suggestions. What I currently have working is a way to generate an OpenGL texture from an SDL surface with the same pixel format. The code is currently unsuitable for many calls (i.e. I'm using it to generate HUDs), but here's what I have:


int GLTexFromSurface(SDL_Surface* src, GLuint tex, int type) {
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, type, src->w, src->h, 0, type,
GL_UNSIGNED_BYTE, src->pixels );

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

return 1;
}

inline int GLFreeTex(GLuint* tex) {
glDeleteTextures(1,tex);
return 1;
}

//POT == Power Of Two
inline int GLMakePOT(int dim) {
double log2 = log(dim) / log(2);
int log2i = (int)ceil(log2);
return (int)(pow(2,log2i));
}

int DrawStr(TTF_Font* fnt, char* str, float x, float y, GLuint texi, SDL_Color color) {
SDL_Surface* text = TTF_RenderText_Blended(fnt, str, color);
if(text == NULL) {
printf("DrawStr(): unable to allocate text buffer\n");
return 0;
}

int width = GLMakePOT(text->w);
int height = GLMakePOT(text->h);

//FIXME: currently, the texture has to be square to prevent ugly distortions
if(width > height) height = width;
else if(height > width) width = height;

SDL_Surface* tmp = SDL_CreateRGBSurface(0, width, height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
if(tmp == NULL) {
printf("DrawStr(): unable to allocate temporary surface\n");
SDL_FreeSurface(text);
return 0;
}

//FIXME: not sure this is needed...
SDL_FillRect(tmp, &(SDL_Rect){0,0,width,height}, 0);

if(SDL_BlitSurface(text, NULL, tmp, NULL)) {
printf("DrawStr(): unable to create OpenGL-compatible surface\n");
SDL_FreeSurface(text);
SDL_FreeSurface(tmp);
return 0;
}

//my OpenGL surface has RGBA format
GLTexFromSurface(tmp, texi, GL_RGBA);

glBindTexture(GL_TEXTURE_2D, texi);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glTranslatef(x,y,-1.0f);

glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f); glVertex3f(0.0f,0.0f,0.0f);
glTexCoord2f(1.0f,0.0f); glVertex3f(width,0.0f,0.0f);
glTexCoord2f(1.0f,1.0f); glVertex3f(width,height,0.0f);
glTexCoord2f(0.0f,1.0f); glVertex3f(0.0f,height,0.0f);
glEnd();

glFinish();

SDL_FreeSurface(text);
SDL_FreeSurface(tmp);
GLFreeTex(&texi);

return 1;
}

What I'll probably end up doing is creating one small 32-bit SDL surface for each HUD element one big 32-bit SDL surface offscreen, and one big OpenGL texture when the game initilizes. Then, during run-time, I'll just clear the big SDL surface, blit the HUD elements to it, bind it to the OpenGL texture, and render it as a single quad.

Thanks again!


All times are GMT -5. The time now is 12:14 PM.