最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

URP管線,RenderFeature后處理模糊小記

2023-06-06 15:56 作者:zhou-shan  | 我要投稿


參數(shù)界面

參考文章:Carle專欄? 算法取自毛老師? https://zhuanlan.zhihu.com/p/125744132

模糊算法這里用的是Kawase和DualKawase,最后整合到了一起~~

文末附代碼~~~~~

(才接觸RenderFeature,如有解釋不準(zhǔn)確的地方,希望斧正 感謝)

簡(jiǎn)單解釋一下Kawase思路:

一、算法解析

KawaseBlur

Kawase模糊精華在于算子是隨模糊迭代而變化的,圖中黑點(diǎn)為被渲染像素點(diǎn),紅點(diǎn)為采樣點(diǎn),由采樣點(diǎn)的值計(jì)算出被渲染像素點(diǎn)的值。注意,這里4個(gè)采樣點(diǎn)位于黑點(diǎn)像素的四個(gè)角??!四個(gè)角!意味著這里UV偏移就不能是意義上的One pixe,而是偏移半個(gè)像素點(diǎn)的距離,知道這里后咋們上蒜子圖~~

算子

二、shader部分

回顧KawaseBlur圖,第一次采樣UV偏移為?0.5 * KawaseBlurKernel[m] * TexturePixeSize。第二次采樣UV偏移為1.5*XXX,第三次采樣為2.5*XXX~~~如此類推,所以說(shuō)算子是迭代變化的。上shader關(guān)鍵代碼:

shader關(guān)鍵代碼

三、RenderFeature部分

shader都是小菜,RenderFeature才是最復(fù)雜的,上菜!??!

CS

這里我喜歡把Setting、Feature、Pass分別定義成單獨(dú)的CS文件。

1、Setting解析

這里定義的參數(shù)是顯示到面板的接口,

看紅框部分!??!

藥點(diǎn)

①[System.Serializable]是“序列化參數(shù)列表”,沒(méi)懂什么意思,大概看來(lái)就是配合后面在Feature中定義好Public該類,就能暴露出參數(shù),可通過(guò)面板直接修改。

②這里shader可直接Feature中指定路徑,也可以暴露出來(lái)手動(dòng)指定

③downsamplescale是將處理源圖像給縮小的倍數(shù),passloop是迭代次數(shù),BlurRadius是將要傳入到Pass中的定義的Offset值

2、Feature解析

Feature

藥點(diǎn)

①Create函數(shù)當(dāng)Setting變化時(shí)執(zhí)行,所以這里我們將函數(shù)外聲明好的m_pass放到這里面進(jìn)行實(shí)例化,他的有參構(gòu)造函數(shù)在Pass的Class中,簡(jiǎn)單的賦值并指定渲染時(shí)機(jī)。

有參構(gòu)造函數(shù)

②AddRenderPasses每幀執(zhí)行,將Pass放入到緩沖池里。這里可以做一個(gè)判空,有需要再Debug一下也行。

③Setupsource函數(shù)是我們定義的將相機(jī)圖像傳入到RT的一個(gè)函數(shù)。

3、Pass解析,重中之重來(lái)咯

這里定義了Pass類中需要的變量,以及enum類型的BlurPassIndex。另外臨時(shí)RT的申請(qǐng)流程分三步走,

先用?Shader.PropertyToID("XXXX")定義int類型的ID,

再用cmd.GetTemporaryRT(ID)申請(qǐng)RT,

最后實(shí)例化RT(將RT與ID綁定的操作)RenderTargetIdentifier RTNAME = new?RenderTargetIdentifier(ID)。

這里因?yàn)楹竺嫔婕暗絉T在循環(huán)中申請(qǐng)和釋放,所以我只是先聲明了RT并未將其實(shí)例化。

Pass的大體結(jié)構(gòu)可分為三部分

第一部分:

OnCameraSetup

OnCameraSetup函數(shù)是初始化函數(shù),可以將申請(qǐng)RT、配置RT、申請(qǐng)變量等初始化操作放在這里面執(zhí)行。(這里的操作也可以放到第二部分Execute中做,看個(gè)人選擇和功能需求)

第二部分:

Execute

Render函數(shù)如圖

