OpenGL and SDL_ttf problem

Hi,
I’ve been stuck with this issue for a while now. I’m drawing geometry and text, but only the geometry shows. The text routines are executed in each frame though (it goes through it when I debug…)

I’m guessing the OpenGL state isn’t “clean” before I Draw() or DrawMyText(), but I can’t find the cause…
Any ideas?

Thanks in advance,
Alex

PS. Comment out Draw() in main to see that text works. (if you do that, old texture memory is shown behind the text… :S )

Some example code…:

#include <SDL.h>
#include <SDL_opengl.h>
#include <SDL_ttf.h>
#include <iostream>
#include <string> 

using namespace std;

SDL_Surface*screen;
TTF_Font *font;
unsigned int TEXT_TEXTURE;
unsigned int TEXT_HEIGHT;
unsigned int TEXT_W, TEXT_H;
string oldText;
GLboolean should_rotate = GL_TRUE;
float angle = 0.0f;

bool Setup_Opengl(int width, int height)
{
    GLfloat ratio = (GLfloat) width / (GLfloat) height;
    glViewport( 0, 0, width, height );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    //gluPerspective( 60.0f, ratio, 1.0f, 1024.0f );
    gluPerspective(45.0f, ratio, 1.0f, 5000.0f); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity();
    glShadeModel( GL_SMOOTH );

    /*glCullFace( GL_BACK );
    glFrontFace( GL_CCW );
    glEnable( GL_CULL_FACE );*/

    glClearColor( 0, 0, 0, 0 );
    return true;
}

void Draw()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
    glTranslatef( 0.0, 0.0, -5.0 );
    glRotatef( angle, 0.0, 1.0, 0.0 );

    if( should_rotate ) {
        angle += 0.1f;
        if( angle > 360.0f ) {
            angle = 0.0f;
        }
    }
    GLubyte red[]    = { 255,   0,   0, 255 };
    GLubyte green[]  = {   0, 255,   0, 255 };
    GLubyte blue[]   = {   0,   0, 255, 255 };
    glBegin( GL_TRIANGLES );
        glColor4ubv( red );
        glVertex3f(-1.0, 0.0, 0.0 );
        glColor4ubv( green );
        glVertex3f( 1.0, 0.0, 0.0 );
        glColor4ubv( blue );
        glVertex3f( 0.0, 1.0, 0.0 );
    glEnd( );
    //glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

void Enter2D(int screenwidth, int screenheight) 
{
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    gluOrtho2D( 0, screenwidth, 0, screenheight );
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glLoadIdentity();
}

void Exit2D(void) 
{
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

SDL_Color newSDL_Color( int r, int g, int b ) {
    SDL_Color clr;
    clr.r = r;
    clr.g = g;
    clr.b = b;
    clr.unused = 0;
    return( clr );
}

void DrawMyText(string text)
{
    glEnable(GL_TEXTURE_2D);
    if( oldText != text )
    {
        SDL_Color clrFg = newSDL_Color(0,0,255);
        SDL_Surface* ourSurface = TTF_RenderText_Solid(font, text.c_str(), clrFg);
        TEXT_HEIGHT = ourSurface->h;
        TEXT_W = 1;
        TEXT_H = 1;
        while( TEXT_W < (unsigned int) ourSurface->w )
            TEXT_W*=2;
        while( TEXT_H < (unsigned int) ourSurface->h )
            TEXT_H*=2;
        SDL_Surface* myNewSurface = SDL_CreateRGBSurface(0,TEXT_W,TEXT_H,24,0xff000000,0x00ff0000,0x0000ff00,0);
        SDL_BlitSurface(ourSurface,0,myNewSurface,0);
        glBindTexture( GL_TEXTURE_2D, TEXT_TEXTURE);
        glTexImage2D( GL_TEXTURE_2D, 0, 3, TEXT_W, TEXT_H, 0, GL_RGB, GL_UNSIGNED_BYTE, myNewSurface->pixels );    
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );    
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        SDL_FreeSurface( ourSurface );
        SDL_FreeSurface( myNewSurface );
    }
    else
        glBindTexture( GL_TEXTURE_2D, TEXT_TEXTURE);

    Enter2D(screen->w, screen->h);
    glBegin( GL_QUADS );
        glVertex2f( (float) TEXT_W,0 ); glVertex2f( (float) screen->w, 0 ); glVertex2f (  (float) screen->w, (float) TEXT_HEIGHT ); glVertex2f( (float) TEXT_W, (float) TEXT_HEIGHT );
        glTexCoord2f( 0.0f, (float) TEXT_HEIGHT/TEXT_H ); glVertex2f(0.0f, 0.0f); 
        glTexCoord2f( 1.0f, (float) TEXT_HEIGHT/TEXT_H ); glVertex2f( (float) TEXT_W,0.0f);  
        glTexCoord2f( 1.0f, 0.0f ); glVertex2f( (float) TEXT_W, (float) TEXT_HEIGHT);  
        glTexCoord2f( 0.0f, 0.0f ); glVertex2f(0.0f, (float) TEXT_HEIGHT);
    glEnd();
    Exit2D();
    glDisable(GL_TEXTURE_2D);
    oldText=text;
}

