Unity Shader学习:SSAO屏幕环境光遮蔽

Unity Shader学习:SSAO屏幕环境光遮蔽

主要思路:1.随机采样像素法线半球周围的像素,平均对比与该像素深度是否处在暗处。2.双边滤波去噪点。3.后期AO图与原图混合。

原文链接:https://blog.csdn.net/puppet_master/article/details/82929708

Unity Shader学习:SSAO屏幕环境光遮蔽_第1张图片
无AO

Unity Shader学习:SSAO屏幕环境光遮蔽_第2张图片
有AO

Unity Shader学习:SSAO屏幕环境光遮蔽_第3张图片
AO图

c#部分:

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

public class SSAO : MonoBehaviour {

    public Material SSAOMaterial;
    private List<Vector4> sampleKernelList = new List<Vector4>();
    [Range(0f, 0.002f)]
    public float depthBiasValue = 0f;
    [Range(0.01f, 1f)]
    public float sampleKernelRadius = 1.0f;
    [Range(4,32)]
    public int sampleKernelCount = 16;
    [Range(0.0f, 5.0f)]
    public float AOStrength = 1.0f;
    [Range(0, 2)]
    public int downSample = 0;
    [Range(1, 4)]
    public int blurRadius = 1;
    [Range(0f, 0.2f)]
    public float bilateralFilterStrength = 0.2f;

    public bool onlyShowAO = false;

    public enum SSAOPassName
    {
        GenerateAO=0,
        BilateralFilter=1,
        Composite=2
    }

    private Camera currentCamera;

    void Start () {
        currentCamera = Camera.main;
        currentCamera.depthTextureMode = DepthTextureMode.DepthNormals;
	}

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        //采样点生成
        GenerateAOSampleKernel();

        RenderTexture aoRT = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0);

        SSAOMaterial.SetMatrix("_InverseProjectionMatrix", currentCamera.projectionMatrix.inverse);
        SSAOMaterial.SetFloat("_DepthBiasValue", depthBiasValue);
        SSAOMaterial.SetVectorArray("_SampleKernelArray", sampleKernelList.ToArray());
        SSAOMaterial.SetFloat("_SampleKernelCount", sampleKernelList.Count);
        SSAOMaterial.SetFloat("_AOStrength", AOStrength);
        SSAOMaterial.SetFloat("_SampleKernelRadius", sampleKernelRadius);
        Graphics.Blit(source, aoRT, SSAOMaterial, (int)SSAOPassName.GenerateAO);

        RenderTexture blurRT = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0);

        SSAOMaterial.SetFloat("_BilaterFilterFactor", 1.0f - bilateralFilterStrength);
        SSAOMaterial.SetVector("_BlurRadius", new Vector4(blurRadius, 0, 0, 0));
        Graphics.Blit(aoRT, blurRT, SSAOMaterial, (int)SSAOPassName.BilateralFilter);

        SSAOMaterial.SetVector("_BlurRadius", new Vector4(0, blurRadius, 0, 0));

        if (onlyShowAO)
        {
            Graphics.Blit(blurRT, destination, SSAOMaterial, (int)SSAOPassName.BilateralFilter);
        }
        else
        {
            Graphics.Blit(blurRT, aoRT, SSAOMaterial, (int)SSAOPassName.BilateralFilter);
            SSAOMaterial.SetTexture("_AOTex", aoRT);
            Graphics.Blit(source, destination, SSAOMaterial, (int)SSAOPassName.Composite);
        }
        RenderTexture.ReleaseTemporary(aoRT);
        RenderTexture.ReleaseTemporary(blurRT);
    }

    private void GenerateAOSampleKernel()
    {
        if (sampleKernelCount==sampleKernelList.Count)
        {
            return;
        }
        sampleKernelList.Clear();
        for (int i = 0; i < sampleKernelCount; i++)
        {
            Vector4 vec = new Vector4(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f), 1f);
            vec.Normalize();
            float scale = ((float)i) / sampleKernelCount;
            //调整分布的曲线
            scale = Mathf.Lerp(0.01f, 1.0f, scale * scale);
            vec *= scale;
            sampleKernelList.Add(vec);
        }
    }
}

