按真实情况来说,运动模糊应该检测像素从一帧到下一帧运动的速度,根据这个速度来进行正确的模糊, 但是这个方法相对复杂, 这里抛开速度的影响, 单纯进行动态模糊处理。
1. 将物体渲染到一个纹理, 设为RT。
2. 进行模糊处理, 创建纹理Temp, Sum, Temp用于保存模糊的结果, Sum为保存上一帧图像的纹理, 将本次渲染的纹理RT与上一帧图像Sum(第一次Sum未保存任何内容)进行混合,方法为:使用同一纹理坐标对两纹理采样,然后对采样的两颜色做线性插值。将最后结果保存在纹理Temp中。
VS:
float fInverseViewportWidth;
float fInverseViewportHeight;
struct VS_OUTPUT
{
float4 Position : POSITION0;
float2 tex : TEXCOORD0;
};
VS_OUTPUT vs_main(float4 Pos : POSITION)
{
VS_OUTPUT Output;
Pos.xy = sign(Pos.xy);
Output.Position = float4(Pos.xy, 0.0f, 1.0f);
Output.tex.x = 0.5 * (1 + Pos.x + fInverseViewportWidth);
Output.tex.y = 0.5 * (1 - Pos.y + fInverseViewportHeight);
return( Output );
}
PS:
sampler RT;
sampler Sum;
float blur_factor;
float4 ps_main(float2 tex : TEXCOORD0) : COLOR0
{
float4 render = tex2D(RT, tex);
float4 sum = tex2D(Sum, tex);
return lerp(render, sum, blur_factor);
}
3. 将纹理Temp拷贝到Sum中,for the next frame
4. 最后将纹理Sum拷贝到帧缓冲,显示
这种方法只是一种简单的近似,效果很一般,这不是真正的运动模糊, 大量使用对CPU资源也是一种浪费。
又是可爱的茶壶
真正的运动模糊应该使用时间反失真的方法来实现,这种方法与空间反失真相类似。
1、 对于显示4秒(即100帧)的动画,你要渲染400帧。这400帧也覆盖4秒的时间,只是划分得更细。
2、接下来,按每4帧为一组 . . .
3、把组内所有4帧进行积累渲染。
4、现在你就得到了一个25帧/秒的动画。每一帧都有运动模糊效果
这样一来要求把帧速提高几倍,在实时渲染中这是很难接受的。
在游戏中需要使用运动模糊可以采用一些更简单的方法,如使用具有不同程度运动模糊的纹理来表现等等