depthoffield:景深效果(Depth of Field) 的实现思路方法



什么是景深效果?
景深效果,简称DOF,在人眼跟光学摄像设备上很常见.如下图:
\"\"

简单地来说,就是近处跟远处景物模糊,而焦点附近物体则很清晰.至于为什么会产生这样效果,我就懒得说了:p

那么如何来实现这种效果呢?
看图:
\"\"

从摄像机开始,按距离分成 3部分:
近距离模糊,焦点范围(清晰),远距离模糊
渲染时候按深度(即距离)进行判断,在焦点范围内则是清晰,否则就进行模糊处理.
\"\" 整个过程分 3个Pass:
1. 将场景渲染到个RenderTarget,做为清晰版.
2. 将上步得到RenderTarget进行模糊处理,得到BluredRT(模糊版).
3. 合成.跟据距离来判断是否应该模糊,如果不在焦点范围内则绘制BluredRT,否则就绘制RenderTarget.

那么,还有个问题,深度值如何计算呢?
公式: WDepth = Depth / Far_Z_Clip.
在这里我是把深度值存在Alpha通道中块渲染到RenderTarget,这样在最后步直接取color.a就可以进行深度判断了
\"\"

(右图为Alpha通道,存储了深度值)



Shader和最终效果
sampler RenderTarget;
sampler BluredRT;

//焦点范围
float fNearDis;
float fFarDis;

float4 ps_( float2 TexCoord : TEXCOORD0 ) : COLOR0
{
float4 color = tex2D( RenderTarget, TexCoord );
( color.a > fNearDis && color.a < fFarDis )
color;

tex2D( BluredRT, TexCoord );
}



\"\"

是不是看起来很不自然?
为什么呢?这样实现DOF在清晰和模糊交界处过渡太生硬了,所以就像分成了 3部分样-_-!
那我们增加两个过渡不就成了?
就像这样:
\"\"

sampler RenderTarget;


sampler BluredRT;

//焦点范围
float fNearDis;
float fFarDis;
float fNearRange;
float fFarRange;

float4 ps_( float2 TexCoord : TEXCOORD0 ) : COLOR0
{
float4 sharp = tex2D( RenderTarget, TexCoord );
float4 blur= tex2D( BluredRT, TexCoord );

float percent = max(saturate(1 - (sharp.a-fNearDis)/fNearRange),
saturate((sharp.a-(fFarDis-fFarRange))/fFarRange));

lerp( sharp, blur, percent );
}



\"\"

Tags:  ps景深效果 景深效果 aedepthoffield depthoffield

延伸阅读

最新评论

发表评论