URP下快速实现高度雾

高度雾的实现思路非常简单,通过深度图还原出来的世界坐标的y值来做fog的lerp参数。

代码使用之前的体积光代码的基础上做了个加法,方便快速使用。

代码如下:

Shader "Unlit/VolumetricLightingShader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Intensity("Intensity",float) = 1
        _FogColor("Fog Color",Color) = (1,1,1,1)
        _FogHeight("Fog Height",float) = 1
            _HeightPower("Fog Height Power",float) = 1
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define MAIN_LIGHT_CALCULATE_SHADOWS
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
            #define STEP_TIME 64
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 worldPos:TEXCOORD1;
                float4 screenPos :TEXCOORD2;
            };

            TEXTURE2D_X_FLOAT(_CameraDepthTexture); SAMPLER(sampler_CameraDepthTexture);
            TEXTURE2D(_CameraOpaqueTexture); SAMPLER(sampler_CameraOpaqueTexture);
            TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
            float _Intensity;
            half4 _FogColor;
            float _FogHeight;
            float _HeightPower;
            v2f vert (appdata v)
            {
                v2f o;
                
                o.vertex = TransformObjectToHClip(v.vertex);
                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
                o.screenPos = ComputeScreenPos(o.vertex);
                return o;
            }

            half4 frag (v2f i) : SV_Target
            {
                half2 screenPos = i.screenPos.xy / i.screenPos.w;
                //rebuild world position according to depth
                float depth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture,sampler_CameraDepthTexture, screenPos).r;
                depth = Linear01Depth(depth, _ZBufferParams);
                float2 positionNDC = screenPos * 2 - 1;
                float3 farPosNDC = float3(positionNDC.xy,1)*_ProjectionParams.z;
                float4 viewPos = mul(unity_CameraInvProjection,farPosNDC.xyzz);
                viewPos.xyz *= depth;
                float4 worldPos = mul(UNITY_MATRIX_I_V,viewPos);
                
                float noise = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, screenPos*3).r;
                float3 startPos = i.worldPos;
                float3 dir = normalize(worldPos - startPos);
                startPos += dir * noise;
                worldPos.xyz += dir * noise;
                float len = length(worldPos - startPos);
                float3 stepLen = dir * len / STEP_TIME;
                half3 color = 0;

                half3 sceneColor = SAMPLE_TEXTURE2D(_CameraOpaqueTexture, sampler_CameraOpaqueTexture, screenPos).rgb;
                
                UNITY_LOOP
                for (int i = 0; i < STEP_TIME; i++)
                {
                    startPos += stepLen;
                    float4 shadowPos = TransformWorldToShadowCoord(startPos);
                    float intensity = MainLightRealtimeShadow(shadowPos)*_Intensity;
                    color += intensity*_MainLightColor.rgb;
                }
                
                color /= STEP_TIME;
                color += sceneColor;

                float heightOffset = pow(max((_FogHeight - worldPos.y)/_FogHeight,0), _HeightPower);
                color += heightOffset * _FogColor;
                return half4(color.xyz,1);
            }
            ENDHLSL
        }
    }
}

使用方法还是像之前一样在摄像机前面放一个片,快速的查看效果。

效果如下:

 

 我们能看到天空已经曝的不成样子,通过tonemapping(aces)来解决。最后是这样子:

 

 非常的有意境~哈哈哈哈,程序员觉得好看的美术可能看起来是一坨粑粑。

posted @ 2021-03-08 19:38  syb7384  阅读(1876)  评论(0编辑  收藏  举报