Unity urp 自定义后处理bloom

本文详细描述了如何在Unity中创建一个自定义的Unlit/CustomBloom着色器,包括其属性设置、SubShader部分的结构以及与PostProcessComponent和ScriptableRendererFeature的集成,展示了如何实现模糊效果和后期处理功能。
摘要由CSDN通过智能技术生成

直接上代码

shander
Shader "Unlit/CustomBloom"
{
    Properties
    {
        _MainTex ("MainTex", 2D) = "white" {}
        _Bloom("Bloom", 2D) = "white" {}
        _Size("Size",Range(1,10)) = 1
        _Threshold("Threshold",Range(0,1)) = 0
    }
    SubShader
    {
        HLSLINCLUDE

        #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
        struct appdata
        {
            float4 vertex : POSITION;
            float2 uv : TEXCOORD0;
        };

        struct v2f_bloom
        {
            float2 uv : TEXCOORD0;
            float4 vertex : SV_POSITION;
        };
        
        struct v2f
        {
            float2 uv[5] : TEXCOORD0;
            float4 vertex : SV_POSITION;
        };
        TEXTURE2D(_MainTex);
        SAMPLER(sampler_MainTex);
        half4 _MainTex_TexelSize;
        half4 _MainTex_ST;

        TEXTURE2D(_BloomTex);
        SAMPLER(sampler_BloomTex);
        half4 _BloomTex_TexelSize;
        half4 _BloomTex_ST;

        float _Size;
        float _Threshold;

        v2f vertH (appdata v)
        {
            v2f o;
            o.vertex = TransformObjectToHClip(v.vertex);
            float2 uv = v.uv;
            o.uv[0] = uv; 
            o.uv[1] = uv + float2(_MainTex_TexelSize.x,0) * _Size;
            o.uv[2] = uv - float2(_MainTex_TexelSize.x,0) * _Size;
            o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2,0) * _Size; 
            o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2,0) * _Size; 

            return o;
        }

        v2f vertV (appdata v)
        {
            v2f o;
            o.vertex = TransformObjectToHClip(v.vertex);
            float2 uv = v.uv;
            o.uv[0] = uv; 
            o.uv[1] = uv + float2(_MainTex_TexelSize.y,0) * _Size;
            o.uv[2] = uv - float2(_MainTex_TexelSize.y,0) * _Size;
            o.uv[3] = uv + float2(_MainTex_TexelSize.y * 2,0) * _Size; 
            o.uv[4] = uv - float2(_MainTex_TexelSize.y * 2,0) * _Size; 

            return o;
        }

        float4 frag (v2f i) : SV_Target
        {
            float weight[3] = {0.4026,0.2442,0.0545};
            float4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv[0]) * weight[0];
            for (int j = 1;j < 3;j++)
            {
                col += SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv[2 * j - 1]) * weight[j];
                col += SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv[2 * j]) * weight[j];
            }
            return col;
        }

        v2f_bloom vert_bloom (appdata v)
        {
            v2f_bloom o;
            o.vertex = TransformObjectToHClip(v.vertex);
            o.uv = TRANSFORM_TEX(v.uv,_BloomTex);
            return o;
        }

        float4 fragBloom(v2f_bloom i) : SV_Target
        {
            float4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv);
            float b = 0.2125 * col.r + 0.7154 * col.g + 0.0721 * col.b;
            b = clamp(b - _Threshold,0,1);
            return col * b;
        }

        float4 fragFinal(v2f_bloom i) : SV_Target
        {
            float4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex,i.uv) + SAMPLE_TEXTURE2D(_BloomTex,sampler_BloomTex,i.uv);
            return col;
        }
        ENDHLSL
        Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline"}
        Cull Off ZWrite Off ZTest Always
        LOD 100
        
        Pass
        {
            name "passBloom"
            HLSLPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment fragBloom
            ENDHLSL
        }
        
        Pass
        {
            name "passh"
            HLSLPROGRAM
            #pragma vertex vertH
            #pragma fragment frag
            ENDHLSL
        }
        
        Pass
        {
            name "passv"
            HLSLPROGRAM
            #pragma vertex vertV
            #pragma fragment frag
            ENDHLSL
        }
        
        Pass
        {
            name "passFinal"
            HLSLPROGRAM
            #pragma vertex vert_bloom
            #pragma fragment fragFinal
            ENDHLSL
        }
    }
}

