zoukankan      html  css  js  c++  java
  • Shader 学习笔记 ---Depth of Field 介绍

    老早就想实现 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分别的效果



              

  • 相关阅读:
    Docker
    内存与缓存
    硬盘和内存的关系
    磁盘和硬盘、软盘
    mysql和redis的区别
    BZOJ 3110 k大数查询 (树套树)
    Codeforces 1303E Erase Subsequences (子序列匹配)
    Codeforces 1304E 1-Trees and Queries (树上距离+思维)(翻译向)
    BZOJ 2161 布娃娃(权值线段树)
    2019icpc徐州现场赛 H Yuuki and a problem (树状数组套主席树)
  • 原文地址:https://www.cnblogs.com/lancidie/p/2325201.html
Copyright © 2011-2022 走看看