Untiy URP RenderFeature 屏幕水滴效果

Untiy URP RenderFeature 屏幕水滴效果

在这里插入图片描述

这一方法参考自连接里的“粒子”方法。
思路是将粒子结果绘制进一张RT中,在屏幕上去采样这张RT作为dir扰动信息扰动屏幕画面。(粒子贴一张圆形法线图)


public class RainDrop : ScriptableRendererFeature
{
    [Serializable]
    public class Setting
    {
        public Material material;
        public float _normalIntensity;
        [Range(0,4)]public float downSample;
    }

    public bool enable = false;
    public Setting setting = new Setting();
    public RainPass rainPass;

    public override void Create()
    {
     rainPass = new RainPass();
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        if(!enable ) return;
        rainPass.SetUp(setting, renderer.cameraColorTarget);
        renderer.EnqueuePass(rainPass);
    }
}

public class RainPass : ScriptableRenderPass
{
    public RainDrop.Setting setting;
    //传递进来的屏幕ColorRT
    public RenderTargetIdentifier colRT;
    //绘制particle的pass名称
    ShaderTagId PtagId = new ShaderTagId("ParticleNormalMap");
    //particle的ColorRT
    private RenderTexture ParticleRt;

    public RainPass()
    {
    	//绘制事件在后效之前
        renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
    }
    //过滤设置: 半透明队列里的effect层
    FilteringSettings _filteringSettings = new FilteringSettings(RenderQueueRange.transparent, layerMask:LayerMask.GetMask("Effect"));
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        var material = setting.material;
        if (material == null || material.shader == null || !material.shader.isSupported)  return;
        //屏幕雨滴buffer
        CommandBuffer cmd = CommandBufferPool.Get("ScreenRain");
        cmd.Clear();
        //绘制设置: pass, renderingData, 半透明类,
        DrawingSettings drawingSettings =
            CreateDrawingSettings(PtagId, ref renderingData, SortingCriteria.CommonTransparent);
        //根据调用,绘制设置,过滤设置 ref是为了在不同状态更新时复用drawRenderer
        context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _filteringSettings);
        //设置绘制的贴图给全局变量 用以后面作为扰动源
        Shader.SetGlobalTexture("_ParticleNormalTex", ParticleRt);
        
        //屏幕画面
        var descriptor = renderingData.cameraData.cameraTargetDescriptor;
        descriptor.msaaSamples = 1;
        descriptor.depthBufferBits = 0;
        var texId = Shader.PropertyToID("_ScreenRain");
        cmd.GetTemporaryRT(texId, descriptor);
        material.SetFloat("_NormalIntensity", setting._normalIntensity);
        //把shader 0 pass内容根据传递进来的屏幕colorRT绘制到我们的_ScreenRain图上
        cmd.Blit(colRT, texId, material, 0);
        //将_ScreenRain图复制回屏幕colorRT,这一步是因为我们不能边读边写屏幕colorRT
        cmd.Blit(texId, colRT);
		//释放我们的临时RT
        cmd.ReleaseTemporaryRT(texId);
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }

    public void SetUp(RainDrop.Setting setting, RenderTargetIdentifier rendererCameraColorTarget)
    {
        this.setting = setting;
        //传递屏幕colorRT进Pass里
        colRT = rendererCameraColorTarget;
    }

    public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
    {
        if (!ParticleRt)
        {
        	//粒子colorRT 做降采样
            ParticleRt = new RenderTexture(512>>(int)setting.downSample, 512 >> (int)setting.downSample, 0);
            ParticleRt.Create();
            ParticleRt.name = "_ParticalRTNormal";
        }
        //绘制目标
        ConfigureTarget(ParticleRt);
        //绘制外内容设置为灰,我们为了过滤精度问题将a通道设置为0在pass中使用
        ConfigureClear(ClearFlag.All, new Color(0.5f,0.5f,0.5f,0f));
    }
}
Shader //TODO
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _NormalIntensity("NormalIntensity",Float) = 1
    }
    SubShader
    {
        Pass
        {
            name "Forward"
            Tags
            {
                "LightMode" = "ScreenRain" 
            }
            ZWrite off
            ZTest Always
 
            half4 frag(Varyings input) : SV_Target
            {
                // sample the texture
                //normaltex是一张非sRGB的2d线性图
                half4 normalVector = tex2D(_ParticleNormalTex, input.uv);
                //手动unpack
                float3 normalDir = normalVector * 2 - 1;
                //乘以我们涂白部分就是只有白色部分会影响屏幕
                normalDir.xy *= _NormalIntensity * normalVector.a;
                //扰动屏幕画面
                float2 uv = input.uv + normalDir.xy;
                half4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, uv);
                
                return half4(col.rgb, 1);
            }
            ENDHLSL
        }
        
        Pass{
            name "particle normal map"
            Tags
            {
                "LightMode" = "ParticleNormalMap"
            }
			Blend One One
			ColorMask RGBA
	        Cull Off Lighting Off ZWrite Off

            half4 frag(Varyings input) : SV_Target
            {
                // sample the texture
                half4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, input.uv);
                col.a = 1;//因为RenderFeature中我们将绘制信息外涂黑为0,所以有内容部分涂白为1
                return col;
            }
            ENDHLSL
            }
    }
}

大功告成,接下来就是看粒子效果怎么调整像水滴了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值