配置参数
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

namespace UnityEngine.Rendering.Universal
{
    public static class CustomBloomShaderName
    {
        public const string _Size = "_Size";
        public const string _Threshold = "_Threshold";
        public const string _MainTex = "_MainTex";
        public const string _BloomTex = "_Bloom";
    }

    public class CustomBloomVolme : VolumeComponent, IPostProcessComponent
    {
        public FloatParameter size = new FloatParameter(0);
        public FloatParameter threshold = new FloatParameter(0.5f);
        public IntParameter sampleCount = new IntParameter(1);
        public IntParameter downSample = new IntParameter(2);

        public bool IsActive()
        {
            return size.value > 0;
        }

        public bool IsTileCompatible()
        {
            return false;
        }
    }
}
实现方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using FogMode = UnityEngine.Rendering.Universal.FogMode;

public class CustomBloomFeature : ScriptableRendererFeature
{
    class CustomBloomPass : ScriptableRenderPass
    {
        private RTHandle source;
        private RTHandle tempTargetHandle;
        private RTHandle tempTargetHandle1;
        public Material bloomMaterial;
        private int sizeId = Shader.PropertyToID(CustomBloomShaderName._Size);
        private int thresholdId = Shader.PropertyToID(CustomBloomShaderName._Threshold);
        private int mainTexId = Shader.PropertyToID(CustomBloomShaderName._MainTex);
        private int bloomTexId = Shader.PropertyToID(CustomBloomShaderName._BloomTex);
        int tempbloom = Shader.PropertyToID("tempbloom");
        int tempbloom1 = Shader.PropertyToID("tempbloom1");
        public CustomBloomPass()
        {
            tempTargetHandle = RTHandles.Alloc(tempbloom, name: "tempbloom");
            tempTargetHandle1 = RTHandles.Alloc(tempbloom1, name: "tempbloom1");
        }

        public void Setup(RTHandle source,Material bloomMaterial)
        {
            this.source = source;
            this.bloomMaterial = bloomMaterial;
            this.renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            CustomBloomVolme customBloomVolme = VolumeManager.instance.stack.GetComponent<CustomBloomVolme>();
            if (customBloomVolme.IsActive())
            {
                CommandBuffer cmd = CommandBufferPool.Get("CustomBloomPassCmd");
                var desc = renderingData.cameraData.cameraTargetDescriptor;
                desc.msaaSamples = 1;
                desc.depthBufferBits = 0;
                desc.width = desc.width / customBloomVolme.downSample.value;
                desc.height = desc.height / customBloomVolme.downSample.value;

                RenderingUtils.ReAllocateIfNeeded(ref tempTargetHandle, desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: tempTargetHandle.name);
                RenderingUtils.ReAllocateIfNeeded(ref tempTargetHandle1, desc, FilterMode.Bilinear, TextureWrapMode.Clamp, name: tempTargetHandle1.name);

                bloomMaterial.SetFloat(sizeId,customBloomVolme.size.value);
                bloomMaterial.SetFloat(thresholdId,customBloomVolme.threshold.value);
                
                cmd.Blit(source,tempTargetHandle,bloomMaterial,0);
                
                var lastDown = tempTargetHandle;
                for (int i = 0; i < customBloomVolme.sampleCount.value; i++)
                {
                    cmd.Blit(lastDown,tempTargetHandle1,bloomMaterial,1);
                    lastDown = tempTargetHandle1;
                    cmd.Blit(lastDown,tempTargetHandle,bloomMaterial,2);
                    lastDown = tempTargetHandle;
                }
                
                cmd.SetGlobalTexture(bloomTexId,lastDown);
                cmd.Blit(source,tempTargetHandle1,bloomMaterial,3);
                cmd.Blit(tempTargetHandle1,source);
                //cmd.Blit(tempTargetHandle1,source);
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
                //RTHandles.Release(tempTargetHandle);
                //RTHandles.Release(tempTargetHandle1);
            }
        }
    }
    
    private CustomBloomPass customBloomPass;
    public Material bloomMaterial;
    public override void Create()
    {
        customBloomPass = new CustomBloomPass();
    }

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

    public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    {
        customBloomPass.Setup(renderer.cameraColorTargetHandle,bloomMaterial);
    }
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值