int main( int argc, char* argv[] ){     
    SDL_Init( SDL_INIT_VIDEO );
    atexit(SDL_Quit);

    SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
    SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );

    TTF_Init();
    atexit(TTF_Quit);

    screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL | SDL_DOUBLEBUF | SDL_OPENGLBLIT );
    SDL_WM_SetCaption("SDL_ttf test", NULL); 

    if (!Setup_Opengl(screen->w, screen->h))
        return false;

    glGenTextures( 1, &TEXT_TEXTURE );

    SDL_RWops *rw=SDL_RWFromFile("arial.ttf","rb");
    font = TTF_OpenFontRW(rw,1,10);

    string text="a";
    int textcounter=100;

    while(1) {

        Draw();

        if (textcounter<0) {
            textcounter=100;
            text = "a";
        }else{
            text= text + "a";
            textcounter--;
        }

        DrawMyText(text);

        SDL_GL_SwapBuffers();
    }

    TTF_CloseFont( font );
    SDL_FreeSurface(screen);
    SDL_Quit();
    return 0; 
}

Your code is a bit confusing.

In the beginning of Draw() you clear the depth buffer, but you never enable depth testing in Setup_Opengl(). Do you want depth testing or not?

You usually disable depth testing when you draw 2d text. If you are using it, make sure to disable it when you draw your text in DrawMyText.

/Mathias

I copy-pasted and deleted a lot of code to make that example ^.
Bringing back the depthbuffer code and disabling it in the enter2d() function doesn’t help…

Note that I did add the glDisable(GL_TEXTURE_2D) at the end of DrawMyText to make the geometry show up. Which is weird, because I don’t use textures in my geometry code…
If you comment that disable out you won’t see anything. But also commenting out “glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );” gets the geometry to show up again!

I think the fault is there… is my texture var okay?

Thanks,
Alex

When you use texture objects, you only need to call glTexImage2D once for every texture. You call it every time, that will be costly.

You should always disable everything not needed. Remember, OpenGL is a state machine. If you enable texturing it will be used, even if you don’t send any new texture coordinates.

I only call glTexImage2D() if the text has changed. Is there a better way?

Why would the screen go black on setting the min filter?

thanks,
Alex

Project file is here:
http://www.planet.nl/~ephofhof/SDLttfTestSimple.zip

Commenting the glTexImage2D() line in the DrawMyText() function gets the geometry to show up.
So does uncommenting glDisable(GL_TEXTURE_2D) at the bottom of that function, but then the quad for the text doesn’t even show.

Any ideas? I’m out.

Thanks,
Alex

EDIT: The link above contains the ‘working’ version now…

I got it, needed to set the color to white at the end of Draw():
GLubyte white[] = {255, 255, 255, 255 };
glColor4ubv( white );

And disable texture2D at the end of DrawMyText():
glDisable(GL_TEXTURE_2D);

Thanks guys,
Alex