• unity shader屏幕后处理


    屏幕的亮度、饱和度、对比度

    实现效果:

    unity屏幕后处理之屏幕的亮度、饱和度、对比度

    实现代码:
    脚本:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    //继承脚本中的检测基类:PostEffectsBase
    public class BrightnessSaturationAndContrast : PostEffectsBase
    {
        //定义shader和材质
        public Shader briSatConShader;
        private Material briSatConMaterial;
    
        //亮度
        [Range(0.0f, 3.0f)]
        public float brightness = 1.0f;
        //饱和度
        [Range(0.0f, 3.0f)]
        public float saturation = 1.0f;
        //对比度
        [Range(0.0f, 3.0f)]
        public float contrast = 1.0f;
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        //特效处理
        private void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (material != null)
            {
                material.SetFloat("_Brightness", brightness);
                material.SetFloat("_Saturation", saturation);
                material.SetFloat("_Contrast", contrast);
    
                Graphics.Blit(source, destination, material);
            }
            else
            {
                Graphics.Blit(source, destination);
            }
        }
        //访问private的material
        public Material material
        {
            get
            {
                //使用briSatConShader的briSatConMaterial材质
                briSatConMaterial = CheckShaderAndCreateMaterial(briSatConShader, briSatConMaterial);
                return briSatConMaterial;
            }
        }
    }
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59

    shader:

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "Custom/Chapter12-BrightnessSaturationAndContrast"
    {
        Properties
        {
            _MainTex ("Albedo (RGB)", 2D) = "white" {}
        }
        SubShader
        {
        Pass{
        //深度写入关闭剔除关闭
        ZTest Always Cull Off ZWrite Off
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "unityCG.cginc"
    
        sampler2D _MainTex;
        half _Brightness;
        half _Saturation;
        half _Contrast;
    
        struct v2f{
        float4 pos:SV_POSITION;
        half2 uv:TEXCOORD0;
        };
    
        //调用内置的结构体,只包含顶点信息和纹理坐标
        v2f vert(appdata_img v){
        v2f i;
        i.pos=UnityObjectToClipPos(v.vertex);
        i.uv=v.texcoord;
        return i;
        }
        fixed4 frag(v2f i):SV_Target{
        fixed4 renderTex=tex2D(_MainTex,i.uv);
        //亮度直接乘以颜色
        fixed3 finalColor =renderTex.rgb*_Brightness;
    
        //饱和度
        //计算亮度值
        fixed luminance =renderTex.r*0.2125+renderTex.g*0.7154+renderTex.b*0.0721;
        fixed3 luminanceColor =fixed3(luminance,luminance,luminance);
        //一开始的颜色值和finalcolor差值得到
        finalColor=lerp(luminanceColor,finalColor,_Saturation);
    
        //对比度
        fixed3 avgColor=fixed3(0.5,0.5,0.5);
        finalColor=lerp(avgColor,finalColor,_Contrast);
    
        //用采样颜色的透明通道值
        return fixed4(finalColor,renderTex.a);
        }
        ENDCG
        }
        }
        FallBack Off
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    边缘检测

    原理:
    利用一些边缘检测算子对图像进行卷积操作。
    常见的边缘检测卷积核
    因为边缘的判断其实就是相邻的像素之间的存在差异明显的属性,所以卷积核都是水平和竖直方向都要进行计算,得到两个梯度。
    在这里插入图片描述
    最终的梯度一般有一下两种方式
    在这里插入图片描述
    在这里插入图片描述
    梯度值越大越可能是边缘
    实现效果:
    在这里插入图片描述
    脚本代码:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class EdgeDetection : PostEffectsBase
    {
        public Shader edgeDetectShader;
        private Material edgeDetectMaterial;
        //屏幕后处理的所可以调节和被shader所需要的参数
        //边缘线强度,如果为0则边缘线会叠加在原渲染图像上,如果为1则只有边缘线
        [Range(0.0f, 1.0f)]
        public float edgesOnly = 0.0f;
        //边缘线颜色
        public Color edgeColor = Color.black;
        //背景颜色
        public Color backgroundColor = Color.white;
        public Material material
        {
            get
            {
                edgeDetectMaterial = CheckShaderAndCreateMaterial(edgeDetectShader, edgeDetectMaterial);
                return edgeDetectMaterial;
            }
        }
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
        private void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (material != null)
            {
                material.SetFloat("_EdgeOnly", edgesOnly);
                material.SetColor("_EdgeColor", edgeColor);
                material.SetColor("_BackgroundColor", backgroundColor);
    
                Graphics.Blit(source, destination, material);
            }
            else
            {
                Graphics.Blit(source, destination);
            }
        }
    }
    
    • 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

    shader代码

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "Custom/Chapter12_EdgeDetection"
    {
        Properties
        {
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader
        {
        Pass{
        ZTest Always Cull Off ZWrite Off
    
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "unityCG.cginc"
    
        sampler2D _MainTex;
        //纹理的纹素的大小
        half4 _MainTex_TexelSize;
        //为0的时候是叠加,为1的时候是只有边缘
        half _EdgeOnly;
        half4 _EdgeColor;
        //只有边缘时候的背景颜色
        half4 _BackgroundColor;
    
        struct v2f{
        float4 pos:SV_POSITION;
        half2 uv[9]:TEXCOORD0;
        };
    
        v2f vert(appdata_img i){
        v2f o;
        o.pos=UnityObjectToClipPos(i.vertex);
        half2 uv=i.texcoord;
        //原本只用一个纹理坐标,但是卷积核需要使用周围的纹理坐标,所以需要存储9个纹理坐标
        o.uv[0]=uv+_MainTex_TexelSize*half2(-1,-1);
        o.uv[1]=uv+_MainTex_TexelSize*half2(0,-1);
        o.uv[2]=uv+_MainTex_TexelSize*half2(1,-1);
        o.uv[3]=uv+_MainTex_TexelSize*half2(-1,0);
        o.uv[4]=uv+_MainTex_TexelSize*half2(0,0);
        o.uv[5]=uv+_MainTex_TexelSize*half2(1,0);
        o.uv[6]=uv+_MainTex_TexelSize*half2(-1,1);
        o.uv[7]=uv+_MainTex_TexelSize*half2(0,1);
        o.uv[8]=uv+_MainTex_TexelSize*half2(1,1);
        return o;
        }
    
        //计算颜色的亮度值
        fixed luminance(fixed4 color){
        return 0.2125*color.r+0.7154*color.g+0.0721*color.b;
        }
    
        half Sobel(v2f i){
        //卷积核
        const half Gx[9]={-1,-2,-1,0,0,0,1,2,1};
        const half Gy[9]={-1,0,1,-2,0,2,-1,0,1};
    
        //每个纹素的颜色值
        half texColor;
        //梯度值
        half edgeX=0;
        half edgeY=0;
        for(int j=0;j<9;j++){
        texColor=luminance(tex2D(_MainTex,i.uv[j]));
        edgeX+=texColor*Gx[j];
        edgeY+=texColor*Gy[j];
        }
        return 1-abs(edgeX)-abs(edgeY);
        }
    
        fixed4 frag(v2f i):SV_Target{
        half edge =Sobel(i);
        //edge越大说明梯度值越小,则图像颜色占比较多
        fixed4 withEdgeColor =lerp(_EdgeColor,tex2D(_MainTex,i.uv[4]),edge);
        //edge越大说明梯度值越小,则背景颜色偏大
        fixed4 onlyEdgeColor =lerp(_EdgeColor,_BackgroundColor,edge);
        //最终根据_EdgeOnly差值取得最终的颜色
        fixed4 c=lerp(withEdgeColor,onlyEdgeColor,_EdgeOnly);
        return c;
        }
    
        ENDCG
        }
        }
        FallBack "Diffuse"
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    高斯模糊

    模糊有几种方式:

    • 中值模糊:将领域内的像素排序之后取中值,作为该像素的颜色。
    • 均值模糊:将领域内的像素相加除以个数,得到的均值作为颜色。
      高斯模糊:
      使用高斯核,高斯核由高斯方程得到,高斯核内数据相加为1,不会改变画面亮度。
      在这里插入图片描述
      x和y表示当前位置和卷积核中心的整数距离,距离越远,影响越小,距离越近,影响越大。
      我们可以将正方形的高斯核压缩成两个横向和竖向的卷积核,效果是一样的。
      在这里插入图片描述
      横向的是每一竖列的相加,竖向的是每一横列相加的结果。
      实现效果:
      在这里插入图片描述
      脚本代码:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class GaussianBlur : PostEffectsBase
    {
        public Shader gaussianBlurShader;
        private Material gaussianBlurMaterial = null;
        //迭代次数
        [Range(0, 4)]
        public int iterations = 3;
        //模糊范围
        [Range(0.2f, 3.0f)]
        public float blurSpread = 0.6f;
        //缩放系数,越大需要处理的像素越少,同时可以进一步提高模糊程度,但是过大可能会使得图像像素化。
        [Range(1, 8)]
        public int downSample = 2;
        public Material material
        {
            get
            {
                gaussianBlurMaterial = CheckShaderAndCreateMaterial(gaussianBlurShader, gaussianBlurMaterial);
                return gaussianBlurMaterial;
            }
        }
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    
        public void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (material != null)
            {
                int rtW = source.width / downSample;
                int rtH = source.height / downSample;
    
                //创建缓冲buffer0
                RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
                //设置滤波模式为双线性
                buffer0.filterMode = FilterMode.Bilinear;
                //将src中的屏幕图像传入buffer0
                Graphics.Blit(source, buffer0);
    
                for(int i = 0; i < iterations; i++)
                {
                    //给shader传参数
                    material.SetFloat("_BlurSize", 1.0f + i * blurSpread);
    
                    //新建buffer1,并且进行垂直的模糊处理将得到的图形传递存到buffer1中
                    RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                    Graphics.Blit(buffer0, buffer1, material,0);
    
                    //释放buffer0,并且把模糊后得到的图形赋值给buffer0
                    RenderTexture.ReleaseTemporary(buffer0);
                    buffer0 = buffer1;
    
                    //buffer1重新分配
                    buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                    Graphics.Blit(buffer0, buffer1, material,1);
    
                    RenderTexture.ReleaseTemporary(buffer0);
                    //buffer0储存这一次模糊的结果作为下一次模糊处理的输入图像
                    buffer0 = buffer1;
                }
                //模糊处理之后的结果输出到屏幕上
                Graphics.Blit(buffer0, destination);
                RenderTexture.ReleaseTemporary(buffer0);
            }
            else
            {
                Graphics.Blit(source, destination);
            }
        }
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    shader

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "Custom/Chapter12-GaussianBlur"
    {
        Properties
        {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _BlurSize("_BlurSize",Float)=1.0
        }
        SubShader
        {
            //类似头文件
            CGINCLUDE
            #include "unityCG.cginc"
            sampler2D _MainTex;
            half4 _MainTex_TexelSize;
            float _BlurSize;
    
            //片段着色器的结构体
            struct v2f{
            float4 pos:SV_POSITION;
            //存放采样坐标
            half2 uv[5]:TEXCOORD0;
            };
    
            //垂直顶点着色器
            v2f vertBlurVertical(appdata_img v){
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            half2 uv=v.texcoord;
    
            //每个像素点的纹理坐标不单单是一个而是五个
            o.uv[0] = uv;
            o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
            o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
    		o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
    		o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
            return o;
            }
    
            //水平顶点着色器
            v2f vertBlurHorizontal(appdata_img v){
            v2f o;
            o.pos = UnityObjectToClipPos(v.vertex);
            half2 uv=v.texcoord;
    
            o.uv[0] = uv;
            o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0,0.0) * _BlurSize;
            o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0,0.0) * _BlurSize;
    		o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0,0.0) * _BlurSize;
    		o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0,0.0) * _BlurSize;
            return o;
            }
    
            //通用片段着色器
            fixed4 frag(v2f i):SV_Target{
            //横向和纵向的高斯核相对称
            //存储权重,因为对称所以只有三个
            float weight[3]={0.4026,0.2442,0.0545};
    
            //中间的权重是独特的不是对称的所以单独计算
            fixed3 sum=tex2D(_MainTex,i.uv[0]).rgb*weight[0];
            //计算另外四个
            for(int it=1;it<3;it++){
            sum +=tex2D(_MainTex,i.uv[it]).rgb*weight[it];
            sum +=tex2D(_MainTex,i.uv[it*2]).rgb*weight[it];
            }
    
            return fixed4(sum,1.0);
            }
            ENDCG
    
            ZTest Always Cull Off ZWrite Off
            Pass{
            //设置pass名称方便在其他的shader中调用
            NAME "GAUSSIAN_BLUR_VERTICAL"
            CGPROGRAM
            #pragma vertex vertBlurVertical
            #pragma fragment frag
            ENDCG
            }
    
            Pass{
            //设置pass名称方便在其他的shader中调用
            NAME "GAUSSIAN_BLUR_HORIZONTAL"
            CGPROGRAM
            #pragma vertex vertBlurHorizontal
            #pragma fragment frag
            ENDCG
            }
        }
        FallBack Off
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    CGINCLUDE和ENDCG中间定义的代码,不用包含在任何pass中,使用时也只用调用其中的函数名即可

    曝光效果

    实现步骤

    1. 首先根据一个阙值,将画面中较亮的区域存储在一张渲染纹理中。
    2. 利用高斯模糊对于这一张渲染纹理做模糊处理,扩散较亮的区域。
    3. 将模糊处理过的纹理与原图像进行混合。
      实现效果:
      在这里插入图片描述
      脚本代码
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Bloom : PostEffectsBase
    {
        public Shader bloomShader;
        private Material bloomMaterial = null;
        public Material material
        {
            get
            {
                bloomMaterial = CheckShaderAndCreateMaterial(bloomShader, bloomMaterial);
                return bloomMaterial;
            }
        }
    
        //迭代次数
        [Range(0, 4)]
        public int iterations = 3;
        //模糊范围
        [Range(0.2f, 3.0f)]
        public float blurSpread = 0.6f;
        //缩放系数
        [Range(1, 8)]
        public int downSample = 2;
        //提取较亮范围的阙值
        [Range(0.0f,4.0f)]
        public float luminanceThreshold = 0.6f;
        // Start is called before the first frame update
        void Start()
        {
            
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
        public void OnRenderImage(RenderTexture source, RenderTexture destination)
        {
            if (material != null)
            {
                //传参
                material.SetFloat("_LuminanceThreshold", luminanceThreshold);
                int rtW = source.width / downSample;
                int rtH = source.height / downSample;
    
                RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
                buffer0.filterMode = FilterMode.Bilinear;
    
                //用material中的shader中的第一个pass提取出较亮区域存放在buffer0中
                Graphics.Blit(source, buffer0, material, 0);
                for(int i = 0; i < 3; i++)
                {
                    material.SetFloat("_BlurSize", 1.0f + i * blurSpread);
    
                    RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                    Graphics.Blit(buffer0, buffer1, material, 1);
                    RenderTexture.ReleaseTemporary(buffer0);
                    buffer0 = buffer1;
                    buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);
                    Graphics.Blit(buffer0, buffer1, material, 2);
                    RenderTexture.ReleaseTemporary(buffer0);
                    buffer0 = buffer1;
                }
    
                //将提取出来的图像模糊处理后存储到纹理中
                material.SetTexture("_Bloom", buffer0);
                //利用第四个pass将模糊的图像和原图合并起来
                Graphics.Blit(source, destination, material, 3);
                RenderTexture.ReleaseTemporary(buffer0);
            }
            else
            {
                Graphics.Blit(source, destination);
            }
        }
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    shader

    // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
    
    Shader "Custom/Chapter12-Bloom"
    {
        Properties
        {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _Bloom("Bloom (RGB)",2D)="black"{}
            _LuminanceThreshold("Luminance Threshold",Float)=0.5
            _BlurSize("Blur Size",Float)=1.0
        }
        SubShader
        {
        CGINCLUDE
    
        #include "unityCG.cginc"
        sampler2D _MainTex;
        half4 _MainTex_TexelSize;
        sampler2D _Bloom;
        float _LuminanceThreshold;
        float _BlurSize;
    
        struct v2f{
        float4 pos:SV_POSITION;
        half2 uv:TEXCOORD0;
        };
    
        //提取亮区域的顶点着色器
        v2f vertExtractBright(appdata_img v){
        v2f o;
        o.pos =UnityObjectToClipPos(v.vertex);
        o.uv = v.texcoord;
        return o;
        }
        float luminance(fixed4 color){
        return color.r*0.2125+color.g*0.7154+color.b*0.0721;
        }
        //提取亮区域的片段着色器
        fixed4 fragExtractBright(v2f i):SV_Target{
        fixed4 c =tex2D(_MainTex,i.uv);
        //当亮度小于阙值的时候,val为0,则原图像的颜色丢失,大于阙值,最大值为1,也就是图像原来的颜色
        fixed val=clamp(luminance(c)-_LuminanceThreshold,0.0,1.0);
        return c*val;
        }
    
        //混合图像的片段着色器的结构图
        struct v2fbloom{
        float4 pos:SV_POSITION;
        half4 uv:TEXCOORD0;
        };
    
        //顶点着色器
        v2fbloom vertBloom(appdata_img v){
        v2fbloom o;
        o.pos =UnityObjectToClipPos(v.vertex);
        o.uv.xy =v.texcoord;
        o.uv.zw =v.texcoord;
    
        //平台差异化处理
        #if UNITY_UV_STARTS_AT_TOP
        if(_MainTex_TexelSize.y<0.0){
        o.uv.w=1.0-o.uv.w;
        }
        #endif
    
        return o;
        }
    
        //片段着色器
        fixed4 fragBloom(v2fbloom i):SV_Target{
        return tex2D(_MainTex,i.uv.xy)+tex2D(_Bloom,i.uv.zw);
        }
        ENDCG
    
        ZTest Always Cull Off ZWrite Off
    
        //提取亮区域的pass
        Pass{
        CGPROGRAM
        #pragma vertex vertExtractBright
        #pragma fragment fragExtractBright
        ENDCG
        }
    
        //模糊处理
        UsePass "Custom/Chapter12-GaussianBlur/GAUSSIAN_BLUR_VERTICAL"
        UsePass "Custom/Chapter12-GaussianBlur/GAUSSIAN_BLUR_HORIZONTAL"
    
        //混合图像pass
        Pass{
        CGPROGRAM
        #pragma vertex vertBloom
        #pragma fragment fragBloom
        ENDCG
        }
        }
        FallBack Off
    }
    
    
    • 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
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
  • 相关阅读:
    milvus和相似度检索
    Unity的PICO项目基础环境搭建笔记(调试与构建应用篇)
    Vue学习笔记(二)
    寻找和利用 XXE – XML 外部实体注入
    MySQL高可用
    sha256为什么不可逆,sha256的安全性如何
    mybatis-spring的整合
    [运维|中间件] Apache APISIX使用笔记
    pdd.order.basic.list.get订单基础信息列表查询接口(拼多多店铺订单列表查询接口)代码对接教程
    Linux用户管理指南:创建、删除、权限、最佳实践,全面掌握用户管理技巧
  • 原文地址:https://blog.csdn.net/weixin_46525412/article/details/125491672