XNA Shader编程教程22 – 过渡:左右揭开

程序截图

这是第二个过渡效果的教程,使用一个简单的post process shader从一个场景切换到另一个场景。

今天的effect是一个基本的过渡效果,一个场景会左右揭开(cross,译者注:这里不知道如何翻译,就借用power point中的说法了)至另一个场景。

Cross过渡

Cross过渡使用一根“线”分隔两个场景。在图22.1中,显示了场景B,而场景A正在向右移动。

图22.1

实现shader

和教程21一样,我们需要两个纹理对应两个场景,你还需要一个变量指定淡入淡出的程度。这个变量必须在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的代码:

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

这个shader和教程21中的几乎是一样的,除了下列代码:

float4 finalColor = lerp(Color,Color2,smoothstep(fFadeAmount,fFadeAmount+fSmoothSize,Tex.x)); 

这里我们使用了一个叫做moothstep(a,b,x)的函数(译者注:这个函数的具体解释可见directX sdk,用法是smoothstep(min, max, x),如果x的范围是[min, max],则返回一个介于0和1之间的Hermite插值),这个函数会基于参数a,b,x返回一个介于0和1之间的值。当x小于a时返回0,当x大于b时返回1,当x介于a和b之间则返回一个介于0和1之间的值。

图22.2

当使用smoothstep时,我们使用Tex.x作为x,fFadeAmount作为a,如果fFadeAmount (fSmoothSize设置为0)作为b,那么分割线会变得最清晰。你可以让fSmoothSize大于0使过渡更加平滑,这时b大于a。这个函数会基于Tex.x返回[0,1],可以将这个返回值作为lerp函数的控制参数,实现一个漂亮的过渡效果!

注意:当fSmoothSize大于0而fFadeAmount = 0时,我们仍能在fFadeAmount = 1时看到场景的fSmoothSize部分(译者注:此句好像不通,原文是When fSmoothSize is > 0.0, and fFadeAmount = 0, we will still be able to see fSmoothSize part of the scene displayed when fFadeAmount = 1, because our fade starts at fFadeAmount and stops at fFadeAmount( 0 ) + fSmoothSize.),这是因为切换效果从 fFadeAmount 开始,fFadeAmount( 0 ) + fSmoothSize结束。

使用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之间变化。

译者注:你可以使用

float4 finalColor = lerp(Color,Color2,smoothstep(fFadeAmount,fFadeAmount+fSmoothSize,Tex.y));

让分割线上下移动;

使用

float4 finalColor = lerp(Color,Color2,smoothstep(fFadeAmount,fFadeAmount+fSmoothSize,Tex.x*0.5+Tex.y*0.5));

让分割线沿斜向45度移动,当然改变系数也可以改变对应的角度。 不知你是否有兴趣将power point中的所有过渡效果在shader中实现。


发布时间:2009/6/24 上午10:31:29  阅读次数:9693

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

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号