Unity3D Shader:景深

C#代码:

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

public class JingShen : MonoBehaviour {

    public Material mat;

    [Range(0f, 100f)]
    public float focalDistance = 10;//焦点距离

    [Range(0, 100)]
    public float nearBlurScale = 0;//近距离模糊缩放

    [Range(0,1000f)]
    public float farBlurScale = 50;//远距离模糊缩放

    public int downSample = 1;//分辨率降低值

    public int sampleScale = 1;//采样半径


    private void OnEnable()
    {
        GetComponent<Camera>().depthTextureMode |= DepthTextureMode.Depth;//开启深度
    }
    private void OnDisable()
    {
        GetComponent<Camera>().depthTextureMode &= ~DepthTextureMode.Depth;//关闭深度
    }
    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Mathf.Clamp(focalDistance, transform.GetComponent<Camera>().nearClipPlane, transform.GetComponent<Camera>().farClipPlane);//限制焦点距离在摄像机最近裁剪面和最远裁剪面
        RenderTexture temp1 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);//降低分辨率
        RenderTexture temp2 = RenderTexture.GetTemporary(source.width >> downSample, source.height >> downSample, 0, source.format);
        Graphics.Blit(source, temp1);

        mat.SetVector("_offset", new Vector4(0, sampleScale, 0, 0));//垂直取值
        Graphics.Blit(temp1, temp2, mat,0);
        mat.SetVector("_offset", new Vector4(sampleScale, 0, 0, 0));//水平取值
        Graphics.Blit(temp2, temp1, mat,0);

        mat.SetTexture("_BlurTex", temp1);
        mat.SetFloat("_focalDistance", FocalDistance(focalDistance));
        mat.SetFloat("_nearBlurScale", nearBlurScale);
        mat.SetFloat("_farBlurScale", farBlurScale);

        Graphics.Blit(source, destination, mat, 1);

        RenderTexture.ReleaseTemporary(temp1);
        RenderTexture.ReleaseTemporary(temp2);
    }
    float FocalDistance(float distance)
    {
        //深度转换,把世界空间的深度先转换成摄像机空间的深度,再把摄像机的z值转换成0至1的范围值
        return transform.GetComponent<Camera>().WorldToViewportPoint((distance - transform.GetComponent<Camera>().nearClipPlane) * transform.forward + transform.position).z / (transform.GetComponent<Camera>().farClipPlane - transform.GetComponent<Camera>().nearClipPlane);
    }
}

shader代码:

Shader "Unlit/Test"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _BlurTex("BlurTex",2D)="white"{}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100
        Pass
        {
            //高斯模糊
            ZTest Off
            cull Off
            ZWrite Off
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct appdata{
                float4 vertex:POSITION;
                float2 uv:TEXCOORD0;
            };

            struct v2f
            {
                float4 pos:SV_POSITION;
                float2 uv:TEXCOORD0;
                float4 uv01:TEXCOORD1;
                float4 uv23:TEXCOORD2;
                float4 uv45:TEXCOORD3;
            };
            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            float4 _offset;

            v2f vert(appdata v)
            {
                v2f o;
                _offset*=_MainTex_TexelSize.xyxy;
                o.pos=UnityObjectToClipPos(v.vertex);
                o.uv=v.vertex.xy;
                o.uv01=v.vertex.xyxy+_offset.xyxy*float4(1,1,-1,-1);
                o.uv23=v.vertex.xyxy+_offset.xyxy*float4(1,1,-1,-1)*2;
                o.uv45=v.vertex.xyxy+_offset.xyxy*float4(1,1,-1,-1)*3;
                return o;
            }
            fixed4 frag(v2f i):SV_Target
            {
                fixed4 col=0.4*tex2D(_MainTex,i.uv);
                col+=0.15*tex2D(_MainTex,i.uv01.xy);
                col+=0.15*tex2D(_MainTex,i.uv01.zw);
                col+=0.10*tex2D(_MainTex,i.uv23.xy);
                col+=0.10*tex2D(_MainTex,i.uv23.zw);
                col+=0.05*tex2D(_MainTex,i.uv45.xy);
                col+=0.05*tex2D(_MainTex,i.uv45.zw);
                return col;
            }
            ENDCG
        }
        Pass
        {
            //景深
            ZTest Off
            Cull Off
            ZWrite Off
            ColorMask RGBA
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

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

            sampler2D _MainTex;
            float4 _MainTex_TexelSize;
            sampler2D _CameraDepthTexture;
            sampler2D _BlurTex;
            float _focalDistance;
            float _nearBlurScale;
            float _farBlurScale;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.vertex.xy;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                // sample the texture
                fixed4 col = tex2D(_MainTex, i.uv);

                fixed4 blur=tex2D(_BlurTex,i.uv);

                float depth=SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.uv);
                depth=Linear01Depth(depth);

                float focalTest=clamp(sign(depth-_focalDistance),0,1);
                fixed4 final=(1-focalTest)*col+focalTest*lerp(col,blur,clamp((depth-_focalDistance)*_farBlurScale,0,1));
                final=(focalTest)*final+(1-focalTest)*lerp(col,blur,clamp((_focalDistance-depth)*_nearBlurScale,0,1));
                return final;
            }
            ENDCG
        }
    }
}


猜你喜欢

转载自blog.csdn.net/weixin_42452001/article/details/81233395