Pregunta

He intentado representar texto en una ventana openGL usando SDL y la biblioteca SDL_TTF en Windows XP, VS2010.
Versiones:
SDL versión 1.2.14
SDL TTF desarrollo 1.2.10
openGL (la versión tiene al menos 2-3 años).

He creado con éxito una ventana openGL usando SDL/SDL_image y puedo representar líneas/polígonos en ella sin problemas.

Sin embargo, al pasar al texto, parece que hay algún defecto en mi programa actual. Obtengo el siguiente resultado al intentarlo. este código aquí

enter image description here

Para aquellos que no estén dispuestos a pegar, aquí están solo los segmentos de código cruciales:

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 );
}

segmento 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;
}

¿Hay algún código obvio que me falta?
Gracias por cualquier ayuda sobre este tema.
He estado intentando aprender openGL y SDL durante 3 días, así que perdone cualquier información errónea de mi parte.


EDITAR:

Noto que usando
TTF_RenderUTF8_Shaded
TTF_RenderUTF8_Solid

Lanza una excepción de puntero nulo, lo que significa que hay un error dentro de la función de representación de texto real (sospecho), no sé qué significa esto. TTF_RenderUTF8_Blended devuelve un cuadrado rojo, pero sospecho que todos los problemas dependen de esto.

¿Fue útil?

Solución

Creo que el problema está en las funciones glEnable(GL_TEXTURE_2D) y glDisable(GL_TEXTURE_2D) que deben llamarse cada vez que se pinta el texto en la pantalla. Y quizás también la conversión de color entre la superficie SDL y GL no es correcta. He combinado create_texture y drawText en una sola función que muestra el texto correctamente.Ese es el código:

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 );
} 

captura de pantalla

Estoy inicializando OpenGL de la siguiente manera:

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);
} 

Otros consejos

Creo que debería agregar glEnable (GL_BLEND), porque el código para la superficie del texto dice TTF_RenderUTF8_Blended (fntCourier, text, clrFg) y debe habilitar las capacidades de combinación de opengl.

EDITAR

Bien, finalmente me tomé el tiempo de pasar tu código por un compilador.Lo más importante es que el compilador con -Werror para que las advertencias se conviertan en errores

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

    /*...*/

    return &texture;
}

No lo vi primero, porque es algo así como el codificador C 101 y es bastante inesperado: ¡No debes devolver punteros a variables locales!.Una vez que las funciones salen del alcance, el puntero devuelto señalará únicamente tonterías.¿Por qué devuelves un puntero?Simplemente devuelve un número entero:

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

    /*...*/

    return texture;
}

Debido a esto, tampoco eliminarás la textura después.Lo subes a OpenGL, pero luego pierdes la referencia.


A tu código le falta un glEnable(GL_TEXTURE_2D) es por eso que no puedes ver ningún efecto de textura. Sin embargo, su uso de texturas no es óptimo.De la forma en que lo hiciste, recreas una textura completamente nueva cada vez que estás a punto de dibujar ese texto.Si eso sucede en un bucle de animación, podrás

  1. quedarse sin memoria de textura bastante pronto
  2. ralentizarlo significativamente

(1) se puede solucionar al no generar un nuevo nombre de textura cada vez que se vuelve a dibujar

(2) pueden ser direcciones cargando nuevos datos de textura solo cuando el texto cambia y no usando glTexImage2D, sino glTexSubImage2D (por supuesto, si las dimensiones de la textura cambian, debe ser glTexImage2D).


EDITAR, encontré otro posible problema, pero primero solucione el problema del puntero.

Debes asegurarte de estar utilizando el modo de entorno de textura GL_REPLACE o GL_MODULATE.Si usa GL_DECAL o GL_BLEND, terminará con texto rojo en un quad rojo.

Hubo una fuga de memoria de la función en mi publicación anterior y el programa se bloqueó después de un tiempo ... Mejoré esto separando la carga de textura y la visualización:

La primera función debe llamarse antes del bucle SDL. Carga la cadena de texto en la memoria:

Cada cadena cargada debe tener un parámetro txtNum diferente

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);
 }

El segundo muestra la cadena, se debe llamar en el bucle SDL:

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);
}

ingrese la descripción de la imagen aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top