URP之屏幕后处理 高度雾

之前实现了一个屏幕后处理高度雾,但这个是在Built-in管线下的。现在需要改成URP管线下,然后发现了改动量挺大的,原来的OnRenderImage、OnPreRender都失效了,所以记录一下。

具体代码如下:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;


[System.Serializable, VolumeComponentMenu("zxz/HeightFog")]
public class HeightFogVolume : VolumeComponent, IPostProcessComponent
{
    [Tooltip("雾强度")]
    public ClampedFloatParameter FogDensity = new ClampedFloatParameter(1.0f, 0.0f,5f);
    [Tooltip("雾的起始高度")]
    public FloatParameter FogStart = new FloatParameter(0f);
    [Tooltip("雾的终止高度")]
    public FloatParameter FogEnd = new FloatParameter(2.0f);
    [Tooltip("雾的颜色")]
    public ColorParameter FogColor = new ColorParameter(new Color(130 / 255f, 130 / 255f, 130 / 255f, 1.0f));

    [Tooltip("雾X方向流动速度")]
    public ClampedFloatParameter FogXSpeed = new ClampedFloatParameter(0.05f, -0.5f, 0.5f);
    [Tooltip("雾Z方向流动速度")]
    public ClampedFloatParameter FogZSpeed = new ClampedFloatParameter(0.05f, -0.5f, 0.5f);
    [Tooltip("雾噪声图权重")]
    public ClampedFloatParameter NoiseWeight = new ClampedFloatParameter(1.0f, 0.0f, 3.0f);
    [Tooltip("雾噪声图参数")]
    public ClampedFloatParameter NoiseAmount = new ClampedFloatParameter(1.0f, 0.0f, 30.0f);

    public bool IsActive() => true;

    public bool IsTileCompatible() => false;

}

下面是核心代码:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

public class HeightFogRenderFeature : ScriptableRendererFeature
{
    [System.Serializable]
    public class Settings
    {
        public RenderPassEvent renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
        public Shader shader;
        public Texture noise_tex;
    }
    public Settings settings = new Settings();    
    HeightFogPass pass;

    public override void Create()
    {
        this.name = "HeightFogPass";
        pass = new HeightFogPass(settings.renderPassEvent, settings.shader, settings.noise_tex);
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        pass.Setup(renderer.cameraColorTarget);
        renderer.EnqueuePass(pass);
    }
}

public class HeightFogPass : ScriptableRenderPass
{
    static readonly string k_RenderTag = "HeightFogPass Effects";

    static readonly int MainTexId = Shader.PropertyToID("_MainTex");
    static readonly int NoiseTexId = Shader.PropertyToID("_NoiseTex");
    static readonly int TempTargetId = Shader.PropertyToID("_TempTarget");
    static readonly int FogDensityId = Shader.PropertyToID("_FogDensity");
    static readonly int FogStartId = Shader.PropertyToID("_FogStart");
    static readonly int FogEndId = Shader.PropertyToID("_FogEnd");    
    static readonly int FogColorId = Shader.PropertyToID("_FogColor");
    static readonly int FogXSpeedId = Shader.PropertyToID("_FogXSpeed");
    static readonly int FogZSpeedId = Shader.PropertyToID("_FogYSpeed");
    static readonly int NoiseWeightId = Shader.PropertyToID("_NoiseWeight");
    static readonly int NoiseAmountId = Shader.PropertyToID("_NoiseAmount");

    HeightFogVolume volume;
    Material material;
    Texture noise_tex;
    RenderTargetIdentifier currentTarget;

    public HeightFogPass(RenderPassEvent evt, Shader shader, Texture noise)
    {
        renderPassEvent = evt;
        //var shader = Shader.Find("Universal Render Pipeline/Dejavu/HeightFog");
        if (shader == null)
        {
            Debug.LogError("Shader not found.");
            return;
        }
        material = CoreUtils.CreateEngineMaterial(shader);
        noise_tex = noise;
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        if (material == null)
        {
            Debug.LogError("Material not created.");
            return;
        }

        if (!renderingData.cameraData.postProcessEnabled) return;

        var stack = VolumeManager.instance.stack;
        volume = stack.GetComponent<HeightFogVolume>();
        if (volume == null) { return; }
        if (!volume.IsActive()) { return; }
        var cmd = CommandBufferPool.Get(k_RenderTag);
        Render(cmd, ref renderingData);
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }

    public void Setup(in RenderTargetIdentifier currentTarget)
    {
        this.currentTarget = currentTarget;
    }

