UnityShader---屏幕后处理(内置渲染管线)---13

后处理Unity基本上都提供了相应的实现了。

后处理基类:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(Camera))]
public class PostEffectBase : MonoBehaviour
{

    public Shader usedShader;
    protected Material usedMaterial;

    public Material material
    {
        get
        {
            usedMaterial = CheckShaderAndCreateMaterial(usedShader,usedMaterial);
            return usedMaterial;
        }
    }



    void Start()
    {
        CheckResources();
    }


    protected void CheckResources()
    {
        bool isSupported = CheckSupport();

        if (isSupported == false)
        {
            NotSupport();
        }
    }

    private void NotSupport()
    {
        enabled = false;
    }

    private bool CheckSupport()
    {
        if (SystemInfo.supportsImageEffects == false || SystemInfo.supportsRenderTextures == false)
        {
            Debug.LogError("不支持后处理!");
            return false;
        }

        return true;
    }


    protected Material CheckShaderAndCreateMaterial(Shader shader, Material material)
    {
        if (shader == null)
        {
            return null;
        }

        if (shader.isSupported && material && material.shader == shader)
            return material;

        if (!shader.isSupported)
        {
            return null;
        }
        else
        {
            material = new Material(shader);
            material.hideFlags = HideFlags.DontSave;
            if (material)
                return material;
            else
                return null;
        }
    }
}

调整屏幕亮度饱和度和对比度:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class BrightnessSaturationAndContrast : PostEffectBase
{ 
    [Range(0, 3f)]
    public float brightness = 1;

    [Range(0, 3f)]
    public float saturation = 1;

    [Range(0, 3f)]
    public float contrast = 1;


    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);
        }
    }
}
Shader "Unlit/26"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Brightness("Brightness",Float)=1
        _Saturation("Saturation",Float)=1
        _Contrast("Contrast",Float)=1
    }
    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 a2v
            {
                float4 vertex : POSITION;
                float2 texcoord : TEXCOORD0;
            };

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
                
            };

            v2f vert (a2v v)
            {
                v2f o;

                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord;    

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {               
                fixed4 renderTex = tex2D(_MainTex, i.uv);

                //应用亮度
                fixed3 finalColor = renderTex.rgb * _Brightness;

                //应用饱和度
                fixed luminance = 0.2125 * renderTex.r + 0.7154 * renderTex.g + 0.0721 * renderTex.b;
                fixed3 luminanceColor = fixed3(luminance,luminance,luminance);

                finalColor = lerp(luminance, finalColor,_Saturation);

                //应用对比度
                fixed3 avgColor = fixed3(0.5, 0.5, 0.5);

                finalColor = lerp(avgColor,finalColor,_Contrast);
               
                return fixed4(finalColor,renderTex.a); 
            }
            ENDCG
        }
    }
}