Render

Execute函數(shù)就是具體Pass的執(zhí)行函數(shù)了,也是最重要的部分。

藥點(diǎn)

①因?yàn)镋xecute函數(shù)中沒(méi)有自定義commandBuffer,所以我們會(huì)在函數(shù)體內(nèi)用CommandBufferPool.Get(“PassNameXXX”)命令申請(qǐng)一個(gè)CommandBuffer類型的緩沖區(qū)命令,最后由context.ExecuteCommandBuffer(cmd);注入到緩沖池中

②用了個(gè)Switch控制Feature執(zhí)行哪個(gè)函數(shù),因?yàn)槲覀儗awase和DualKawase寫到了一起

③申請(qǐng)的緩沖區(qū)命令和RT一樣,最終都需要手動(dòng)去釋放以免內(nèi)存泄漏。CommandBufferPool.Release(cmd);

④看Render函數(shù),先用cmd.Blit命令將Source圖像復(fù)制給RT1,再結(jié)合for函數(shù)和一個(gè)bool值和語(yǔ)法糖,乒乓執(zhí)行Pass


稍等一下,插句嘴

看到這里細(xì)心的朋友應(yīng)該注意到了,我們用RT1 RT2都是先申請(qǐng)后使用,為什么這個(gè)this.Source只是聲明了都沒(méi)申請(qǐng)就能用?。。。?/span>

而且最后一個(gè)Blit我們將結(jié)果直接復(fù)制到Source中就收工大吉了,

在FreamDebug中卻顯示我們最后的Blit是將結(jié)果Copy給了cameraColorTarget

這是為什么呢???有的同學(xué)肯定就說(shuō)了Class類直接用等號(hào)賦值相當(dāng)于引用,可以理解為指針。但是我發(fā)現(xiàn)RT、cameraColorTarget、Source的類型RenderTargetIdentifier為結(jié)構(gòu)體??!不是Class!??!結(jié)構(gòu)體等號(hào)賦值實(shí)際上是新定義了一個(gè)變量,這里把我困擾到了,所以我覺(jué)得最合理的應(yīng)該把這里的Source全部替換為cameraColorTarget,省去AddRenderPasses里的那步,我懶了 試過(guò)可行,這兒就把重新截圖了。Unity肯定哪步將二者的地址給指定了一下,所以我最后也不用再釋放Source這個(gè)變量了......

有知道的朋友能告知一下原因嗎!?。。。。?!感謝了

繼續(xù)藥點(diǎn)

⑤這里這個(gè)語(yǔ)法糖我覺(jué)得非常巧妙,避免了我們?nèi)ピ俣x一個(gè)邏輯或者RT來(lái)充當(dāng)temp打工人。

⑥最后釋放兩張RT,這步其實(shí)可以放到接下來(lái)要截圖的第三部分中,但是我還是就寫在第二步的Execute中吧。

三、第三部分

就是可以用來(lái)最終注銷釋放RT等操作,沒(méi)什么可說(shuō)的。

DualKawase就先鴿一鴿吧,碼字太累了...

上源碼:

BlurSetting.cs

using UnityEngine;

using UnityEngine.Rendering;

using UnityEngine.Rendering.Universal;


namespace BlurSettingnamespace

{

? ? [System.Serializable]

? ? public class BlurSetting

? ? {

? ? ? ? public Shader shader = null;


? ? ? ? public BlurType blurType = BlurType.Kawase;


? ? ? ? public RenderPassEvent passEvent = RenderPassEvent.AfterRenderingSkybox;


? ? ? ? public enum BlurType

? ? ? ? {

? ? ? ? ? ? Kawase ,

? ? ? ? ? ? DualKawase,

? ? ? ? ? ? Gaussian

? ? ? ? }? ? ? ?

? ? }

? ? [System.Serializable]

? ? public class KawaseBlurSetting

? ? {

? ? ? ? [Range(1, 10)]

? ? ? ? public int downsamplescale = 1;


? ? ? ? [Range(0, 10)]

? ? ? ? public int passloop = 5;


? ? ? ? [Range(0.0f, 5.0f)]

? ? ? ? public float BlurRadius = 1.0f;


? ? }

? ? [System.Serializable]

? ? public class DualKawaseBlurSetting

? ? {

? ? ? ? [Range(0, 10)]

? ? ? ? public int iteration = 5;


? ? ? ? [Range(0.0f, 5.0f)]

? ? ? ? public float BlurRadius = 1.0f;

? ? }

}

