得益于新的硬件加速渲染,SDL2.0中的透明度变得更快。这里我们将使用alpha调制(它的工作原理很像颜色调制)来控制纹理的透明度。
//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 );
//设置混合
void setBlendMode( SDL_BlendMode blending );
//设置透明度调制
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;
};
这里我们将添加两个函数来支持纹理上的alpha透明度。首先是setAlpha,它的功能很像颜色调制教程中的setColor。还有setBlendMode,它将控制纹理的混合方式。为了让混合正常工作,你必须对纹理设置混合模式。我们将在后面详细介绍。
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;
}
在这里的纹理加载函数中,我们正在加载我们要alpha混合的正面纹理和一个背景纹理。随着正面纹理越来越透明,我们就能看到更多的背面纹理。正如你在代码中看到的,在我们成功加载正面纹理后,我们将SDL BlendMode设置为blend,这样就启用了混合。由于背景不会是透明的,所以我们不必对其设置混合。
现在alpha是如何工作的呢?Alpha就是不透明度,不透明度越低,我们就越能看透它。就像红色、绿色或蓝色的颜色组件一样,当调制它时,它从0到255。最好的理解方式是用一些例子。比如说,如果我们在白色背景上有正面图像。
这是255(100%alpha)时的正面图像:
这是191(75%alpha)的正面图像:
这是在127(50%alpha)的正面图像:
这是在63(25%alpha)时的正面图像:
这是0(0%alpha)时的正面图像:
如你所见,alpha越低越透明。
void LTexture::setBlendMode( SDL_BlendMode blending ){
//设置混合功能
SDL_SetTextureBlendMode( mTexture, blending );
}
void LTexture::setAlpha( Uint8 alpha ){
//调制纹理Alpha
SDL_SetTextureAlphaMod( mTexture, alpha );
}
下面是实际工作的SDL函数。setBlendMode中的SDL_SetTextureBlendMode[1]允许我们启用混合,SDL_SetTextureAlphaMod[2]允许我们设置整个纹理的alpha量。
//Main loop flag
bool quit = false;
//Event handler
SDL_Event e;
//Modulation component
Uint8 a = 255;
//While application is running
while( !quit )
{
//Handle events on queue
while( SDL_PollEvent( &e ) != 0 )
{
//User requests quit
if( e.type == SDL_QUIT )
{
quit = true;
}
//处理按键
else if( e.type == SDL_KEYDOWN )
{
//Increase alpha on w
if( e.key.keysym.sym == SDLK_w )
{
//超过255的上限
if( a + 32 > 255 )
{
a = 255;
}
//否则递增
else
{
a += 32;
}
}
//Decrease alpha on s
else if( e.key.keysym.sym == SDLK_s )
{
//如果低于0,则为上限
if( a - 32 < 0 )
{
a = 0;
}
//否则减少
else
{
a -= 32;
}
}
}
}
事件循环处理退出事件,并通过w/s键使alpha值上升/下降。
//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 );
在主循环的最后,我们进行渲染。清空屏幕后,我们先渲染背景,然后在其上渲染前端调制纹理。就在渲染前面的纹理之前,我们设置它的alpha值。尝试增加/减少alpha值,看看透明度对渲染的影响。
[1]
SDL_SetTextureBlendMode: http://wiki.libsdl.org/SDL_SetTextureBlendMode
[2]
SDL_SetTextureAlphaMod: http://wiki.libsdl.org/SDL_SetTextureAlphaMod
[3]
这里: http://www.lazyfoo.net/tutorials/SDL/13_alpha_blending/13_alpha_blending.zip
[4]
原文链接: http://www.lazyfoo.net/tutorials/SDL/13_alpha_blending/index.php