Unity shader学习之屏幕后期处理效果之高度雾,重建world pos方法1

要想通过屏幕后期处理效果实现高度雾,就得知道屏幕中每个像素在世界空间中的坐标。

其中一种方法是:

打开深度纹理,通过uv坐标和深度计算出屏幕中每个像素在NDC中的坐标,再通过世界坐标到投影空间的转换矩阵的逆矩阵来变换,即可得到其在世界空间中的坐标。

但此种方法需要在 fragment shader 中进行矩阵乘法计算,而这通常会影响游戏性能。

转载请注明出处:https://www.cnblogs.com/jietian331/p/9441440.html

c#代码:

基类

using UnityEngine;

[RequireComponent(typeof(Camera))]
public abstract class PostEffectRenderer : GameBehaviour
{
    [SerializeField]
    Material m_material;

    Camera m_camera;


    protected abstract string ShaderName { get; }

    protected Material Mat
    {
        get
        {
            if (!m_material)
            {
                Shader shader = Shader.Find(ShaderName);
                if (shader != null && shader.isSupported)
                    m_material = new Material(shader);
                else
                    NotSupport();
            }
            return m_material;
        }
    }

    protected Camera SelfCamera
    {
        get
        {
            if (!m_camera)
                m_camera = GetComponent<Camera>();
            return m_camera;
        }
    }


    void Start()
    {
        if (!SystemInfo.supportsImageEffects)
            NotSupport();
    }

    protected virtual void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        Graphics.Blit(src, dest, Mat);
    }

    protected void NotSupport()
    {
        Debug.LogError(string.Format("{0} not support!", this.GetType().Name));
        enabled = false;
    }

}
View Code

子类

using UnityEngine;

public class HighFog : PostEffectRenderer
{
    protected override string ShaderName
    {
        get { return "Custom/Study/High Fog"; }
    }

    void OnEnable()
    {
        base.SelfCamera.depthTextureMode = DepthTextureMode.Depth;
    }

    void OnDisable()
    {
        base.SelfCamera.depthTextureMode = DepthTextureMode.None;
    }

    protected override void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        var projMatrix = GL.GetGPUProjectionMatrix(base.SelfCamera.projectionMatrix, false);
        var m = projMatrix * base.SelfCamera.worldToCameraMatrix;
        base.Mat.SetMatrix("_ViewportToWorldMatrix", m.inverse);
        base.OnRenderImage(src, dest);
    }
}
View Code

shader

Shader "Custom/Study/High Fog"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _FogColor ("Color", Color) = (1, 1, 1, 1)
        _FogPosY ("Fog pos y", float) = 0.1
        _FogDisappearHeight ("Fog disappear height", float) = 10
    }

    SubShader
    {
        Pass
        {
            ZTest Always
            ZWrite Off
            Cull Off

            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;
            sampler2D _CameraDepthTexture;
            uniform float4x4 _ViewportToWorldMatrix;
            float4 _FogColor;
            float _FogPosY;
            float _FogDisappearHeight;

            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
            
            fixed4 frag (v2f i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                
                float d = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv);
                float4 H = float4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, d, 1);
                float4 D = mul(_ViewportToWorldMatrix, H);
                float4 worldPos = D / D.w;

                float fogWeight;
                if(worldPos.y < _FogPosY)
                {
                    fogWeight = 1;
                }
                else if(worldPos.y > _FogPosY + _FogDisappearHeight)
                {
                    fogWeight = 0;
                }
                else
                {
                    fogWeight = 1 - (worldPos.y - _FogPosY) / _FogDisappearHeight;
                }

                return lerp(col, _FogColor, fogWeight);
            }

            ENDCG
        }
    }

    Fallback Off
}
View Code

效果如下图:

猜你喜欢

转载自www.cnblogs.com/jietian331/p/9441440.html
今日推荐