KawaseBlurRenderPass.cs


using UnityEngine.Rendering;

using UnityEngine.Rendering.Universal;


using BlurSettingnamespace;


namespace KawaseBlurRenderPassnamespace

{

? ? class KawaseBlurRenderPass : ScriptableRenderPass

? ? {

? ? ? ? private BlurSetting m_setting;

? ? ? ? private KawaseBlurSetting kawaseBlurSetting;

? ? ? ? private DualKawaseBlurSetting dualKawaseBlurSetting;

? ? ? ??

? ? ? ? enum BlurPassIndex

? ? ? ? {

? ? ? ? ? ? KawasePass = 0,

? ? ? ? ? ? DualKawaseUpPass = 1,

? ? ? ? ? ? DualKawaseDownPass = 2

? ? ? ? }


? ? ? ? public KawaseBlurRenderPass(BlurSetting blurSetting, KawaseBlurSetting kawaseBlurSetting , DualKawaseBlurSetting dualKawaseBlurSetting)

? ? ? ? {

? ? ? ? ? ? this.m_setting = blurSetting;

? ? ? ? ? ? this.kawaseBlurSetting = kawaseBlurSetting;

? ? ? ? ? ? this.dualKawaseBlurSetting = dualKawaseBlurSetting;

? ? ? ? ? ? this.renderPassEvent = blurSetting.passEvent;? ? ? ? ? ??

? ? ? ? }


? ? ? ? //定義源RT

? ? ? ? private RenderTargetIdentifier Source { get; set; }


? ? ? ? //聲明兩個(gè)臨時(shí)RT(未實(shí)例化)? 定義其ID

? ? ? ? private readonly int TempRTID1 = Shader.PropertyToID("TempRTID1Name");

? ? ? ? private readonly int TempRTID2 = Shader.PropertyToID("TempRTID2Name");? ? ? ??


? ? ? ? RenderTargetIdentifier TempRT1;

? ? ? ? RenderTargetIdentifier TempRT2;


? ? ? ? //定義一個(gè)shader參數(shù)ID

? ? ? ? private readonly int _OffsetID = Shader.PropertyToID("_Offset");

? ? ? ? Material passmat;


? ? ? ? public void Setupsource(RenderTargetIdentifier source)

? ? ? ? {

? ? ? ? ? ? this.Source = source;

? ? ? ? }

? ? ? ? // This method is called before executing the render pass.

? ? ? ? // It can be used to configure render targets and their clear state. Also to create temporary render target textures.

? ? ? ? // When empty this render pass will render to the active camera render target.

? ? ? ? // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.

? ? ? ? // The render pipeline will ensure target setup and clearing happens in a performant manner.

? ? ? ? public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? if(m_setting.blurType == BlurSetting.BlurType.Kawase)

? ? ? ? ? ? ? ? Initialize(cmd, renderingData);


? ? ? ? ? ? if (m_setting.shader == null)

? ? ? ? ? ? ? ? return;

? ? ? ? ? ? else? ? ? ? ? ??

? ? ? ? ? ? ? ? passmat = new Material(m_setting.shader);?

? ? ? ? ? ??

? ? ? ? }


? ? ? ? // Here you can implement the rendering logic.

? ? ? ? // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers

? ? ? ? // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html

? ? ? ? // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.

? ? ? ? public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? CommandBuffer cmd = CommandBufferPool.Get("KawaseBlurPass");


? ? ? ? ? ? //重要操作

? ? ? ? ? ? switch(m_setting.blurType)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? case BlurSetting.BlurType.Kawase:

? ? ? ? ? ? ? ? ? ? Render(cmd , renderingData);

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? case BlurSetting.BlurType.DualKawase:

? ? ? ? ? ? ? ? ? ? DualRender(cmd, renderingData);

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? default:

? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? }


? ? ? ? ? ? context.ExecuteCommandBuffer(cmd);


