Question

Je suis tenté de rendre le texte sur une fenêtre en utilisant SDL openGL et la bibliothèque SDL_ttf sur Windows XP, VS2010.
Versions:
Version SDL 1.2.14
SDL TTF devel 1.2.10
openGL (version est âgé d'au moins 2-3 ans).

Je l'ai créé avec succès une fenêtre en utilisant SDL openGL / SDL_image et peut rendre les lignes / polygones sur celui-ci sans problème.

Cependant, le déplacement sur texte, il semble qu'il y ait une faille dans mon programme actuel, je reçois le résultat suivant lorsque vous essayez ce code

entrer image description ici

pour ceux qui ne veulent pas Pastebin ici ne sont que les segments de code crutial:

void drawText(char * text) {
    glLoadIdentity();
    SDL_Color clrFg = {0,0,255,0}; // set colour to blue (or 'red' for BGRA)
    SDL_Surface *sText = TTF_RenderUTF8_Blended( fntCourier, text, clrFg );
    GLuint * texture = create_texture(sText);
    glBindTexture(GL_TEXTURE_2D, *texture);
    // draw a polygon and map the texture to it, may be the source of error
    glBegin(GL_QUADS); {
        glTexCoord2i(0, 0); glVertex3f(0, 0, 0);
        glTexCoord2i(1, 0); glVertex3f(0 + sText->w, 0, 0);
        glTexCoord2i(1, 1); glVertex3f(0 + sText->w, 0 + sText->h, 0);
        glTexCoord2i(0, 1); glVertex3f(0, 0 + sText->h, 0);
    } glEnd();
    // free the surface and texture, removing this code has no effect
    SDL_FreeSurface( sText );
    glDeleteTextures( 1, texture );
}

segment 2:

// create GLTexture out of SDL_Surface
GLuint * create_texture(SDL_Surface *surface) {
    GLuint texture = 0;

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    // The SDL_Surface appears to have BGR_A formatting, however this ends up with a 
    // white rectangle no matter which colour i set in the previous code.
    int Mode = GL_RGB;

    if(surface->format->BytesPerPixel == 4) {
        Mode = GL_RGBA;
    }

    glTexImage2D(GL_TEXTURE_2D, 0, Mode, surface->w, surface->h, 0, Mode, 
                 GL_UNSIGNED_BYTE, surface->pixels);

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

    return &texture;
}

Y at-il un peu évident de code que je suis absent?
Merci pour toute aide à ce sujet.
J'ai essayé d'apprendre openGL et SDL pendant 3 jours maintenant s'il vous plaît pardonnez toute information erronée de ma part.


EDIT:

Je remarque que l'utilisation
TTF_RenderUTF8_Shaded
TTF_RenderUTF8_Solid

Jeter une exception de pointeur nul, ce qui signifie qu'il ya une erreur dans la fonction de rendu de texte réel (je pense), je ne sais pas comment ce moyen TTF_RenderUTF8_Blended renvoie un carré rouge, mais je soupçonne que tous les problèmes de charnière à ce sujet.

Était-ce utile?

La solution

Je pense que le problème est dans les glEnable(GL_TEXTURE_2D) et les fonctions glDisable(GL_TEXTURE_2D) qui doit être appelé à chaque fois que le texte est peint sur la screen.And peut-être aussi la conversion des couleurs entre la surface SDL et GL ne va pas. J'ai combiné create_texture et drawText en une seule fonction qui affiche le texte correctement. C'est le code:

void drawText(char * text, TTF_Font* tmpfont) {
SDL_Rect area;
SDL_Color clrFg = {0,0,255,0};
SDL_Surface *sText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Blended( tmpfont, text, clrFg ));
area.x = 0;area.y = 0;area.w = sText->w;area.h = sText->h;
SDL_Surface* temp = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,sText->w,sText->h,32,0x000000ff,0x0000ff00,0x00ff0000,0x000000ff);
SDL_BlitSurface(sText, &area, temp, NULL);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sText->w, sText->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp->pixels);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS); {
    glTexCoord2d(0, 0); glVertex3f(0, 0, 0);
    glTexCoord2d(1, 0); glVertex3f(0 + sText->w, 0, 0);
    glTexCoord2d(1, 1); glVertex3f(0 + sText->w, 0 + sText->h, 0);
    glTexCoord2d(0, 1); glVertex3f(0, 0 + sText->h, 0); 
} glEnd();
glDisable(GL_TEXTURE_2D);
SDL_FreeSurface( sText );
SDL_FreeSurface( temp );
} 

