dof景深matlab,Shader学习(三):DOF(景深)

下面和大家介绍的是一个学习shader着色器的系列,想使用好shader的开发人员可以学习下。下面介绍第三篇关于DOF(景深)。

DOF(景深)最简单的现象就是当你用眼睛聚焦到前景的地方,后面就会变模糊, 当用眼睛聚焦到远景的地方,前就会变模糊,相机也会有同样的情况,通过调节光圈和焦距就很容易出现景深的效果。如果要说景深形成的原理的话,可以用小孔成像来说一天,但是在图形学里面,要做的就一件事 Faking it!镜头前的东西被模糊,远离镜头的东西比较清晰

Box filter 过于简单,高斯模糊需要两个pass,这里用一个稍微复杂的filter,一次pass就搞定,滤波器是这样的

eab959675e8daac26917fc20e3525224.png

具体的pixel shader里面是这样的

floatfInverseViewportWidth;

floatfInverseViewportHeight;

sampler Texture0;

constfloat4 samples[9] =

{

-1.0, -1.0, 0, 1.0/16.0,

-1.0, 1.0, 0, 1.0/16.0,

1.0, -1.0, 0, 1.0/16.0,

1.0, 1.0, 0, 1.0/16.0,

-1.0, 0.0, 0, 2.0/16.0,

1.0, 0.0, 0, 2.0/16.0,

0.0, -1.0, 0, 2.0/16.0,

0.0, 1.0, 0, 2.0/16.0,

0.0, 0.0, 0, 4.0/16.0

};

float4 ps_main(float2 texCoord: TEXCOORD0) : COLOR

{

float4 col = float4(0,0,0,0);

// Sample and output the averaged colors

for(inti=0;i<9;i )

col  = samples[i].w*tex2D(Texture0,texCoord

float2(samples[i].x*fInverseViewportWidth,

samples[i].y*fInverseViewportHeight));

returncol;

}

ac401c094436929647e28cafa05830f1.png

基于Depth Impostor的DOF基本的原理就是首先渲染一个模糊的RT,这个模糊的RT可能会用到很多种pass,比如之前的高斯模糊,还有上面所说的filter,进行多次叠加。然后根据之前rt里的alpha通道的值进行blend。在RenderMonkey中具体的做法首先添加一个下面几个变量

9cf73453f8368603e325331ddb45805f.png

相机的几个参数

16cfedfe6dcbc2faf3ad02d61f13e21a.png

在绘制模型的时候,要把对应的深度存储到alpha中

VS

float4x4 view_proj_matrix;

floatfar_clip;

structVS_OUTPUT

{

float4 Pos:     POSITION;

float2 Txr1:    TEXCOORD0;

float1 Depth:   TEXCOORD1;

};

VS_OUTPUT vs_main(

float4 inPos: POSITION,

float2 Txr1: TEXCOORD0

)

{

VS_OUTPUT Out;

float4 OutPos;

float4 offset;

offset.x = 200;

offset.y = 0;

offset.z = 0;

offset.w = 0;

// Compute the position of the vertex

Out.Pos = OutPos = mul(view_proj_matrix, inPos   offset);

Out.Txr1 = Txr1;

// Send the depth to the pixel shader for encoding

Out.Depth = OutPos.w/far_clip;

returnOut;

}pixel shader

floatNear_Range;

floatFar_Range;

floatNear_Dist;

floatFar_Dist;

sampler Texture0;

float4 ps_main(

float4 inDiffuse: COLOR0,

float2 inTxr1: TEXCOORD0,

float1 Depth: TEXCOORD1

) : COLOR0

{

// Compute blur factor based on   near and far focus planes

floatBlur = max(clamp(0,1, 1 - (Depth-Near_Dist)/Near_Range),

clamp(0,1, (Depth-(Far_Dist-Far_Range))/Far_Range));

//  Output constant color:

returnfloat4(tex2D(Texture0,inTxr1).rgb,Blur);

}注意,Shader中所有的运算都是行主序!注意,Shader中所有的运算都是行主序!注意,Shader中所有的运算都是行主序!

4e90265ca4de4833be2a76545a6bdc7d.png

具体来看下这个运算流程,

在VS中

Out.Pos = OutPos = mul(view_proj_matrix, inPos   offset);经过这一步的计算,Out.Pos的w取值范围就是(0, far_clip)

Out.Depth = OutPos.w/far_clip;

这一步将深度映射到0到1.

再看ps

floatBlur = max(clamp(0,1, 1 - (Depth-Near_Dist)/Near_Range), clamp(0,1,(Depth-(Far_Dist-Far_Range))/Far_Range));

这里是计算Blur值,也是后面进行blend的参数。Blend的取值范围如下

01b6422107024196e4194e4379e094cb.png

在nearRange之前和FarDist之后,取值都是1,中间部分是0,其余的部分是在0到1之前线性变化。根据NearRange,NearDis,FarRange,FarDist这几个值,就可以获得不同的景深效果。

模糊的rt处理这里就不说了,最好叠加个两三次。

最后在present的时候,只需要根据alpha值进行两张rt的Blend就可以了

88380493f1614fa7ed989b1d0ee3a343.png

bb790bc6ff741ad387bb3a62a83d1cd1.png

看一下深度的Texture

83a185f0538e93054eaac1223bdb7c1b.png取Blur值

returnfloat4(tex2D(Texture0,inTxr1).rgb,tex1D(Texture1,Depth).a);这样就省去了每次都去计算一遍算式的成本,特别是当blur的计算特别复杂的时候。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值