边缘检测:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EdgeDetection : PostEffectBase
{
    [Range(0,1f)]
    public float edgeOnly = 0;

    public Color edgeColor = Color.black;

    public Color backgroundColor = Color.white;

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            material.SetFloat("_EdgeOnly", edgeOnly);
            material.SetColor("_EdgeColor", edgeColor);
            material.SetColor("_BackgroundColor", backgroundColor);

            Graphics.Blit(source, destination, material);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/27"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _EdgeOnly("EdgeOnly",Float)=1
        _EdgeColor("EdgeColor",Color)=(0,0,0,1)
        _BackgroundColor("BackgroundColor",Color)=(1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag          

            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float _EdgeOnly;
            fixed4 _EdgeColor;
            fixed4 _BackgroundColor;

            struct v2f
            {
                float4 pos : SV_POSITION;
                half2 uv[9] : TEXCOORD0;               
            };

            v2f vert (appdata_img v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                
                half2 uv = v.texcoord;

                o.uv[0] = uv + _MainTex_TexelSize.xy * half2(-1,-1);
                o.uv[1] = uv + _MainTex_TexelSize.xy * half2(0, -1);
                o.uv[2] = uv + _MainTex_TexelSize.xy * half2(1, -1);
                o.uv[3] = uv + _MainTex_TexelSize.xy * half2(-1, 0);
                o.uv[4] = uv + _MainTex_TexelSize.xy * half2(0, 0);
                o.uv[5] = uv + _MainTex_TexelSize.xy * half2(1, 0);
                o.uv[6] = uv + _MainTex_TexelSize.xy * half2(-1, 1);
                o.uv[7] = uv + _MainTex_TexelSize.xy * half2(0, 1);
                o.uv[8] = uv + _MainTex_TexelSize.xy * half2(1, 1);

                return o;
            }

            fixed luminance(fixed4 color)
            {
                return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
            }

            //Sobel边缘检测算子
            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]));
                    //texColor = tex2D(_MainTex,i.uv[j]);

                    edgeX += texColor * Gx[j];
                    edgeY += texColor * Gy[j];
                }

                half edge = 1 - abs(edgeX) - abs(edgeY);

                return edge;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                half edge = Sobel(i);

                //edge=0 是边,edge=1 是原图(采样中间值),0-1之间的进行混合
                
                //edge = edge < 0.1 ? 0 : 1;
                
                fixed4 withEdgeColor = lerp(_EdgeColor,tex2D(_MainTex,i.uv[4]),edge);
                fixed4 onlyEdgeColor = lerp(_EdgeColor,_BackgroundColor,edge);

                return lerp(withEdgeColor, onlyEdgeColor, _EdgeOnly);
            }
            ENDCG
        }
    }
    Fallback Off
}

高斯模糊:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GaussianBlur : PostEffectBase
{
    [Range(0, 4)]
    public int iterations = 3;

    [Range(0.2f, 3f)]
    public float blurSpread = 0.6f;

    [Range(1, 8)]
    public int downSample = 2;

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            int rtW = source.width / downSample;
            int rtH = source.height / downSample;

            RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);
            buffer0.filterMode = FilterMode.Bilinear;

            Graphics.Blit(source, buffer0);

            for (int i = 0; i < iterations; i++)
            {
                material.SetFloat("_BlurSize", 1 + i * blurSpread);

                RenderTexture buffer1 = RenderTexture.GetTemporary(rtH, rtW, 0);

                Graphics.Blit(buffer0, buffer1, material, 0);

                RenderTexture.ReleaseTemporary(buffer0);

                buffer0 = buffer1;

                buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);

                Graphics.Blit(buffer0, buffer1, material, 1);

                RenderTexture.ReleaseTemporary(buffer0);

                buffer0 = buffer1;
            }

            Graphics.Blit(buffer0, destination);

            RenderTexture.ReleaseTemporary(buffer0);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/28"
{
    Properties 
    {
        _MainTex("Base (RGB)", 2D) = "white" {}
        _BlurSize("Blur Size", Float) = 1.0        // 模糊采样距离,过大会产生虚影
    }

    SubShader 
    {
        // 类似C++头文件功能。使用时不用包含在Pass块,Pass中直接指定顶点和片元着色器,可避免编写两个一样的frag函数
        CGINCLUDE

        #include "UnityCG.cginc"

        sampler2D _MainTex;
        float4 _MainTex_TexelSize;
        float _BlurSize;
       
        struct v2f 
        {
            float4 pos : SV_POSITION;
            half2 uv[5]: TEXCOORD0;
        };

        // appdata_img定义在UnityCG.cginc
        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;
        }
        // 两个Pass公用片元着色器
        fixed4 fragBlur(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 * 2 - 1]).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 
        {
            NAME "GAUSSIAN_BLUR_VERTICAL"           // 定义名字。可以从其他Shader直接来使用该Pass
            CGPROGRAM
            #pragma vertex vertBlurVertical  
            #pragma fragment fragBlur
            ENDCG
        }
        Pass 
        {
            NAME "GAUSSIAN_BLUR_HORIZONTAL"
            CGPROGRAM
            #pragma vertex vertBlurHorizontal  
            #pragma fragment fragBlur
            ENDCG
        }
    }
} 

