ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

URP管线中自定义Bloom

2021-11-19 22:00:52  阅读:463  来源: 互联网

标签:自定义 buffer screenUV private int URP pragma float4 Bloom


非HDR开启bloom的效果
主要是URP作者的教程
工程源码在我的git中:我的git工程网址
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;

partial class PostFXStack
{
    private const string bufferName = "Post FX";
    CommandBuffer buffer = new CommandBuffer()
    {
        name = bufferName
    };

    private ScriptableRenderContext context;
    private Camera camera;
    private PostFXSettings settings;

    private int fxSourceId = Shader.PropertyToID("_PostFXSource");
    private int fxSource2Id = Shader.PropertyToID("_PostFXSource2");
    private int bloomBucibicUpsamplingId = Shader.PropertyToID("_BloomBicubicUpsampling");
    private int bloomPrefilterId = Shader.PropertyToID("_BloomPrefilter");
    private int bloomThresholdId = Shader.PropertyToID("_BloomThreshold");
    private int bloomIntensityId = Shader.PropertyToID("_BloomIntensity");
    public bool IsActive => settings != null;
    private const int maxBloomPyramidLevels = 16;
    private int bloomPyramidId;
    enum Pass
    {
        // BloomPrefilter,
        // BloomCombine,
        BloomVertical,
        BloomHorizontal,
        BloomCombine,
        BloomPrefilter,
        Copy,
    }

    public PostFXStack()
    {
        bloomPyramidId = Shader.PropertyToID("_BloomPyramid0");
        for (int i = 0; i < maxBloomPyramidLevels * 2; i++)
        {
            // id的结果是 申请的顺序 +1的结果
            Shader.PropertyToID("_BloomPyramid"+i);
        }
    }


    void DoBloom(int sourceId)
    {
        buffer.BeginSample("Bloom");
        PostFXSettings.BloomSettings bloom = settings.Bloom;
        int width = camera.pixelWidth / 2, height = camera.pixelHeight / 2;
        
        Vector4 threshold;
        threshold.x = Mathf.GammaToLinearSpace(bloom.threshold);
        threshold.y = threshold.x * bloom.thresholdKnee;
        threshold.z = threshold.y * 2f;
        threshold.w = 0.25f /( threshold.y + 0.00001f);
        threshold.y -= threshold.x;
        buffer.SetGlobalVector(bloomThresholdId,threshold);
        
        
        
        RenderTextureFormat format = RenderTextureFormat.Default;
        buffer.GetTemporaryRT(bloomPrefilterId,width,height,0,FilterMode.Bilinear,format);
        Draw(sourceId,bloomPrefilterId,Pass.BloomPrefilter);
        width /= 2;
        height /= 2;
        int formId = bloomPrefilterId;
        int toId = bloomPyramidId + 1;

        int i;
        for ( i = 0; i < bloom.maxIterations; i++)
        {
            if (bloom.maxIterations == 0 || bloom.intensity <=0 || height < bloom.downscaleLimit * 2 || width < bloom.downscaleLimit * 2)
            {
                break;
            }

            int midId = toId - 1;
            buffer.GetTemporaryRT(midId,width,height,0,FilterMode.Bilinear,format);
            buffer.GetTemporaryRT(toId,width,height,0,FilterMode.Bilinear,format);
            Draw(formId, midId,Pass.BloomHorizontal);
            Draw(midId,toId,Pass.BloomVertical);
            formId = toId;
            toId += 2;
            width /= 2;
            height /= 2;
        }
        buffer.ReleaseTemporaryRT(bloomPrefilterId);
        buffer.SetGlobalFloat(bloomBucibicUpsamplingId,bloom.bicubicUpsampling ? 1f : 0f);
        buffer.SetGlobalFloat(bloomIntensityId,bloom.intensity);
        //Draw(formId,BuiltinRenderTextureType.CameraTarget,Pass.BloomHorizontal);
        if (i>1)
        {
            
        
        buffer.ReleaseTemporaryRT(formId - 1);
        toId -= 5;
        for (i -= 1; i > 0; i--)
        {
            buffer.SetGlobalTexture(fxSource2Id,toId+1);
            Draw(formId,toId,Pass.BloomCombine);
            buffer.ReleaseTemporaryRT(formId);
            buffer.ReleaseTemporaryRT(toId + 1);
            formId = toId;
            toId -= 2;
        }
        }
        else
        {
            buffer.ReleaseTemporaryRT(bloomPyramidId);
        }
        buffer.SetGlobalTexture(fxSource2Id,sourceId);
        Draw(formId,BuiltinRenderTextureType.CameraTarget,Pass.BloomCombine);
        buffer.ReleaseTemporaryRT(formId);
        buffer.EndSample("Bloom");
    }
    
    
    /// <summary>
    /// 用来替换 buff.Blit 的函数, 比Blit 更高效
    /// </summary>
    /// <param name="from"></param>
    /// <param name="to"></param>
    /// <param name="pass"></param>
    void Draw(RenderTargetIdentifier from,RenderTargetIdentifier to, Pass pass)
    {
        buffer.SetGlobalTexture(fxSourceId,from);
        buffer.SetRenderTarget(to,RenderBufferLoadAction.DontCare,RenderBufferStoreAction.Store);
        buffer.DrawProcedural(Matrix4x4.identity, settings.Material,(int)pass,MeshTopology.Triangles,3);
    }
    public void Setup(ScriptableRenderContext context, Camera camera, PostFXSettings settings)
    {
        this.context = context;
        this.camera = camera;
        this.settings = camera.cameraType <= CameraType.SceneView ? settings : null;
        ApplySceneViewState();
    }
    