shader部分:

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

public class SSAO : MonoBehaviour {

    public Material SSAOMaterial;
    private List<Vector4> sampleKernelList = new List<Vector4>();
    [Range(0f, 0.002f)]
    public float depthBiasValue = 0f;
    [Range(0.01f, 1f)]
    public float sampleKernelRadius = 1.0f;
    [Range(4,32)]
    public int sampleKernelCount = 16;
    [Range(0.0f, 5.0f)]
    public float AOStrength = 1.0f;
    [Range(0, 2)]
    public int downSample = 0;
    [Range(1, 4)]
    public int blurRadius = 1;
    [Range(0f, 0.2f)]
    public float bilateralFilterStrength = 0.2f;

    public bool onlyShowAO = false;

    public enum SSAOPassName
    {
        GenerateAO=0,
        BilateralFilter=1,
        Composite=2
    }

    private Camera currentCamera;

    void Start () {
        currentCamera = Camera.main;
        currentCamera.depthTextureMode = DepthTextureMode.DepthNormals;
	}

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        //采样点生成
        GenerateAOSampleKernel();

        RenderTexture aoRT = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0);

        SSAOMaterial.SetMatrix("_InverseProjectionMatrix", currentCamera.projectionMatrix.inverse);
        SSAOMaterial.SetFloat("_DepthBiasValue", depthBiasValue);
        SSAOMaterial.SetVectorArray("_SampleKernelArray", sampleKernelList.ToArray());
        SSAOMaterial.SetFloat("_SampleKernelCount", sampleKernelList.Count);
        SSAOMaterial.SetFloat("_AOStrength", AOStrength);
        SSAOMaterial.SetFloat("_SampleKernelRadius", sampleKernelRadius);
        Graphics.Blit(source, aoRT, SSAOMaterial, (int)SSAOPassName.GenerateAO);

        RenderTexture blurRT = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0);

        SSAOMaterial.SetFloat("_BilaterFilterFactor", 1.0f - bilateralFilterStrength);
        SSAOMaterial.SetVector("_BlurRadius", new Vector4(blurRadius, 0, 0, 0));
        Graphics.Blit(aoRT, blurRT, SSAOMaterial, (int)SSAOPassName.BilateralFilter);

        SSAOMaterial.SetVector("_BlurRadius", new Vector4(0, blurRadius, 0, 0));

        if (onlyShowAO)
        {
            Graphics.Blit(blurRT, destination, SSAOMaterial, (int)SSAOPassName.BilateralFilter);
        }
        else
        {
            Graphics.Blit(blurRT, aoRT, SSAOMaterial, (int)SSAOPassName.BilateralFilter);
            SSAOMaterial.SetTexture("_AOTex", aoRT);
            Graphics.Blit(source, destination, SSAOMaterial, (int)SSAOPassName.Composite);
        }
        RenderTexture.ReleaseTemporary(aoRT);
        RenderTexture.ReleaseTemporary(blurRT);
    }

    private void GenerateAOSampleKernel()
    {
        if (sampleKernelCount==sampleKernelList.Count)
        {
            return;
        }
        sampleKernelList.Clear();
        for (int i = 0; i < sampleKernelCount; i++)
        {
            Vector4 vec = new Vector4(Random.Range(-1f, 1f), Random.Range(-1f, 1f), Random.Range(-1f, 1f), 1f);
            vec.Normalize();
            float scale = ((float)i) / sampleKernelCount;
            //调整分布的曲线
            scale = Mathf.Lerp(0.01f, 1.0f, scale * scale);
            vec *= scale;
            sampleKernelList.Add(vec);
        }
    }
}

你可能感兴趣的:(Unity,Shader)