Bloom:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bloom : PostEffectBase
{
    [Range(0, 4)]
    public int iterations = 3;

    [Range(0.2f, 3f)]
    public float blurSpread = 0.6f;

    [Range(1, 8)]
    public int downSample = 2;

    [Range(0, 4f)]
    public float luminanceThreshold = 0.5f;


    private 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;

            Graphics.Blit(source, buffer0, material, 0);

            for (int i = 0; i < iterations; i++)
            {
                material.SetFloat("_BlurSize", 1 + i * blurSpread);

                RenderTexture buffer1 = RenderTexture.GetTemporary(rtH, rtW, 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);
            Graphics.Blit(source, destination, material, 3);

            RenderTexture.ReleaseTemporary(buffer0);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/29"
{
	Properties
	{
		_MainTex("Base (RGB)", 2D) = "white" {}
		_Bloom("Bloom",2D) = "black"{}
		_LuminanceThreshold("LuminanceThreshold",Float) = 0.5
		_BlurSize("Blur Size", Float) = 1.0        // 模糊采样距离,过大会产生虚影
	}

		SubShader
		{
			// 类似C++头文件功能。使用时不用包含在Pass块,Pass中直接指定顶点和片元着色器,可避免编写两个一样的frag函数
			CGINCLUDE

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float4 _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;
			}

			//获取亮度值
			fixed luminance(fixed4 color)
			{
				return 0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b;
			}

			fixed4 fragExtractBright(v2f i) :SV_Target
			{
				fixed4 col = tex2D(_MainTex,i.uv);

				fixed val = clamp(luminance(col) - _LuminanceThreshold, 0.0, 1.0);

				return col * val;
			}
			
			//定义混合Pass 用的

			struct v2fBloom
			{
				float4 pos:SV_POSITION;
				float4 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)
					o.uv.w = 1 - 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
			{
				CGPROGRAM

				#pragma vertex vertExtractBright
				#pragma fragment fragExtractBright

				ENDCG
			}

			UsePass "Unlit/28/GAUSSIAN_BLUR_VERTICAL"
			UsePass "Unlit/28/GAUSSIAN_BLUR_HORIZONTAL"

			Pass
			{
				CGPROGRAM

				#pragma vertex vertBloom
				#pragma fragment fragBloom

				ENDCG
			}
		}
}

运动模糊:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

public class MotionBlur : PostEffectBase
{
    [Range(0, 1f)]
    public float blurAmount = 0.5f;

    //累计图像叠加缓存
    private RenderTexture accumulationTexture;

    private void OnDisable()
    {
        DestroyImmediate(accumulationTexture);
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (material != null)
        {
            if (accumulationTexture == null || accumulationTexture.width != source.width || accumulationTexture.height != source.height)
            {
                DestroyImmediate(accumulationTexture);
                accumulationTexture = new RenderTexture(source.width, source.height, 0);
                accumulationTexture.hideFlags = HideFlags.HideAndDontSave;
                Graphics.Blit(source, accumulationTexture);
            }

            accumulationTexture.MarkRestoreExpected();

            material.SetFloat("_BlurAmount", 1 - blurAmount);

            Graphics.Blit(source,accumulationTexture,material);

            Graphics.Blit(accumulationTexture,destination);
        }
        else
        {
            Graphics.Blit(source, destination);
        }
    }
}
Shader "Unlit/30"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurAmount("BlurAmount",Float)=0.5
    }
    SubShader
    {
        CGINCLUDE

        #include "UnityCG.cginc"

        sampler2D _MainTex;
        fixed _BlurAmount;

        struct v2f
        {
            float4 pos:SV_POSITION;
            half2 uv:TEXCOORD0;
        };

        v2f vert(appdata_img v) 
        {
            v2f o;

            o.pos = UnityObjectToClipPos(v.vertex);

            o.uv = v.texcoord;

            return o;
        }

        fixed4 fragRGB(v2f i) :SV_Target
        {
            return fixed4(tex2D(_MainTex,i.uv).rgb,_BlurAmount);
        }

        half4 fragA(v2f i):SV_Target
        {
            return tex2D(_MainTex,i.uv);
        }


        ENDCG

        ZTest Always Cull Off ZWrite Off

        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha

            ColorMask RGB

            CGPROGRAM

            #pragma vertex vert
            #pragma fragment fragRGB

            ENDCG
        }

        Pass
        {
            Blend One Zero
            ColorMask A
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment fragA
            ENDCG
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值