? ? ? ? ? ? CommandBufferPool.Release(cmd);? ? ? ? ? ??

? ? ? ? }


? ? ? ? // Cleanup any allocated resources that were created during the execution of this render pass.

? ? ? ? public override void OnCameraCleanup(CommandBuffer cmd)

? ? ? ? {

? ? ? ? }

? ? ? ? void Initialize(CommandBuffer cmd , RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? RenderTextureDescriptor renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;


? ? ? ? ? ? int width = Mathf.Max(renderTextureDescriptor.width / kawaseBlurSetting.downsamplescale, 1);

? ? ? ? ? ? int height = Mathf.Max(renderTextureDescriptor.height / kawaseBlurSetting.downsamplescale, 1);


? ? ? ? ? ? //申請(qǐng)兩個(gè)臨時(shí)RT

? ? ? ? ? ? cmd.GetTemporaryRT(TempRTID1, width, height, 0, FilterMode.Trilinear, renderTextureDescriptor.colorFormat);

? ? ? ? ? ? cmd.GetTemporaryRT(TempRTID2, width, height, 0, FilterMode.Trilinear, renderTextureDescriptor.colorFormat);


? ? ? ? ? ? //指定RT? 實(shí)例化的過(guò)程

? ? ? ? ? ? TempRT1 = new RenderTargetIdentifier(TempRTID1);

? ? ? ? ? ? TempRT2 = new RenderTargetIdentifier(TempRTID2);

? ? ? ? }

? ? ? ? void DualInitialize(CommandBuffer cmd , RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? //RenderTextureDescriptor renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;

? ? ? ? ? ??

? ? ? ? }

? ? ? ? void Render(CommandBuffer cmd ,RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? cmd.Blit(this.Source, TempRTID1);

? ? ? ? ? ? bool NeedSwith = true;

? ? ? ? ? ? for(int i = 1;i < (kawaseBlurSetting.passloop + 1); i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? //cmd.SetGlobalFloat(_OffsetID , i / kawaseBlurSetting.downsamplescale + kawaseBlurSetting.BlurRadius);

? ? ? ? ? ? ? ? cmd.SetGlobalFloat(_OffsetID , i + kawaseBlurSetting.BlurRadius);

? ? ? ? ? ? ? ? cmd.Blit(NeedSwith ? TempRT1 : TempRT2, NeedSwith ? TempRT2 : TempRT1, passmat, (int)BlurPassIndex.KawasePass);

? ? ? ? ? ? ? ? NeedSwith = !NeedSwith;

? ? ? ? ? ? }

? ? ? ? ? ? cmd.Blit(NeedSwith ? TempRT1 : TempRT2, this.Source);


? ? ? ? ? ? //釋放RT

? ? ? ? ? ? cmd.ReleaseTemporaryRT(TempRTID1);

? ? ? ? ? ? cmd.ReleaseTemporaryRT(TempRTID2);

? ? ? ? }


? ? ? ? void DualRender(CommandBuffer cmd , RenderingData renderingData)