    public void Render(int sourceId)
    {
        //Draw(sourceId,BuiltinRenderTextureType.CameraTarget,Pass.Copy);
        DoBloom(sourceId);
        //buffer.Blit(sourceId,BuiltinRenderTextureType.CameraTarget);
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }

    // void ApplySceneViewState()
    // {
    //     if (camera.cameraType == CameraType.SceneView && !SceneView.currentDrawingSceneView.sceneViewState.showImageEffects )
    //     {
    //         settings = null;
    //     }
    // }
    
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;

[CreateAssetMenu(menuName = "Rendering/Custom Post FX Settings")]
public class PostFXSettings : ScriptableObject
{
    [SerializeField]
    private Shader shader = default;

    [System.Serializable]
    public struct BloomSettings
    {
        [Range(0f,16f)]
        public int maxIterations;
        [FormerlySerializedAs("downscaleLimit")] [Min(1f)]
        public int downscaleLimit;
        // 是否使用三线性插值滤波
        public bool bicubicUpsampling;

        [Min(0f)]
        public float threshold;
        [Range(0f,1f)]
        public float thresholdKnee;
        [Min(0f)]
        public float intensity;
    }
    [SerializeField]
    private BloomSettings bloom = default;
    
    public BloomSettings Bloom => bloom;

    [System.NonSerialized]
    private Material material;

