Frage

Ich habe versucht, Text mithilfe von SDL und der SDL_TTF-Bibliothek unter Windows XP und VS2010 in einem OpenGL-Fenster zu rendern.
Versionen:
SDL-Version 1.2.14
SDL TTF-Entwicklung 1.2.10
openGL (Version ist mindestens 2-3 Jahre alt).

Ich habe mit SDL/SDL_image erfolgreich ein OpenGL-Fenster erstellt und kann problemlos Linien/Polygone darauf rendern.

Wenn ich mich jedoch dem Text zuwende, scheint es, dass in meinem aktuellen Programm ein Fehler vorliegt. Beim Versuch erhalte ich das folgende Ergebnis diesen Code hier

enter image description here

Für diejenigen, die kein Pastebin verwenden möchten, sind hier nur die entscheidenden Codesegmente:

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

Gibt es ein offensichtliches Stück Code, das mir fehlt?
Vielen Dank für jede Hilfe zu diesem Thema.
Ich versuche jetzt seit 3 ​​Tagen, openGL und SDL zu lernen, also verzeihen Sie bitte etwaige Fehlinformationen meinerseits.


BEARBEITEN:

Das merke ich beim Gebrauch
TTF_RenderUTF8_Shaded
TTF_RenderUTF8_Solid

Wirf eine Nullzeiger-Ausnahme aus, was bedeutet, dass in der eigentlichen Textwiedergabefunktion ein Fehler vorliegt (ich vermute), ich weiß nicht, was das bedeutet TTF_RenderUTF8_Blended gibt ein rotes Quadrat zurück, aber ich vermute, dass alle Probleme davon abhängen.

War es hilfreich?

Lösung

Ich denke, das Problem liegt in der glEnable(GL_TEXTURE_2D) Und glDisable(GL_TEXTURE_2D) Funktionen, die jedes Mal aufgerufen werden müssen, wenn der Text auf den Bildschirm gemalt wird. Und möglicherweise stimmt auch die Farbkonvertierung zwischen der SDL- und GL-Oberfläche nicht.Ich habe kombiniert create_texture Und drawText in eine einzige Funktion umwandeln, die den Text richtig anzeigt.Das ist der 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 );
} 

Bildschirmfoto

Ich initialisiere OpenGL wie folgt:

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

Andere Tipps

Ich denke, Sie sollten einfach glEnable(GL_BLEND) hinzufügen, da der Code für die Textoberfläche TTF_RenderUTF8_Blended( fntCourier, text, clrFg ) lautet und Sie die Mischfunktionen von opengl aktivieren müssen.

BEARBEITEN

Okay, ich habe mir endlich die Zeit genommen, Ihren Code einem Compiler zu unterziehen.Am wichtigsten ist der Compiler mit -Werror so dass Warnungen zu Fehlern werden

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

    /*...*/

    return &texture;
}

Ich habe es nicht zuerst gesehen, weil das so etwas wie die 101 des C-Codierers ist und ziemlich unerwartet ist: Sie dürfen keine Zeiger auf lokale Variablen zurückgeben!.Sobald die Funktion den Gültigkeitsbereich verlässt, zeigt der zurückgegebene Zeiger nur noch auf Unsinn.Warum geben Sie überhaupt einen Zeiger zurück?Geben Sie einfach eine Ganzzahl zurück:

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

    /*...*/

    return texture;
}

Aus diesem Grund werden Sie die Textur im Nachhinein auch nicht löschen.Sie laden es auf OpenGL hoch, verlieren dann aber den Verweis darauf.


In Ihrem Code fehlt ein glEnable(GL_TEXTURE_2D) Deshalb sind keine Textureffekte erkennbar. Allerdings ist Ihr Einsatz von Texturen nicht optimal.So wie Sie es gemacht haben, erstellen Sie jedes Mal, wenn Sie diesen Text zeichnen, eine völlig neue Textur.Wenn das in einer Animationsschleife passiert, werden Sie

  1. Der Texturspeicher geht ziemlich bald aus
  2. verlangsamen es erheblich

(1) kann behoben werden, indem nicht bei jedem Neuzeichnen ein neuer Texturname generiert wird

(2) können Adressen sein, indem neue Texturdaten nur dann hochgeladen werden, wenn sich der Text ändert, und indem nicht glTexImage2D, sondern glTexSubImage2D verwendet wird (wenn sich die Abmessungen der Textur ändern, muss es natürlich glTexImage2D sein).


BEARBEITEN, ich habe ein weiteres mögliches Problem gefunden, aber beheben Sie zuerst Ihr Zeigerproblem.

Sie sollten sicherstellen, dass Sie den Texturumgebungsmodus GL_REPLACE oder GL_MODULATE verwenden.Wenn Sie GL_DECAL oder GL_BLEND verwenden, erhalten Sie roten Text auf einem roten Quad.

In meinem vorherigen Beitrag ist die Erinnerung an die Funktion verloren gegangen und das Programm stürzte nach einiger Zeit ab ...Ich habe dies verbessert, indem ich das Laden und Anzeigen der Textur getrennt habe:

Die erste Funktion muss vor der SDL-Schleife aufgerufen werden. Sie lädt eine Textzeichenfolge in den Speicher:

Jede geladene Zeichenfolge muss einen anderen txtNum-Parameter haben

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

Der zweite zeigt den String an, muss in der SDL-Schleife aufgerufen werden:

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top