? ? ? ? {

? ? ? ? ? ? RenderTextureDescriptor renderTextureDescriptor = renderingData.cameraData.cameraTargetDescriptor;

? ? ? ? ? ? int Width = renderTextureDescriptor.width;

? ? ? ? ? ? int Height = renderTextureDescriptor.height;

? ? ? ? ? ? bool IsChange = true;


? ? ? ? ? ? //初始化RT1 RT2

? ? ? ? ? ? SetupRT(cmd, TempRT1, TempRTID1, Width, Height);


? ? ? ? ? ? Width /= 2;

? ? ? ? ? ? Height /= 2;

? ? ? ? ? ? SetupRT(cmd, TempRT2, TempRTID2, Width , Height);


? ? ? ? ? ? //將Source傳入RT1中

? ? ? ? ? ? cmd.Blit(this.Source, TempRTID1);


? ? ? ? ? ? //傳遞參數(shù)給shader

? ? ? ? ? ? cmd.SetGlobalFloat(_OffsetID, dualKawaseBlurSetting.BlurRadius);


? ? ? ? ? ? //DownSample

? ? ? ? ? ? for (int i = 1;i < dualKawaseBlurSetting.iteration + 1; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Width /= 2;

? ? ? ? ? ? ? ? Height /= 2;


? ? ? ? ? ? ? ? cmd.Blit(IsChange ? TempRTID1 : TempRTID2,

? ? ? ? ? ? ? ? ? ? ? ? IsChange ? TempRTID2 : TempRTID1, passmat, (int)BlurPassIndex.DualKawaseDownPass);


? ? ? ? ? ? ? ? IsChange = !IsChange;


? ? ? ? ? ? ? ? //釋放RT 準(zhǔn)備參加下次循環(huán)計(jì)算

? ? ? ? ? ? ? ? cmd.ReleaseTemporaryRT(IsChange ? TempRTID2 : TempRTID1);


? ? ? ? ? ? ? ? //重新申請(qǐng)RT 準(zhǔn)備參加下次循環(huán)計(jì)算

? ? ? ? ? ? ? ? SetupRT(cmd, IsChange ? TempRT2 : TempRT1, IsChange ? TempRTID2 : TempRTID1, Width, Height);? ??

? ? ? ? ? ? }

? ? ? ? ? ? //找到最后參與Pass計(jì)算的RT 此時(shí)兩張RT都已申請(qǐng),未釋放


? ? ? ? ? ? //釋放最后申請(qǐng)的RT

? ? ? ? ? ? cmd.ReleaseTemporaryRT(IsChange ? TempRTID2 : TempRTID1);

? ? ? ? ? ? //重新申請(qǐng)正常尺寸的RT

? ? ? ? ? ? Width *= 4;

? ? ? ? ? ? Height *= 4;


? ? ? ? ? ? SetupRT(cmd, IsChange ? TempRT2 : TempRT1, IsChange ? TempRTID2 : TempRTID1, Width, Height);

? ? ? ? ? ? //升采樣循環(huán)

? ? ? ? ? ? for (int i = 1; i < dualKawaseBlurSetting.iteration + 1; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Width *= 2;

? ? ? ? ? ? ? ? Height *= 2;


? ? ? ? ? ? ? ? cmd.Blit(IsChange ? TempRTID1 : TempRTID2,

? ? ? ? ? ? ? ? ? ? ? ? IsChange ? TempRTID2 : TempRTID1, passmat, (int)BlurPassIndex.DualKawaseUpPass);


? ? ? ? ? ? ? ? IsChange = !IsChange;


? ? ? ? ? ? ? ? //釋放RT

? ? ? ? ? ? ? ? cmd.ReleaseTemporaryRT(IsChange ? TempRTID2 : TempRTID1);


? ? ? ? ? ? ? ? //重新申請(qǐng)RT

? ? ? ? ? ? ? ? SetupRT(cmd, IsChange ? TempRT2 : TempRT1, IsChange ? TempRTID2 : TempRTID1, Width, Height);

? ? ? ? ? ? }

? ? ? ? ? ? //最后將最后參與計(jì)算的RT傳遞回源RT中,再將兩個(gè)RT都釋放

? ? ? ? ? ? cmd.Blit(IsChange ? TempRTID1 : TempRTID2, this.Source);


? ? ? ? ? ? cmd.ReleaseTemporaryRT(TempRTID1);

? ? ? ? ? ? cmd.ReleaseTemporaryRT(TempRTID2);

? ? ? ? }


? ? ? ? void SetupRT(CommandBuffer cmd, RenderTargetIdentifier renderTargetIdentifier, int ID , int width , int heigh)

? ? ? ? {

? ? ? ? ? ? //申請(qǐng)臨時(shí)RT

? ? ? ? ? ? cmd.GetTemporaryRT(ID, width, heigh, 0, FilterMode.Trilinear, RenderTextureFormat.Default);

? ? ? ? ? ? //實(shí)例化RT

? ? ? ? ? ? renderTargetIdentifier = new RenderTargetIdentifier(ID);

? ? ? ? }

? ? }

}

KawaseBlurRenderfeature.cs

using UnityEngine;

using UnityEngine.Rendering;

using UnityEngine.Rendering.Universal;


using KawaseBlurRenderPassnamespace;

using BlurSettingnamespace;


public class KawaseBlurRenderfeature : ScriptableRendererFeature

