后处理SSAO,双边模糊

后处理SSAO

//C#

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


public class ScreenSpaceAmbientAcclusion : PostProcessBase
{
    private Camera mainCamera;
    public Camera camera 
    {
        get 
        {
            if(mainCamera == null)
            {
                mainCamera= GetComponent<Camera>();
            }
            return mainCamera;
        }
    }
    public Shader SSAOShader;
    private Material ssaoMaterial;

    
    public Material ssaoMat
    {
        get
        {
            ssaoMaterial = CheckShaderAndCreateMaterial(SSAOShader, ssaoMaterial); 
            return ssaoMaterial;
        }
    }

    public Shader BlurShader;
    private Material blurMaterial;
    public Material blurMat
    {
        get
        {
            blurMaterial = CheckShaderAndCreateMaterial(BlurShader, blurMaterial); 
            return blurMaterial;
        }
    }

    void OnEnable()
    {
        camera.depthTextureMode |= DepthTextureMode.DepthNormals;   
    }
    
    [Range(1,256)]
    public int SampleCount;
    [Range(0.01f, 0.5f)]
    public float SampleRadius;                      //SSAO 相机空间 随机半径最大值。
    public Color AOColor = new Color(0.0f,0.0f,0.0f);

    [Range(0.0f, 0.1f)]
    public float UVOffset;                          //双边模糊采样UV偏移。
    [Range(0.0f, 1.0f)]
    public float BilaterFilterFactor;               //法线比较的敏感度,值越大,法线差别对模糊的影响越小。
    
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Matrix4x4 cameraProj = camera.projectionMatrix;
        ssaoMat.SetMatrix("_Matrix_P",cameraProj);
        ssaoMat.SetMatrix("_Matrix_IP", cameraProj.inverse);         //传入投影矩阵逆矩阵
        ssaoMat.SetInt("_SampleCount", SampleCount);
        ssaoMat.SetFloat("_SampleRadius", SampleRadius);
        ssaoMat.SetColor("_AOColor", AOColor);

        
        RenderTexture buffer0 = RenderTexture.GetTemporary(src.width / 2, src.height / 2, 0);       //downsample
        RenderTexture buffer1 = RenderTexture.GetTemporary(src.width / 2, src.height / 2, 0);
        Graphics.Blit(src, buffer0, ssaoMat, 0);

        blurMat.SetFloat("_UVOffset",UVOffset);              //模糊AO图
        blurMat.SetFloat("_BilaterFilterFactor",BilaterFilterFactor);
        Graphics.Blit(buffer0, buffer1, blurMat,0);
        Graphics.Blit(buffer1, buffer0, blurMat, 1);
        
        blurMat.SetTexture("_AoTex", buffer0);                   //与原图叠加
        
        Graphics.Blit(src, dest, blurMat, 2);
        Graphics.Blit(src, dest, blurMat, 2);
    }
}
//SSAO shader