    public Material Material
    {
        get
        {
            if (material==null && shader != null)
            {
                material = new Material(shader);
                material.hideFlags = HideFlags.HideAndDontSave;
            }
            return material;
        }
    }
}

Shader "Hidden/CustomRP/PostFXStack"
{
    SubShader
    {
    
        Cull Off
        ZTest Always
        Zwrite Off
                    
            HLSLINCLUDE
            #include "../ShaderLibrary/Common.hlsl"
            #include "PostFXStackPasses.hlsl"
            ENDHLSL

        
        
        Pass
        {
            Name "Bloom Vertical"        
            HLSLPROGRAM
            #pragma target 3.5
            #pragma vertex DefaultPassVertex
            #pragma fragment BloomVerticalPassFragment            
            ENDHLSL
        }    
//            
        Pass
        {
            Name "Bloom Horizontal"        
            HLSLPROGRAM
            #pragma target 3.5
            #pragma vertex DefaultPassVertex
            #pragma fragment BloomHorizontalPassFragment            
            ENDHLSL
        }
        
        Pass
        {
            Name "Bloom Combine"        
            HLSLPROGRAM
            #pragma target 3.5
            #pragma vertex DefaultPassVertex
            #pragma fragment BloomCombinePassFragment            
            ENDHLSL
        }
                    
        Pass
        {
            Name "Bloom Prefilter"        
            HLSLPROGRAM
            #pragma target 3.5
            #pragma vertex DefaultPassVertex
            #pragma fragment BloomprefilterPassFragment            
            ENDHLSL
        }
        
            
        Pass
        {
            Name "Copy"        
            HLSLPROGRAM
            #pragma target 3.5
            #pragma vertex DefaultPassVertex
            #pragma fragment CopyPassFragment            
            ENDHLSL
        }
       
        
         
        
    }
}

// unity  标准输入库
#ifndef CUSTOM_POST_FX_STACE_INCLUDE 
#define CUSTOM_POST_FX_STACE_INCLUDE
#include "../../../Library/PackageCache/com.unity.render-pipelines.core@10.3.2/ShaderLibrary/Filtering.hlsl"
TEXTURE2D(_PostFXSource);
TEXTURE2D(_PostFXSource2);

SAMPLER(sampler_linear_clamp);
float4 _PostFXSource_TexelSize;    

bool _BloomBicubicUpsampling;
float4 _BloomThreshold;
float _BloomIntensity;

float4 GetSourceTexelSize()
{
    return _PostFXSource_TexelSize;
}



float4 GetSource(float2 screenUV)
{
    return SAMPLE_TEXTURE2D_LOD(_PostFXSource,sampler_linear_clamp,screenUV,0);
}


float4 GetSource2(float2 screenUV)
{
    return SAMPLE_TEXTURE2D_LOD(_PostFXSource2,sampler_linear_clamp,screenUV,0);
}


float4 GetSourceBicubic(float2 screenUV)
{
    return SampleTexture2DBicubic(TEXTURE2D_ARGS(_PostFXSource,sampler_linear_clamp),screenUV,_PostFXSource_TexelSize.zwxy,1.0,1.0);
}



struct Varyings
{
    float4 positionCS : SV_POSITION;
    float2 screenUV : VAR_SCREEN_UV;
};

Varyings DefaultPassVertex(uint vertexID : SV_vertexID)
{
    Varyings output;
    output.positionCS = float4(vertexID <= 1 ? -1.0 : 3.0,vertexID == 1 ? 3.0 : -1.0,0.0,1.0);
    output.screenUV = float2(vertexID <= 1 ? 0.0 : 2.0, vertexID == 1 ? 2.0 : 0.0);
    // y 值上下反转
    if(_ProjectionParams.x < 0.0)
    {
        output.screenUV.y = 1.0 - output.screenUV.y;
    }
    return output;
}

float4 CopyPassFragment(Varyings input) : SV_TARGET
{
    // 用于调试
    //return float4(input.screenUV,0.0,1.0);
    return GetSource(input.screenUV);
}

//----------------
//----------------
//----------------
//----------------



// 水平方向的模糊
float4 BloomHorizontalPassFragment(Varyings input) : SV_TARGET
{
    float3 color = 0.0;
    float offsets[] = {-4.0,-3.0,-2.0,-1.0,0.0,
                        1.0,2.0,3.0,4.0 };
    float weights[] = { 0.01621622,0.05405405,0.12162162,0.19459459, 0.22702703,
                        0.19459459,0.12162162 ,0.05405405,0.01621622};
    
   for(int i= 0; i<9; i++)
   {
    float offset = offsets[i] *2.0 * GetSourceTexelSize().x;
    color += GetSource(input.screenUV + float2(offset,0.0)).rgb * weights[i];
   }
    return float4(color,1.0);
}


//  在vertical 中可以缩减到5次, 但是在 BloomHorizontal中不能,因为已经在该pass中使用了双线性过滤
float4 BloomVerticalPassFragment(Varyings input) : SV_TARGET
{
    float3 color = 0.0;
    float offsets[] = {-3.23076923,-1.38461538, 0.0,1.38461538 ,3.23076923};
    float weights[] = { 0.07027027,0.31621622, 0.22702703,
                        0.31621622,0.07027027 };
                            
   for(int i = 0;i<5; i++)
   {
        float offset = offsets[i] * GetSourceTexelSize().y;
        color += GetSource(input.screenUV + float2(0.0,offset)).rgb * weights[i];
   }
    return float4(color,1.0);
}

float4 BloomCombinePassFragment(Varyings input):SV_TARGET
{
    float3 lowRes;
    if (_BloomBicubicUpsampling) 
    {
        lowRes = GetSourceBicubic(input.screenUV).rgb;
    }
    else
    {
        lowRes = GetSource(input.screenUV).rgb;
    }
    
    float3 hightRes = GetSource2(input.screenUV).rgb;
    return float4(lowRes * _BloomIntensity + hightRes,1.0);
}


float3 ApplyBloomThreshold(float3 color)
{
    float brightness = Max3(color.r,color.g,color.b);
    float soft = brightness + _BloomThreshold.y;
    soft = clamp(soft,0.0, _BloomThreshold.z);
    soft = soft * soft * _BloomThreshold.w;
    float contribution = max(soft,brightness - _BloomThreshold.x);
    contribution /= max(brightness,0.00001);
    return color * contribution; 
}


float4 BloomprefilterPassFragment(Varyings input):SV_TARGET
{
    float3 color = ApplyBloomThreshold(GetSource(input.screenUV).rgb);
    return float4(color,1.0);
}




#endif

标签:自定义,buffer,screenUV,private,int,URP,pragma,float4,Bloom
来源: https://blog.csdn.net/js0907/article/details/121431606

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有