{? ??

? ? public BlurSetting blurSetting = new();

? ? public KawaseBlurSetting kawaseBlurSetting = new();

? ? public DualKawaseBlurSetting dualKawaseBlurSetting = new();


? ? //public DualKawaseBlurSetting dualKawaseBlurSetting;


? ? KawaseBlurRenderPass m_pass;

? ??

? ? public override void Create()

? ? {

? ? ? ? m_pass = new(blurSetting, kawaseBlurSetting, dualKawaseBlurSetting);? ?

? ? }


? ? // Here you can inject one or multiple render passes in the renderer.

? ? // This method is called when setting up the renderer once per-camera.

? ? public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)

? ? {

? ? ? ? m_pass.Setupsource(renderer.cameraColorTarget);

? ? ? ? if(blurSetting.shader != null && kawaseBlurSetting.passloop != 0 && dualKawaseBlurSetting.iteration != 0)

? ? ? ? ? ? renderer.EnqueuePass(m_pass);

? ? }

}

shader源碼(本來(lái)我寫成了三個(gè)文件,但是路徑難免會(huì)不同,我就隨便整合成一個(gè)了,湊合用吧)

Shader "Post/KawaseBlur"

{

? ? Properties

? ? {

? ? ? ? [HideInInspector] _MainTex ("Texture", 2D) = "white" { }

? ? }


? ? HLSLINCLUDE

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


? ? //#include "../../RenderFeature/PostShaderSource/postprocessing.hlsl"

? ? //#include "../../RenderFeature/PostShaderSource/KawaseBlurKernel.hlsl"


? ? /////////////////////////////////////////////////////////////////////////////////////////

? ? //kawaseBlur算子和雙重向下采樣算子

? ? static float2 KawaseBlurKernel[4] = {

? ? ? ? float2(-1, -1), //左下

? ? ? ? float2(-1, 1), //左上

? ? ? ? float2(1, 1), //右上

? ? ? ? float2(1, -1) ? ? ?//右下


? ? };


? ? //雙重向上采樣算子

? ? static float2 KawaseBlurKernel_Up[8] = {

? ? ? ? float2(0, 1),

? ? ? ? float2(0.5, 0.5),

? ? ? ? float2(1, 0),

? ? ? ? float2(0.5, -0.5),

? ? ? ? float2(0, -1),

? ? ? ? float2(-0.5, -0.5),

? ? ? ? float2(-1, 0),

? ? ? ? float2(-0.5, 0.5),

? ? };


? ? float4 KawaseBlur(TEXTURE2D(Tex), SAMPLER(samplertex), float2 uv, float2 TexSize, float PixeOffset)

? ? {

? ? ? ? float4 col = 0;

? ? ? ? int loopnum = 4;

? ? ? ? for (int i = 0; i < loopnum; i++)

? ? ? ? col += SAMPLE_TEXTURE2D(Tex, samplertex, uv + (float2) (PixeOffset +0.5f) * KawaseBlurKernel[i] * TexSize);

? ? ? ? return col / loopnum;

? ? }


? ? float4 DualKawaseBlur_Up(TEXTURE2D(Tex), SAMPLER(samplertex), float2 uv, float2 TexSize, float PixeOffset)

? ? {

? ? ? ? float4 col = 0;

? ? ? ? for (int i = 4; i < 0; i++)

? ? ? ? {

? ? ? ? ? ? col += SAMPLE_TEXTURE2D(Tex, samplertex, uv + KawaseBlurKernel_Up[i] * (1.0 + PixeOffset) * TexSize);

? ? ? ? ? ? col += SAMPLE_TEXTURE2D(Tex, samplertex, uv + KawaseBlurKernel_Up[i + 1] * (1.0 + PixeOffset) * TexSize) * 2;

? ? ? ? }

? ? ? ? return col * 0.0833;

? ? }


? ? float4 DualKawaseBlur_Down(TEXTURE2D(Tex), SAMPLER(samplertex), float2 uv, float2 TexSize, float PixeOffset)

? ? {

? ? ? ? float4 col = SAMPLE_TEXTURE2D(Tex, samplertex, uv) * 0.5;

? ? ? ? for (int i = 0; i < 4; i++)

? ? ? ? col += SAMPLE_TEXTURE2D(Tex, samplertex, uv + KawaseBlurKernel[i] * (float2)PixeOffset * TexSize) * 0.125;

? ? ? ? return col;

? ? }


? ? struct appdata

? ? {

? ? ? ? float4 vertex : POSITION;

? ? ? ? float2 uv : TEXCOORD0;

? ? };


? ? struct v2f

? ? {

? ? ? ? float2 uv : TEXCOORD0;

? ? ? ? float4 vertex : SV_POSITION;

? ? };

? ?


? ? TEXTURE2D(_MainTex);

? ? SAMPLER(sampler_MainTex);


? ? CBUFFER_START(UnityPerMaterial)


? ? ? ? float4 _MainTex_TexelSize;


? ? CBUFFER_END

? ?

? ? v2f VertDefault(appdata v)

? ? {

? ? ? ? v2f o;

? ? ? ? o.vertex = TransformObjectToHClip(v.vertex.xyz);

? ? ? ? o.uv = v.uv;

? ? ? ? return o;

? ? }


? ? //////////////////////////////////////////////////////////////////////////////////////////////


? ? float _Offset;


? ? float4 frag(v2f i) : SV_Target

? ? {

? ? ? ? // sample the texture

? ? ? ? float4 col = KawaseBlur(_MainTex, sampler_MainTex, i.uv, _MainTex_TexelSize.xy, _Offset);

? ? ? ? return col;

? ? }


? ? float4 frag_Up(v2f i) : SV_Target

? ? {

? ? ? ? // sample the texture

? ? ? ? float4 col = KawaseBlur(_MainTex, sampler_MainTex, i.uv, _MainTex_TexelSize.xy, _Offset);

? ? ? ? return col;

? ? }


? ? float4 frag_Down(v2f i) : SV_Target

? ? {

? ? ? ? // sample the texture

? ? ? ? float4 col = KawaseBlur(_MainTex, sampler_MainTex, i.uv, _MainTex_TexelSize.xy, _Offset);

? ? ? ? return col;

? ? }

? ? ENDHLSL


? ? SubShader

? ? {

? ? ? ? Tags { "RenderType" = "Opaque" }

? ? ? ? Cull Off

? ? ? ? ZWrite Off

? ? ? ? ZTest Always

? ? ? ?

? ? ? ? Pass

? ? ? ? {

? ? ? ? ? ? Name "KawaseBlurPass"

? ? ? ? ? ? HLSLPROGRAM


? ? ? ? ? ? #pragma vertex VertDefault

? ? ? ? ? ? #pragma fragment frag


? ? ? ? ? ? ENDHLSL

? ? ? ? }


? ? ? ? Pass

? ? ? ? {

? ? ? ? ? ? Name "DualKawaseBlurPass_UpSampling"

? ? ? ? ? ? HLSLPROGRAM


? ? ? ? ? ? #pragma vertex VertDefault

? ? ? ? ? ? #pragma fragment frag_Up


? ? ? ? ? ? ENDHLSL

? ? ? ? }


? ? ? ? Pass

? ? ? ? {

? ? ? ? ? ? Name "DualKawaseBlurPass_DownSampling"

? ? ? ? ? ? HLSLPROGRAM


? ? ? ? ? ? #pragma vertex VertDefault

? ? ? ? ? ? #pragma fragment frag_Down


? ? ? ? ? ? ENDHLSL

? ? ? ? }

? ? }

}


URP管線,RenderFeature后處理模糊小記的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
岚皋县| 永顺县| 金堂县| 中超| 绩溪县| 昌乐县| 内乡县| 温泉县| 固阳县| 宁化县| 麻阳| 乳山市| 佛坪县| 沧州市| 韶关市| 织金县| 塘沽区| 芜湖县| 柯坪县| 江永县| 景洪市| 平遥县| 阜阳市| 桃园县| 遂宁市| 民县| 武乡县| 宝山区| 沾益县| 临城县| 汶上县| 龙口市| 浦东新区| 泸州市| 沁阳市| 锦州市| 六盘水市| 逊克县| 喀喇沁旗| 夹江县| 柳河县|