博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Shader 学习笔记 ---Depth of Field 介绍
阅读量:6588 次
发布时间:2019-06-24

本文共 1702 字,大约阅读时间需要 5 分钟。

老早就想实现 Depth of field 的效果了,这几天终于有点时间来好好学习并加以实现。使用的是Render Monkey 1.71,
    Render Monkey的sample里的DOF的稍微有点复杂,不过效果很漂亮。我觉得只要知道了原理并实现了基本的效果就可以了
o(∩_∩)o...
    一共分为4个pass 
   前两个pass效果一样 在两个不同的位置渲染两个teapot到BackBuffer这张纹理,并保存下相对聚焦区域的深度值
  
  1. //渲染物体的VS代码
  2. struct VS_OUTPUT
  3. {
  4.    float4 Pos    : POSITION;
  5.    float2 Tex    : TEXCOORD0;
  6.    float3 View   : TEXCOORD1;
  7.    float  depth  : TEXCOORD2;
  8. };
  9. VS_OUTPUT vs_main (
  10.    float4 inPos  : POSITION,
  11.    float2 inTex  : TEXCOORD0 )
  12. {
  13.   VS_OUTPUT Out = (VS_OUTPUT) 0; 
  14.    float4 offsetPos = inPos;
  15.    offsetPos.xyz += 10.0 * teapotPos;  //沿Z轴偏移一段距离
  16.    
  17.    // Output transformed position:
  18.    Out.Pos = mul( view_proj_matrix, offsetPos ); 
  19.    // Compute position in view space:
  20.    float3 Pview = mul( view_matrix, offsetPos ); 
  21.  
  22.    // Compute the view direction in view space:
  23.    Out.View = - normalize( Pview );
  24.    // Propagate texture coordinate for the object:
  25.    Out.Tex = inTex;
  26.    Out.depth = Pview.z;  //算出深度值
  27.    return Out;
  28.    
  29. }

 

  1. //渲染物体的PS代码
  2. float d_near;
  3. float d_focus;  //聚焦区域
  4. float d_far;
  5. sampler2D Texture0;
  6. float ComputeDepthBlur (float depth)
  7. {
  8.    float f;
  9.    f = (depth - d_focus)/d_focus;//算出当前像素点相对于d_focus的深度值
  10.    
  11.    f = clamp (f, -1.0, 1.0);  //控制在-1到1之间
  12.    return f * 0.5f + 0.5f;   //控制在0到1之间
  13.      
  14. }
  15. float4 ps_main(  float2 Tex    : TEXCOORD0, 
  16.                  float  depth  : TEXCOORD2) : COLOR
  17. {   
  18.    float4 FinalColor = tex2D(Texture0, Tex);
  19.    FinalColor.a = ComputeDepthBlur (depth);  //在纹理中保存深度值
  20.    
  21.    return FinalColor;
  22. }

   第三个pass 模糊一下BackBuffer,并渲染到Blur这张纹理

   第四个pass 混合BackBuffer和Blur这两张纹理,根据BackBuffer保存下的深度值,来确定当前像素点的模糊程度

  1. //关键的PS代码
  2. sampler2D TBlur;  //模糊的纹理
  3. sampler2D TBack;  //正常的纹理 , 保存有深度值
  4. float4 ps_main(float2 texCoord: TEXCOORD0) : COLOR {
  5.    float4 sharp = tex2D(TBack,   texCoord);
  6.    float4 blur  = tex2D(TBlur, texCoord);
  7.    // 根据深度值来决定混合的程度,即模糊的程度
  8.    return lerp(sharp, blur, sharp.w ); 
  9. }

   以下是效果图和四个PASS分别的效果
          

你可能感兴趣的文章
Fedora 12 (Constantine)Beta版及Alpha镜像下载
查看>>
稳扎稳打Silverlight(3) - 2.0控件之Border, Button, Calendar, Canvas, CheckBox, ComboBox
查看>>
Who's Using Cyberthreat Intelligence and How?
查看>>
【翻译】SQL Server索引进阶:第六级,标签
查看>>
确定两串乱序同构
查看>>
寒假研究计划
查看>>
Android:ListView、BaseAdapter、convertView、ListView优化及事件、notifyDataSetChanged()
查看>>
新版发布功能上线,新增「大屏快照」功能!
查看>>
代码调优及其他zz
查看>>
Centos7+Postfix+Dovecot实现邮件收发
查看>>
“蒜你狠”和“豆你玩”的遐想。。
查看>>
无法解析连接描述中指定的SID
查看>>
ext3格式化成ext4
查看>>
自己编译redhat 9.0内核心得
查看>>
SQL Server数据库的管理及维护
查看>>
Silverlight在MSDN类库中的小变化
查看>>
再说java多线程Thread
查看>>
两种Web页面局部刷新技术的简单较量
查看>>
管理学中的知名定律之阿什法则
查看>>
Android客户端应用享用传统Web服务
查看>>