Continuando nossa série de artigos traduzidos do site lazyfoo, iremos ver agora como aproveitar a nova renderização acelerada por hardware do SDL, que faz com o uso de transparência seja muito mais rápida, e usa a modulação do canal alpha (que funciona exatamente a modulação de cores) para controlar a transparência de uma textura.
//Texture wrapper class class LTexture { public: //Initializes variables LTexture(); //Deallocates memory ~LTexture(); //Loads image at specified path bool loadFromFile( std::string path ); //Deallocates texture void free(); //Set color modulation void setColor( Uint8 red, Uint8 green, Uint8 blue ); //Set blending void setBlendMode( SDL_BlendMode blending ); //Set alpha modulation void setAlpha( Uint8 alpha ); //Renders texture at given point void render( int x, int y, SDL_Rect* clip = NULL ); //Gets image dimensions int getWidth(); int getHeight(); private: //The actual hardware texture SDL_Texture* mTexture; //Image dimensions int mWidth; int mHeight; };
Iremos adicionar aqui duas funções para suporte da transparência alpha em uma textura. Primeiro temos setAlpha que funciona de forma similar à setColor no artigo sobre modulação de cores. Temos também setBlendMode que controlará como a textura será combinada com o canal alpha. Para que a combinação funciona de forma adequada, você deve ajustar o modo de combinação da textura. Veremos isso em detalhes mais tarde.
bool loadMedia() { //Loading success flag bool success = true; //Load front alpha texture if( !gModulatedTexture.loadFromFile( "13_alpha_blending/fadeout.png" ) ) { printf( "Failed to load front texture!\n" ); success = false; } else { //Set standard alpha blending gModulatedTexture.setBlendMode( SDL_BLENDMODE_BLEND ); } //Load background texture if( !gBackgroundTexture.loadFromFile( "13_alpha_blending/fadein.png" ) ) { printf( "Failed to load background texture!\n" ); success = false; } return success; }
Aqui na função de carregamento da textura iremos carregar a textura frontal que iremos combinar com o canal alpha e uma textura de fundo. A medida que a textura frontal vai ficando mais transparente, seremos capazes de enxergar cada vez mais a textura do fundo. Como você pode ver no código, depois de ter carregado com sucesso a textura frontal, configuramos o BlendMode para blend para que a combinação seja ativada. Como o fundo não irá ficar transparente, não temos que ativar a combinação para ela.
Agora, como Alpha funciona? Alpha é a opacidade, e com uma opacidade menor mais podemos enxergar através da textura. Como os componentes vermelho, verde e azul da cor, o canal Alpha vai de 0 a 255 ao ser modulada. A melhor maneira de entender isso tudo é com alguns exemplos. Digamos que temos uma imagem frontal sobre um plano de fundo branco.
Aqui temos a imagem frontal em 255 (Alpha 100%):
Aqui temos a imagem frontal em 191 (Alpha 75%):
Aqui temos a imagem frontal em 127 (Alpha 50%):
Aqui temos a imagem frontal em 63 (Alpha 25%):
Aqui temos a imagem frontal em 0 (Alpha 0%):
Como você pode ver, quanto menor o valor do canal Alpha mais transparente a imagem é.
void LTexture::setBlendMode( SDL_BlendMode blending ) { //Set blending function SDL_SetTextureBlendMode( mTexture, blending ); } void LTexture::setAlpha( Uint8 alpha ) { //Modulate texture alpha SDL_SetTextureAlphaMod( mTexture, alpha ); }
Aqui temos a funcões SDL que fazem o trabalho de verdade. SDL_SetTextureBlendMode em setBlendMode permite que ativemos a combinação e SDL_SetTextureAlphaMod permite que ajustemos o valor do canal Alpha de toda a textura.
//Main loop flag bool quit = false; //Event handler SDL_Event e; //Modulation component Uint8 a = 255; //While application is running while( !quit ) {
Assim que entramos no loop principal, declaramos uma variável para controlar o valor do canal Alpha da textura. Esse valor é inicializado em 255 de forma que a textura frontal começa completamente opaca.
//Handle events on queue while( SDL_PollEvent( &e ) != 0 ) { //User requests quit if( e.type == SDL_QUIT ) { quit = true; } //Handle key presses else if( e.type == SDL_KEYDOWN ) { //Increase alpha on w if( e.key.keysym.sym == SDLK_w ) { //Cap if over 255 if( a + 32 > 255 ) { a = 255; } //Increment otherwise else { a += 32; } } //Decrease alpha on s else if( e.key.keysym.sym == SDLK_s ) { //Cap if below 0 if( a - 32 < 0 ) { a = 0; } //Decrement otherwise else { a -= 32; } } } }
O loop de eventos encerra a aplicacão e aumenta ou diminiu o valor do canal Alpha com as teclas w e s do teclado.
//Clear screen SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF ); SDL_RenderClear( gRenderer ); //Render background gBackgroundTexture.render( 0, 0 ); //Render front blended gModulatedTexture.setAlpha( a ); gModulatedTexture.render( 0, 0 ); //Update screen SDL_RenderPresent( gRenderer );
No final do loop principal fazemos a nossa renderização. Depois de limpar a tema, primeiro renderizamos o plano de fundo e em seguida renderizamos a textura frontal, modulada, sobre ele. Antes de renderizar a textura frontal, ajustamos o valor de seu canal Alpha. Tente aumentar e diminuir esse valor para ver como a transparência afeta a renderização.
Baixe os arquivos de mídia e código fonte desse artigo aqui.