当前位置:   article > 正文

Unity Shader PostProcessing - 9 - RadialBlur 径向模糊_unity radialblur

unity radialblur


径向模糊这个概念最初我是在高中的时候学习PS有介绍的。
当时就觉得这个效果很棒。

当然PS那个径向模糊比我实现的这个效果要好(我这个也不能实现太好的效果,运行在手机上会受不了),毕竟PS是离线编辑,且针对一帧图像处理的,不存在什么性能不性能的问题,怎么炫就怎么来。

实现

从PS上的径向模糊不难理解,就是对指定某个径向点后,如下图中的绿色点C是径向点,红色的P,Q两点别分与C点直线上的前前后后都用采样点,就那些蓝色点,越是靠近C点,采样距离越小,所以模糊程度响度来说会比较小的(意思就会相对边缘的来说会比较清晰)。
在这里插入图片描述
来看看运行中,我们将其他参数调整一下,只看采样距离
在这里插入图片描述

注意查看远处的三颗球,红色圆圈是球的原始位置,黄色箭头是前前后后分别采样的位置,越靠近径向点,采样距离就越近。

还看不出来的话,你就直接看人物的头部,中间部分是最清晰的。

控制采样步长

在代码上只要控制好采样步长就可以了:

float2 stepDir = normalize(vec) * _SampleDistance; // 每次的采样步长方向
float stepLenFactor = len * 0.1 * _Intensity; // len : 0~0.5 再乘上 0.1 就是0~0.05,越是靠近中心开,采样距离会越小,模糊度就会相对边缘来说更小
stepDir *= stepLenFactor; // 控制步长值,stepLenFactor=len * 0.1 * _Intensity中的:0.1是经验数值可以不管,或是外部公开控制也是可以的
fixed4 sum = 0;
for (int it = 0; it < sampleCount; it++) {
    float2 appliedStep = stepDir * it;
    sum += tex2D(_DownSampleRT, i.uv + appliedStep); // 正向采样
    sum += tex2D(_DownSampleRT, i.uv - appliedStep); // 反向采样
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

主要看这么一句:

float stepLenFactor = len * 0.1 * _Intensity; // len : 0~0.5 再乘上 0.1 就是0~0.05,越是靠近中心开,采样距离会越小,模糊度就会相对边缘来说更小
  • 1

就可以控制越径向点月经采样距离越小

完整代码如下:

完整的Shader

// jave.lin 2020.03.21 径向模糊 - Radial Blur
Shader "Custom/RadialBlur" {
    CGINCLUDE
    #include "UnityCG.cginc"
    struct appdata {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;
    };
    struct v2f {
        float4 vertex : SV_POSITION;
        float2 uv : TEXCOORD0;
    };
    float _Intensity;           // 径向效果的强度
    float _FadeRadius;          // 淡出径向效果的半径范围
    float _SampleDistance;      // 每次采样的距离
    sampler2D _DownSampleRT;    // 原图降采样后的图
    sampler2D _SrcTex;          // 原始图像纹理
    v2f vert(appdata v) {
        v2f o;
        o.vertex = UnityObjectToClipPos(v.vertex);
        o.uv = v.uv;
        return o;
    }
    fixed4 frag(v2f i) : SV_Target {
        const int sampleCount = 5; // 单想采样次数,乘以2就是真的总次数
        const float invSampleCount = 1.0 / ((float)sampleCount * 2);
        float2 vec = i.uv - 0.5;
        float len = length(vec);
        float fade = smoothstep(0, _FadeRadius, len); // 平滑淡出的径向效果值
        float2 stepDir = normalize(vec) * _SampleDistance; // 每次的采样步长方向
        float stepLenFactor = len * 0.1 * _Intensity; // len : 0~0.5 再乘上 0.1 就是0~0.05,越是靠近中心开,采样距离会越小,模糊度就会相对边缘来说更小
        stepDir *= stepLenFactor; // 控制步长值,stepLenFactor=len * 0.1 * _Intensity中的:0.1是经验数值可以不管,或是外部公开控制也是可以的
        fixed4 sum = 0;
        for (int it = 0; it < sampleCount; it++) {
            float2 appliedStep = stepDir * it;
            sum += tex2D(_DownSampleRT, i.uv + appliedStep); // 正向采样
            sum += tex2D(_DownSampleRT, i.uv - appliedStep); // 反向采样
        }
        sum *= invSampleCount; // 均值模糊
        return lerp(tex2D(_SrcTex, i.uv), sum, fade * _Intensity);
    }
    ENDCG
    SubShader {
        Cull Off ZWrite Off ZTest Always
        Pass {
            NAME "RADIA_BLUR"
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            ENDCG
        }
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

均值模糊

完整的Shader中,也可以看到,我也采样的是均值模糊sum *= invSampleCount; // 均值模糊,性能上也是比较高的方式。

DownSample

接下来我们再对采样图做了downSample(就是对径向模糊的数据源采样图做了降低分辨率),最后就只有58 x 27左右的尺寸,在移动端上性能是很可观的,而且降低采样图尺寸后除了占用VRAM(显存)少了,就连模糊的效果也提升了,实在是一举两得。
在这里插入图片描述
在这里插入图片描述

完整的CSharp

using UnityEngine;
/// <summary>
/// jave.lin 2020.03.21 径向模糊 Radial Blur
/// </summary>
public class RadialBlurScript : MonoBehaviour
{
    private static int _Intensity_hash = Shader.PropertyToID("_Intensity");
    private static int _FadeRadius_hash = Shader.PropertyToID("_FadeRadius");
    private static int _SampleDistance_hash = Shader.PropertyToID("_SampleDistance");
    private static int _SrcTex_hash = Shader.PropertyToID("_SrcTex");
    private static int _DownSampleRT_hash = Shader.PropertyToID("_DownSampleRT");

    public Material mat;

    [Header("Radial Blur")]
    [Range(0, 1)]
    public float intensity = 1;                         // 效果强度
    [Range(0f, 1f)]
    public float fadeRadius = 0.38f;                    // 半径范围内的都淡出
    [Range(0f, 1f)]
    public float sampleDistance = 0.25f;                // 径向模糊每次采样的距离
    [Range(1, 40)]
    public int blurDownSample = 40;                     // 模糊降低输出采样率
    private Camera cam;
    private void Start()
    {
        cam = GetComponent<Camera>();
        cam.depthTextureMode |= DepthTextureMode.Depth;
    }
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (!mat)
        {
            Graphics.Blit(source, destination);
            return;
        }
        var rw = Screen.width / blurDownSample;
        var rh = Screen.height / blurDownSample;
        RenderTexture downSampleRT = RenderTexture.GetTemporary(rw, rh, 0);
        downSampleRT.filterMode = FilterMode.Bilinear;
        downSampleRT.name = "downSampleRT";
        Graphics.Blit(source, downSampleRT);
        mat.SetFloat(_Intensity_hash, intensity);
        mat.SetFloat(_FadeRadius_hash, fadeRadius);
        mat.SetFloat(_SampleDistance_hash, sampleDistance);
        mat.SetTexture(_DownSampleRT_hash, downSampleRT);
        mat.SetTexture(_SrcTex_hash, source);
        Graphics.Blit(null, destination, mat, 0);
        RenderTexture.ReleaseTemporary(downSampleRT);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

运行效果

在这里插入图片描述
在这里插入图片描述

Project

backup : UnityShader_RadialBlurTesting_2018.3.0f2

Referneces

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/107487
推荐阅读
相关标签
  

闽ICP备14008679号