capture d'écran

Je l'initialisation OpenGL comme suit:

int Init(){
glClearColor( 0.1, 0.2, 0.2, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho( 0, 600, 300, 0, -1, 1 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if( glGetError() != GL_NO_ERROR ){
    return false;
}
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA);
} 

Autres conseils

I think you should just add glEnable(GL_BLEND), because the code for the text surface says TTF_RenderUTF8_Blended( fntCourier, text, clrFg ) and you have to enable the blending abilities of opengl.

EDIT

Okay, I finally took the time to put your code through a compiler. Most importantly, compiler with -Werror so that warning turn into errors

GLuint * create_texture(SDL_Surface *surface) {
    GLuint texture = 0;

    /*...*/

    return &texture;
}

I didn't see it first, because that's something like C coder's 101 and is quite unexpected: You must not return pointers to local variables!. Once the functions goes out of scope the pointer returned will point to nonsense only. Why do you return a pointer at all? Just return a integer:

GLuint create_texture(SDL_Surface *surface) {
    GLuint texture = 0;

    /*...*/

    return texture;
}

Because of this you're also not going to delete the texture afterward. You upload it to OpenGL, but then loose the reference to it.


Your code misses a glEnable(GL_TEXTURE_2D) that's why you can't see any effects of texture. However your use of textures is suboptimal. They way you did it, you recreate a whole new texture each time you're about to draw that text. If that happens in a animation loop, you'll

  1. run out of texture memory rather soon
  2. slow it down significantly

(1) can be addressed by not generating a new texture name each redraw

(2) can be addresses by uploading new texture data only when the text changes and by not using glTexImage2D, but glTexSubImage2D (of course, if the dimensions of the texture change, it must be glTexImage2D).


EDIT, found another possible issue, but first fix your pointer issue.

You should make sure, that you're using GL_REPLACE or GL_MODULATE texture environment mode. If using GL_DECAL or GL_BLEND you end up with red text on a red quad.

There was leaking memory of of the function in my previous post and the program was crashing after some time... I improved this by separating the texture loading and displaying:

The first function must be called before the SDL loop.It loads text string into memory:

Every string loaded must have different txtNum parameter

GLuint texture[100];
SDL_Rect area[100]; 
void Load_string(char * text, SDL_Color clr, int txtNum, const char* file, int ptsize){
    TTF_Font* tmpfont;
    tmpfont = TTF_OpenFont(file, ptsize); 
    SDL_Surface *sText = SDL_DisplayFormatAlpha(TTF_RenderUTF8_Solid( tmpfont, text, clr ));
    area[txtNum].x = 0;area[txtNum].y = 0;area[txtNum].w = sText->w;area[txtNum].h = sText->h;
    glGenTextures(1, &texture[txtNum]);
    glBindTexture(GL_TEXTURE_2D, texture[txtNum]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, sText->w, sText->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sText->pixels);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    SDL_FreeSurface( sText );
    TTF_CloseFont(tmpfont);
 }

The second one displays the string, must be called in the SDL loop:

void drawText(float coords[3], int txtNum) {
     glBindTexture(GL_TEXTURE_2D, texture[txtNum]);
     glEnable(GL_TEXTURE_2D);
     glBegin(GL_QUADS); {
     glTexCoord2f(0, 0); glVertex3f(coords[0], coords[1], coords[2]);
     glTexCoord2f(1, 0); glVertex3f(coords[0] + area[txtNum].w, coords[1], coords[2]);
     glTexCoord2f(1, 1); glVertex3f(coords[0] + area[txtNum].w, coords[1] + area[txtNum].h, coords[2]);
     glTexCoord2f(0, 1); glVertex3f(coords[0], coords[1] + area[txtNum].h, coords[2]); 
     } glEnd();
     glDisable(GL_TEXTURE_2D);
}

enter image description here

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top