7 Stimmen

SDL + SDL_ttf: Transparenter überblendeter Text?

Ich möchte eine anti-aliased Zeichenfolge auf einer SDL_Surface mit einem bestimmten Alphakanal.

Ich habe herausgefunden, dass es möglich ist, zu rendern:

  • eine Anti-Aliasing-Zeichenkette mit dem Blended Variante der String-Rendering-Methode (d.h.: TTR_RenderText_Blended ). Aber dann kann ich es nicht transparent machen.
  • Ein Anti-Aliasing-String mit der Shaded Methode. Aber dann gibt es einen soliden Hintergrund. Der Hintergrund und die gezeichnete Zeichenkette können transparent gemacht werden, aber dann ist der feste Hintergrund immer noch da. Die Übergabe einer transparenten Hintergrundfarbe ist ebenfalls nicht möglich.
  • eine nicht geglättete Zeichenkette, die ich nach Belieben transparent machen kann, indem ich die Solid Variante. Aber sie ist nicht anti-aliasing.

Danke

0 Stimmen

Haben Sie das jemals zum Laufen gebracht?

0 Stimmen

@BruceConnor: Nein. Das ist in der Tat ziemlich traurig darüber. Ich habe zu OpenGL gewechselt und eine Bitmap-Schriftart verwendet. Das erfordert eine Menge Arbeit, aber als ich es endlich zum Laufen gebracht habe, war ich wirklich sehr zufrieden. Hoffentlich sind Sie bereit, einige Stunden Programmierarbeit zu investieren, um das Gleiche zu tun.

0 Stimmen

Grüße, ich habe das gleiche Problem wie Sie und habe es noch nicht gelöst. Vielleicht hast du ja schon eine Idee, ich habe dort eine Frage gestellt: stackoverflow.com/questions/12700085 . In meinem Fall kann ich im Moment keine Bitmap-Schriftart verwenden.

13voto

Daniel Hanrahan Punkte 4462

Ich weiß, ich bin ein bisschen spät dran :/

Nach der SDL Dokumentation über SDL_SetAlpha :

Beachten Sie, dass Alpha pro Pixel und pro Fläche nicht kombiniert werden kann; falls vorhanden, wird immer das Alpha pro Pixel verwendet.

Also regelmäßig SDL_BlitSurface / SDL_SetAlpha wird hier nicht funktionieren. Aber es kann getan werden:

Example using only SDL

Die einzigen Möglichkeiten, die mir zum Alpha-Blending einfallen TTF_RenderText_Blended Ausgabe sind die Verwendung von OpenGL oder die Anpassung der Alphawerte der einzelnen Pixel in der Oberfläche.

Durch Anpassung der Alphawerte pro Pixel

Sie können dies tun, indem Sie die Alphawerte pro Pixel von [0, 255] zu einem neuen Bereich [0, alpha] :

// Changes a surface's alpha value, by altering per-pixel alpha if necessary.
void SetSurfaceAlpha (SDL_Surface *surface, Uint8 alpha)
{
    SDL_PixelFormat* fmt = surface->format;

    // If surface has no alpha channel, just set the surface alpha.
    if( fmt->Amask == 0 ) {
        SDL_SetAlpha( surface, SDL_SRCALPHA, alpha );
    }
    // Else change the alpha of each pixel.
    else {
        unsigned bpp = fmt->BytesPerPixel;
        // Scaling factor to clamp alpha to [0, alpha].
        float scale = alpha / 255.0f;

        SDL_LockSurface(surface);

        for (int y = 0; y < surface->h; ++y) 
        for (int x = 0; x < surface->w; ++x) {
            // Get a pointer to the current pixel.
            Uint32* pixel_ptr = (Uint32 *)( 
                    (Uint8 *)surface->pixels
                    + y * surface->pitch
                    + x * bpp
                    );

            // Get the old pixel components.
            Uint8 r, g, b, a;
            SDL_GetRGBA( *pixel_ptr, fmt, &r, &g, &b, &a );

            // Set the pixel with the new alpha.
            *pixel_ptr = SDL_MapRGBA( fmt, r, g, b, scale * a );
        }   

        SDL_UnlockSurface(surface);
    }       
}           

Ich weiß, es sieht beängstigend aus, aber es ist ziemlich einfach. Die wichtigste Zeile ist hier:

