XNA Shader编程教程21-过渡:淡入淡出

程序截图

今天的教程是一个过渡效果,先展示一个场景,然后使用一个简单的post process shader淡入淡出到另一个场景。

淡入淡出效果

淡入淡出效果可以在许多电影,游戏和power point演示中看到。先播放场景A,然后在场景A淡出的同时播放场景B,产生两个场景间平滑的淡入淡出效果。

这在许多场合是很有用的,例如游戏中的切换场景或从一个菜单切换到另一个菜单等。

实现shader

淡入淡出shader很容易实现,你可能会有几个解决方案。

在shader中需要两张纹理,每张对应一个场景,还需要一个变量决定淡入淡出的程度。这个变量必须在0和1之间,当为0时播放场景A,为1时播放场景B。

下面是shader代码:

sampler ColorMapSampler : register(s0); 

texture ColorMap2; 
sampler ColorMapSampler2 = sampler_state 
{
    Texture = <ColorMap2>; 
    MinFilter = Linear; 
    MagFilter = Linear; 
    MipFilter = Linear; 
    AddressU = Clamp; 
    AddressV = Clamp; 
}; 
float fFadeAmount; 

这里我们定义了两个纹理采样器,ColorMapSampler1和ColorMapSampler2,两者都包含一个场景,使用一个叫做fFadeAmount的变量实现两者的切换。纹理采样器可以使用两种不同的方式定义,这在前面的教程中已经解释过了。

现在我们已经做好了实现pixel shader的准备。因为这是一个post process shader,所以无需编写vertex shader。

// Transition 
float4 PixelShader(float2 Tex: TEXCOORD0) : COLOR
{
    float4 Color = tex2D(ColorMapSampler, Tex); 
    float4 Color2 = tex2D(ColorMapSampler2, Tex); 
    float4 finalColor = lerp(Color,Color2,fFadeAmount); 
    
    // Set our alphachannel to fAlphaAmount. 
    finalColor.a = 1; 
    return finalColor; 
}

这里我们做的就是从每个场景中提取颜色,并使用lerp函数混合这两个颜色。变量fFadeAmount控制渐淡的程度,0表示不减淡,显示场景SceneA,如果为0.3则减淡30%,同时显示场景A和B,其中场景A占70%,B占30%。(译者注:如果查看directX sdk,可知lerp函数的用法是:lerp(x, y, s),返回x + s(y - x))最后创建

technique: technique PostProcess
{
    pass P0
    {
        // A post process shader only needs a pixel shader. 
        PixelShader = compile ps_2_0 PixelShader(); 
    }
} 

使用shader

使用shader时,我们需要将两个场景绘制到一张纹理中,并将它传递到shader:

spriteBatch.Begin(SpriteBlendMode.AlphaBlend,SpriteSortMode.Immediate, SaveStateMode.SaveState); 
{
    // Apply the post process shader 
    float fadeBetweenScenes = ((float)Math.Sin(m_Timer) * 0.5f) + 0.5f; 
    effectPost.Parameters["fFadeAmount"].SetValue(fadeBetweenScenes); 
    effectPost.Parameters["ColorMap2"].SetValue(Scene2Texture); 
    effectPost.CommitChanges(); effectPost.Begin(); 
    {
        effectPost.CurrentTechnique.Passes[0].Begin(); 
        {
            spriteBatch.Draw(SceneTexture, new Rectangle(0, 0, 800, 600), Color.White); 
            effectPost.CurrentTechnique.Passes[0].End(); 
        }
    }
    effectPost.End(); 
} 
spriteBatch.End(); 

我们使用一张绘制场景A的纹理和另一张绘制场景B的纹理作为参数,并通过一个周期函数让变量fFadeAmount在0和1之间变化。

现在已经完成这个示例了,比起前面的教程其实并不难,对吗? ;)


发布时间:2009/6/24 上午10:09:34  阅读次数:9622

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号