Shader "may/SSAO"
{
    Properties
    {
        _MainTex("Source Tex", 2D) = "white"{}
        
    }
    SubShader
    {
        Cull Off ZWrite Off ZTest Always
        pass
        {
            Blend Off
            CGPROGRAM
            #pragma vertex vert 
            #pragma fragment frag 
            #include "UnityCG.cginc"
            sampler2D _MainTex;
            sampler2D _CameraDepthNormalsTexture;   //深度法线图
            
            float4x4 _Matrix_IP;    //逆矩阵
            float4x4 _Matrix_P;
            int _SampleCount;       //半球采样点数量
            float _SampleRadius;    //半球半径
            fixed4 _AOColor;        //ao的颜色,默认黑色

            struct a2v 
            {
                float4 vertex:POSITION;
                float2 uv:TEXCOORD;
            };
            struct v2f 
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD;
            };
            
            v2f vert(a2v v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }

            float RandomFloat(float2 uv)    //随机
            {
                return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453);
            }
            float3 RandomFloat3(float2 uv)  //随机向量  单位随机向量 * [-1,1]
            {
                float3 ranVector;
                ranVector.x = RandomFloat(uv) * 2 - 1;
                ranVector.y = RandomFloat(uv*uv) * 2 - 1;
                ranVector.z = RandomFloat(uv*uv*uv) * 2 - 1;
                return normalize(ranVector);
            }

            fixed4 frag(v2f i):SV_TARGET
            {
                //重建世界坐标
                float depthTex =  DecodeFloatRG(tex2D(_CameraDepthNormalsTexture, i.uv).zw);
                float3 normalVS = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, i.uv));
                float4 posNDC = float4(i.uv.x * 2 -1, i.uv.y * 2 -1, depthTex * 2 - 1, 1);
                float4 posVS = mul(_Matrix_IP, posNDC);
                posVS = posVS / posVS.w;


                //在观察空间,定义一个切线空间
                float3 tangentVS = RandomFloat3(i.uv);
                float3 binormalVS = normalize(cross(tangentVS, normalVS));
                tangentVS = cross(normalVS, binormalVS);
                float3x3 ViewSpaceToTangentSpace = {tangentVS, binormalVS, normalVS};
                float3x3 TangentSpaceToViewSpace = transpose(ViewSpaceToTangentSpace);


                int count = 0;  // 没被遮挡采样点数
                for(int k = 0; k < _SampleCount; k++)
                {
                    float3 randomVector = RandomFloat3(i.uv * (k+1) );                              //偏移量,像素的切线空间 ,注意要保证每次循环产生的向量不同(所以乘k)
                    randomVector.z =abs( randomVector.z ) * 0.8 +0.2;                             //切线空间,偏移量,分量范围: [-1, 1], [-1, 1], [0, 1]
                    randomVector = mul(TangentSpaceToViewSpace, randomVector);
                    randomVector *= _SampleRadius;
                    
                    float4 SamplerPointPosVS = posVS + float4(randomVector, 0); //采样点,相机空间
                    float4 SamplerPointPosCS = mul(_Matrix_P, SamplerPointPosVS);
                    float4 SamplerPointPosNDC = SamplerPointPosCS / SamplerPointPosCS.w;
                    float2 SamplerPointUV = (SamplerPointPosNDC.xy + 1) / 2;

                    float Depth = DecodeFloatRG(tex2D(_CameraDepthNormalsTexture, SamplerPointUV).zw);
                    float4 ndc = float4( SamplerPointUV * 2 -1, Depth * 2 - 1,  1);
                    float4 vs = mul(_Matrix_IP, ndc);
                    vs /= vs.w;

                    if( (-vs.z) - (-SamplerPointPosVS.z) > 0 || (-SamplerPointPosVS.z) - (-vs.z) > _SampleRadius )        // 场景深度图的深度  大于  采样点深度(未被遮挡)   或    采样点深度 大于 场景深度 很多(被遮挡,但是是错开的物体)
                    {
                        count++;
                    }
                }

                //float4 rowTex = tex2D(_MainTex, i.uv);

                fixed ao= float(count)/_SampleCount;
                return lerp( _AOColor, fixed4(1, 1, 1, 1), ao);//          (1-ao)*_AOColor + ao * fixed4(1, 1, 1, 1);    ao做出的遮罩 * ao颜色 + 非ao区域 * 白色
            }

            ENDCG
        }
    }
    FallBack "Diffuse"
}
//BilateralBlur    //模糊,但保持图像中的边缘信息