*pixel_ptr = SDL_MapRGBA( fmt, r, g, b, scale * a );

Sie können ihn wie folgt verwenden:

text_surface = TTF_RenderText_Blended( font, "Hello World!", color );
SetSurfaceAlpha( text_surface, 128 );

Mit OpenGL

Bei der Verwendung von OpenGL sind die Dinge viel einfacher. Angenommen, Sie konvertieren die SDL_Surface von TTF_RenderText_Blended zu einer GL-Textur zu machen, können Sie einfach verwenden:

glColor4f( 1.0, 1.0, 1.0, Alpha );

bevor Sie es auf einem texturierten Quad rendern.

Vergessen Sie aber nicht, vorher den Alpha-Blending-Modus zu aktivieren!

glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

0 Stimmen

Vielen Dank, dass Sie sich die Zeit genommen haben, diese späte Antwort zu geben. Du könntest dir damit ein Nekromanten-Abzeichen verdienen, wenn mehr Leute dafür stimmen.

0 Stimmen

Wenn Sie die programmierbare OpenGL-Pipeline verwenden, können Sie außerdem im Fragment-Shader die Textureinheit mit dem Alphawert multiplizieren. color = myColor.a * texture(myTexture, myCoords);

2voto

Lord Wolfenstein Punkte 251

Der Weg, dies mit einer TTF zu tun, ist die Verwendung von SDL_SetTextureAlphaMod() Etwa so

SDL_Surface *surface;
SDL_Texture *texture;
SDL_Color color = {255, 255, 255, 128}
surface = TTF_RenderText_Blended_Wrapped(myFont, "HI!", color, 100);
// myFont and the _renderer is pre-defined somewhere in the game
texture = SDL_CreateTextureFromSurface(_renderer, surface);
SDL_SetTextureAlphaMod(texture, color.a);
SDL_RenderCopy(_renderer, texture, NULL, &dest);
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);

/*...*/

SDL_RenderPresent(_renderer);

https://wiki.libsdl.org/SDL_SetTextureAlphaMod

0 Stimmen

Hurra, danke für die Antwort! Ich frage mich, ob das neu ist, seit die Frage ursprünglich gestellt wurde? Aber bei mir hat es auf jeden Fall funktioniert. +1

1voto

bobobobo Punkte 61051

Alles, was Sie tun müssen, ist anrufen SDL_SetAlpha zu Ihrem SDL_Surface nach Erstellung des Sprites, auf dem der Text gerendert wird, aber vor dem Aufruf von SDL_DisplayFormatAlpha auf diesem Sprite .

// Make the sprite with the text on it
SDL_Surface *swSprite = TTF_RenderText_Solid( font, text, textColor ) ;

// CALL SET ALPHA NOW
SDL_SetAlpha( swSprite, SDL_SRCALPHA, 128 ) ; // 50% opacity

// OK, NOW you can convert it to display format.  I'm presuming
// you called `SDL_SetVideoMode` with the `SDL_HWSURFACE` flag set previously
SDL_Surface* hwSprite = SDL_DisplayFormatAlpha( swSprite ) ;

// If you invert the above 2 steps, it won't work.

// We don't need the software sprite anymore
SDL_FreeSurface( swSprite ) ;

// Now draw the hwSprite as normal
SDL_BlitSurface( hwSprite, NULL, screen, &spriteLocation );

0 Stimmen

Dies funktioniert allerdings nur mit TTF_RenderText_Solid Variante, nicht TTF_RenderText_Blended .

-2voto

Victor Marzo Punkte 734

Warum nicht Bitmap-Schriften verwenden? Sie könnten ein png-Bild mit Alphakanal erstellen. Ich denke, dass SDL_ttf mit dem gleichen System arbeitet, es erstellt ein Bild und verwendet intern Bitmap-Schriften.

1 Stimmen

Hinweis: @ForceMagic hat einen toten Link entfernt. Wenn Sie einen Ersatz finden können, fügen Sie ihn bitte wieder ein. An ForceMagic: Da du gefragt hast, ist es in Ordnung, den toten Link zu entfernen, aber bitte füge einen Kommentar hinzu (der den Poster benachrichtigt), damit er die Benachrichtigung erhält und einen neuen (oder Ersatz-)Link findet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X