Unity Standard Assets中的SunShafts

来源:互联网 发布:java参数传递 编辑:程序博客网 时间:2024/06/06 17:41

  • 效果描述
  • 参数说明
  • 原理概述
  • 实现细节
  • 可优化之处

效果描述

模拟非常亮的光源在部分被遮挡时产生的径向光散射效果。


参数说明

Rely on Z Buffer: 该选项在高亮区域提取阶段用于决定启用哪种遮挡遮罩方法。其他略


原理概述

找出天空中未被遮挡的、亮度较高的像素区域(其他区域置零);

计算径向模糊;

与原画面混合


实现细节

效果文件内含5个Pass。第2#、3#pass分别实现颜色比较和深度比较两种未遮挡天空盒区域提取;1#pass用于径向模糊;0和4#pass分别实现Screen和Add两种混合效果。

      遮罩计算

      frag_nodepth片元着色器需要脚本调用接口:GL.ClearWithSkybox (false, GetComponent<Camera>());

      单独将天空盒绘制到一张RT上。然后在frag_nodepth中通过将此RT和原图像进行逐项素的差异比较:

      if (Luminance ( abs(sky.rgb - tex.rgb)) < 0.1)
            outColor = TransformColor (sky) * dist;


      仅绘制满足条件的像素。而且在TransformColor会进一步筛选掉亮度超过给定阈值的像素。dist作为圆形遮罩限制效果作用范围。

// consider maximum radius

  #if UNITY_UV_STARTS_AT_TOP

    half2 vec = _SunPosition.xy - i.uv1.xy;

  #else

    half2 vec = _SunPosition.xy - i.uv.xy;
  #endif

    half dist = saturate (_SunPosition.w - length (vec));
    
   frag_depth片元着色器需要使用_CameraDepthTexture。将采样的深度之转换至线性化的0~1区间,然后通过与给定值比较获取遮罩。
depthSample = Linear01Depth (depthSample);
    …

    half4 outColor = 0;

    // consider shafts blockers

    if (depthSample > 0.99)

        outColor = TransformColor (tex) * dist;


  径向模糊

  v2f_radial vert_radial( appdata_img v ) {

      v2f_radial o;

      o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

      o.uv.xy =  v.texcoord.xy;

      o.blurVector = (_SunPosition.xy - v.texcoord.xy) * _BlurRadius4.xy;
      return o; 
  
}

  half4 frag_radial(v2f_radial i) : SV_Target 
 {
      half4 color = half4(0,0,0,0);

      for(int j = 0; j < SAMPLES_INT; j++)   
{
          half4 tmpColor = tex2D(_MainTex, i.uv.xy);

          color += tmpColor;

          i.uv.xy += i.blurVector;
      }
 return color / SAMPLES_FLOAT;

  }

可优化之处

    代码中反复调用GetComponent<Camera>()获取Camera组件。需做缓存优化。

    原来的实现在遮罩绘制完后会吊用DrawBorder()在其上覆盖绘制一个黑色的边框,防止采样clamping时出现问题。可以修改为在绘制遮罩时用黑色做目标RT的Clear,然后Bliting时使用调整后的顶点数据绘制目标RT。便可优化掉一次拷贝和边框的绘制。

源码:https://github.com/Mikeyiy/unity_image_effects_review

0 0
原创粉丝点击