    void Render(CommandBuffer cmd, ref RenderingData renderingData)
    {
        ref var cameraData = ref renderingData.cameraData;
        var source = currentTarget;
        int destination = TempTargetId;

        var w = cameraData.camera.scaledPixelWidth;
        var h = cameraData.camera.scaledPixelHeight;
        
        material.SetFloat(FogDensityId, volume.FogDensity.value);        
        material.SetFloat(FogStartId, volume.FogStart.value);
        material.SetFloat(FogEndId, volume.FogEnd.value);
        material.SetColor(FogColorId, volume.FogColor.value);
        material.SetFloat(FogXSpeedId, volume.FogXSpeed.value);
        material.SetFloat(FogZSpeedId, volume.FogZSpeed.value);
        material.SetFloat(NoiseWeightId, volume.NoiseWeight.value);
        material.SetFloat(NoiseAmountId, volume.NoiseAmount.value);
        material.SetTexture(NoiseTexId, noise_tex);

        int shaderPass = 0;
        cmd.SetGlobalTexture(MainTexId, source);
        cmd.GetTemporaryRT(destination, w, h, 0, FilterMode.Point, RenderTextureFormat.Default);
        cmd.Blit(source, destination);
        cmd.Blit(destination, source, material, shaderPass);
    }
}

后处理的HLSL下的Shader代码:


Shader "URP/zxz/HeightFog"
{
    Properties
    {
        _MainTex("Base (RGB)", 2D) = "white" {}           
    }

        HLSLINCLUDE
        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

        CBUFFER_START(UnityPerMaterial)
        float4 _MainTex_ST;
        float4 _NoiseTex_ST;       
        half _FogDensity;
        float _FogStart;
		float _FogEnd;
        half4 _FogColor;
        half _FogXSpeed;
        half _FogYSpeed;
        half _NoiseWeight;
        half _NoiseAmount;

        CBUFFER_END

        sampler2D _MainTex;
        sampler2D _NoiseTex;
        TEXTURE2D(_CameraDepthTexture);
        SAMPLER(sampler_CameraDepthTexture);


    struct appdata {
        float4 positionOS : POSITION;
        float2 uv : TEXCOORD0;
        UNITY_VERTEX_INPUT_INSTANCE_ID
    };

    struct v2f {
        float4 positionCS : SV_POSITION;
        float2 uv : TEXCOORD0;
        float3 viewRayWorld : TEXCOORD1;
        UNITY_VERTEX_OUTPUT_STEREO
    };

    v2f vert(appdata v)
    {
        v2f o;
        UNITY_SETUP_INSTANCE_ID(v);
        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
        o.positionCS = TransformObjectToHClip(v.positionOS.xyz);

        float sceneRawDepth = 1;
#if defined(UNITY_REVERSED_Z)
        sceneRawDepth = 1 - sceneRawDepth;
#endif
        float3 worldPos = ComputeWorldSpacePosition(v.uv, sceneRawDepth, UNITY_MATRIX_I_VP);
        o.viewRayWorld = worldPos - _WorldSpaceCameraPos.xyz;
        o.uv = v.uv;
        return o;
    }
   
    float4 frag(v2f i) : SV_Target
    {
        float sceneRawDepth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, sampler_CameraDepthTexture, i.uv);
        float linear01Depth = Linear01Depth(sceneRawDepth, _ZBufferParams);
        float3 worldPos = _WorldSpaceCameraPos.xyz + ( linear01Depth) * i.viewRayWorld;

        float2 speed = _Time.y * float2(_FogXSpeed, _FogYSpeed);				
        float noise = (tex2D(_NoiseTex, worldPos.xz / _NoiseAmount + speed).r - 0.5) * _NoiseWeight;                    
        float fogDensity = (_FogEnd - worldPos.y) / (_FogEnd - _FogStart); 
        fogDensity = saturate(fogDensity * _FogDensity * (1 + noise));        
        half4 finalColor = tex2D(_MainTex, i.uv);
        //half4 finalColor = tex2D(_NoiseTex, i.uv);
        finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);
        return finalColor;
    }



        ENDHLSL
        
        SubShader
    {
        //Tags {"RenderType" = "Opaque"  "RenderPipeline" = "UniversalPipeline"}
        Tags{ "RenderPipeline" = "UniversalPipeline"  "RenderType" = "Overlay" "Queue" = "Transparent-499" "DisableBatching" = "True" }
            LOD 100
            ZTest Always Cull Off ZWrite Off
            Blend one zero
            Pass
        {
             Name "HeightFog"
             
             HLSLPROGRAM
              #pragma vertex vert
             #pragma fragment frag
             ENDHLSL
        }

    }    
}

坑:

在这里插入图片描述
创建Demo项目时,用的是3D URP模板。结果配置好后发现没效果。折腾了一天!!!!!!!!!下班了才发现是用下面的模板就可以了。最后第二天发现问题所在:
在这里插入图片描述
如上图,需要选取Always选项。

参考文章:https://blog.csdn.net/yinfourever/article/details/121047957

github:https://github.com/982464509/URP-PostProcessingFog.git

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值