Shader "may/BilateralBlur"
{
    Properties
    {
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
    }
    SubShader
    {
        CGINCLUDE
            #include "UnityCG.cginc"
            sampler2D _MainTex;
            sampler2D _AoTex;
            sampler2D _CameraDepthNormalsTexture;   //深度法线 
            float4 _AoTex_TexelSize;

            float _UVOffset;              //uv偏移量, 0 不偏移, 1 偏移量为窗口的宽/高       5x5采样   
            float _BilaterFilterFactor;

            struct a2v
            {
                float4 vertex:POSITION;
                float2 uv:TEXCOORD;
            };
            struct v2f_blur
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD;
                half2 uvOffset:TEXCOORD1;
            };
            struct v2f_Add
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD;
            };
            v2f_blur vert_Horizontal(a2v v)
            {
                v2f_blur o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.uvOffset = half2(_UVOffset, 0);
                return o;
            }
            v2f_blur vert_Vertical(a2v v)
            {
                v2f_blur o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                o.uvOffset = half2(0, _UVOffset);
                return o;
            }

            float CompareNormal(float3 normal0, float3 normal1)
            {
                return smoothstep(_BilaterFilterFactor, 1.0, dot(normal0, normal1));
            }
            fixed4 frag_blur( v2f_blur i):SV_TARGET
            {
                half2 UVOffset = i.uvOffset;
                half2 uv0 = i.uv - 3 * UVOffset;
                half2 uv1 = i.uv - 2 * UVOffset;
                half2 uv2 = i.uv - 1 * UVOffset;
                half2 uv3 = i.uv;
                half2 uv4 = i.uv + 1 * UVOffset;
                half2 uv5 = i.uv + 2 * UVOffset;
                half2 uv6 = i.uv + 3 * UVOffset;
                
	            fixed4 color0 = tex2D(_MainTex, uv0);
	            fixed4 color1 = tex2D(_MainTex, uv1);
	            fixed4 color2 = tex2D(_MainTex, uv2);
	            fixed4 color3 = tex2D(_MainTex, uv3);
	            fixed4 color4 = tex2D(_MainTex, uv4);
	            fixed4 color5 = tex2D(_MainTex, uv5);
                fixed4 color6 = tex2D(_MainTex, uv6);

                float3 normal0 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv0));
                float3 normal1 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv1));
                float3 normal2 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv2));
                float3 normal3 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv3));
                float3 normal4 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv4));
                float3 normal5 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv5));
                float3 normal6 = DecodeViewNormalStereo(tex2D(_CameraDepthNormalsTexture, uv6));
                
                fixed weight0 = CompareNormal(normal3, normal0) * 0.11453744493;
                fixed weight1 = CompareNormal(normal3, normal1) * 0.19823788546;
                fixed weight2 = CompareNormal(normal3, normal2) * 0.31718061674;
                fixed weight3 = 0.37004405286;
                fixed weight4 = CompareNormal(normal3, normal4) * 0.31718061674;
                fixed weight5 = CompareNormal(normal3, normal5) * 0.19823788546;
                fixed weight6 = CompareNormal(normal3, normal6) * 0.11453744493;
                fixed weight = weight0 + weight1 + weight2 + weight3 + weight4 + weight5 + weight6;

                fixed4 blurColor = fixed4(0,0,0,0);
                blurColor += color0 * weight0;
                blurColor += color1 * weight1;
                blurColor += color2 * weight2;
                blurColor += color3 * weight3;
                blurColor += color4 * weight4;
                blurColor += color5 * weight5;
                blurColor += color6 * weight6;

               
                
                //return color5;
                return blurColor /weight;
            }

            v2f_Add vert_Add(a2v v)
            {
                v2f_Add o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            fixed4 frag_Add( v2f_Add i):SV_TARGET
            {
                fixed4 src = tex2D(_MainTex, i.uv);         //原图
                fixed4 bluredAO = tex2D(_AoTex, i.uv);      //模糊后的AO;
                return src * bluredAO;
            }
        ENDCG


        ZWrite Off ZTest Always Cull Off 
        pass 
        {
           CGPROGRAM
           #pragma vertex vert_Horizontal
           #pragma fragment frag_blur
           ENDCG
        }
        pass 
        {
           CGPROGRAM
           #pragma vertex vert_Vertical
           #pragma fragment frag_blur
           ENDCG
        }
        pass 
        {
           CGPROGRAM
           #pragma vertex vert_Add
           #pragma fragment frag_Add
           ENDCG
        }
    }
    FallBack "Diffuse"
}

SSAO,HBAO,GTAO

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值