您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

277 行
8.4 KiB

using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Experimental.Rendering;
using System.Reflection;
namespace Unity.DemoTeam.DigitalHuman
{
// basic procedure:
//
// 1. alloc temp
// b. custom color (R8)
// c. custom normal (ARGBHalf)
//
// 2. clear
// b. write 1 -> custom color
//
// 3. mark decals
// a. write 0 -> custom color
// b. write 1 -> custom stencil
//
// 4. enable stencil
//
// 5. render fullscreen
// a. write decoded normal -> custom normal
//
// 6. render fullscreen
// a. write blurred decoded normal -> normal
//
// 7. free temp
public class NormalBufferBlurPass : CustomPass
{
[HideInInspector] public RenderQueueType queue = RenderQueueType.AllOpaque;
[HideInInspector] public LayerMask layerMask = 0;// default to 'None'
static readonly int rtRegions = Shader.PropertyToID("_NormalBufferBlur_Regions");
static readonly int rtDecoded = Shader.PropertyToID("_NormalBufferBlur_Decoded");
const string NAME_SHADER = "Hidden/DigitalHuman/NormalBufferBlurPass";
static readonly string[] NAME_PASS_REPLACE = new string[]
{
"Forward",// HDShaderPassNames.s_ForwardStr
"ForwardOnly",// HDShaderPassNames.s_ForwardOnlyStr
"SRPDefaultUnlit", // HDShaderPassNames.s_SRPDefaultUnlitStr
"DBufferMesh_3RT",// HDShaderPassNames.s_MeshDecalsMStr
};
static ShaderTagId[] NAME_PASS_REPLACE_TAG = null;
const int PASS_MARK = 0;
const int PASS_DECODE = 1;
const int PASS_BLUR_AND_ENCODE = 2;
const int PASS_BLUR_AND_ENCODE_AND_DECAL = 3;
Material passMaterial;
const int DBUFFER_NORMALS = 1;
const int DBUFFER_MASK = 2;
private RTHandle[] dbufferRTs;
private RenderTargetIdentifier[] dbufferRTIDs;
private RenderTargetIdentifier[] dbufferNormalMaskRTIDs;
private void FindDbufferRTs(HDRenderPipeline hdPipeline)
{
dbufferRTIDs = null;
var fieldInfo_m_DbufferManager = typeof(HDRenderPipeline).GetField("m_DbufferManager", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo_m_DbufferManager != null)
{
//Debug.Log("FindDbufferRTs : " + fieldInfo_m_DbufferManager);
var m_DbufferManager = fieldInfo_m_DbufferManager.GetValue(hdPipeline);
if (m_DbufferManager != null)
{
var fieldInfo_m_RTs = m_DbufferManager.GetType().GetField("m_RTs", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo_m_RTs != null)
{
//Debug.Log("FindDbufferRTs : " + fieldInfo_m_RTs);
dbufferRTs = fieldInfo_m_RTs.GetValue(m_DbufferManager) as RTHandle[];
}
var fieldInfo_m_RTIDs = m_DbufferManager.GetType().GetField("m_RTIDs", BindingFlags.NonPublic | BindingFlags.Instance);
if (fieldInfo_m_RTIDs != null)
{
//Debug.Log("FindDbufferRTIDs : " + fieldInfo_m_RTIDs);
dbufferRTIDs = fieldInfo_m_RTIDs.GetValue(m_DbufferManager) as RenderTargetIdentifier[];
}
}
}
}
private RenderTargetIdentifier[] GetDbufferNormalMaskRTIDs()
{
if (dbufferRTs != null)
{
if (dbufferRTs[DBUFFER_NORMALS] == null || dbufferRTs[DBUFFER_MASK] == null)
{
return null;
}
}
if (dbufferRTIDs != null)
{
if (dbufferNormalMaskRTIDs == null)
dbufferNormalMaskRTIDs = new RenderTargetIdentifier[2];
dbufferNormalMaskRTIDs[0] = dbufferRTIDs[DBUFFER_NORMALS];
dbufferNormalMaskRTIDs[1] = dbufferRTIDs[DBUFFER_MASK];
}
return dbufferNormalMaskRTIDs;
}
static bool EnsureMaterial(ref Material material, string shaderName)
{
if (material != null && material.shader == null)
material = null;
if (material == null)
material = CoreUtils.CreateEngineMaterial(shaderName);
return (material != null);
}
protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
{
base.Setup(renderContext, cmd);
base.name = "NormalBufferBlurPass";
FindDbufferRTs(RenderPipelineManager.currentPipeline as HDRenderPipeline);
EnsureMaterial(ref passMaterial, NAME_SHADER);
if (passMaterial != null)
{
passMaterial.SetInt("_StencilBit", (int)UserStencilUsage.UserBit0);
}
if (NAME_PASS_REPLACE_TAG == null)
{
NAME_PASS_REPLACE_TAG = new ShaderTagId[NAME_PASS_REPLACE.Length];
for (int i = 0; i != NAME_PASS_REPLACE_TAG.Length; i++)
{
NAME_PASS_REPLACE_TAG[i] = new ShaderTagId(NAME_PASS_REPLACE[i]);
}
}
}
#if UNITY_2020_2_OR_NEWER
protected override void Execute(CustomPassContext ctx)
{
Profiler.BeginSample("NormalBufferBlurPass");
ExecuteNormalBufferBlur(
ctx.renderContext,
ctx.cmd,
ctx.hdCamera,
ctx.cameraColorBuffer,
ctx.cameraDepthBuffer,
ctx.cameraNormalBuffer,
ctx.cullingResults
);
Profiler.EndSample();
}
#else
protected override void Execute(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, CullingResults cullingResults)
{
RTHandle cameraColor;
RTHandle cameraDepth;
GetCameraBuffers(out cameraColor, out cameraDepth);
Profiler.BeginSample("NormalBufferBlurPass");
ExecuteNormalBufferBlur(
renderContext,
cmd,
hdCamera,
cameraColor,
cameraDepth,
GetNormalBuffer(),
cullingResults
);
Profiler.EndSample();
}
#endif
void ExecuteNormalBufferBlur(ScriptableRenderContext renderContext, CommandBuffer cmd, HDCamera hdCamera, RTHandle cameraColor, RTHandle cameraDepth, RTHandle cameraNormal, CullingResults cullingResults)
{
if (!EnsureMaterial(ref passMaterial, NAME_SHADER))
return;
if (layerMask == 0)
return;
if (!hdCamera.frameSettings.IsEnabled(FrameSettingsField.Decals))
return;
int bufferW = cameraColor.rt.width;
int bufferH = cameraColor.rt.height;
// allocate temporary buffers
cmd.GetTemporaryRT(rtRegions, bufferW, bufferH, (int)DepthBits.None, FilterMode.Point, RenderTextureFormat.R8, RenderTextureReadWrite.Linear, 1, false);
cmd.GetTemporaryRT(rtDecoded, bufferW, bufferH, (int)DepthBits.None, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, false);
// render decals to mark blur regions
CoreUtils.SetRenderTarget(cmd,
rtRegions, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
cameraDepth, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store,
ClearFlag.Color, Color.white
);
CoreUtils.SetViewport(cmd, cameraDepth);
RendererListDesc renderListDesc = new RendererListDesc(NAME_PASS_REPLACE_TAG, cullingResults, hdCamera.camera)
{
rendererConfiguration = PerObjectData.None,
renderQueueRange = GetRenderQueueRange(queue),
sortingCriteria = SortingCriteria.None,
layerMask = layerMask,
overrideMaterial = passMaterial,
overrideMaterialPassIndex = PASS_MARK,
stateBlock = null,
excludeObjectMotionVectors = false,
};
HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(renderListDesc));
// decode normal buffer in marked regions
CoreUtils.SetRenderTarget(cmd,
rtDecoded, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
cameraDepth, RenderBufferLoadAction.Load, RenderBufferStoreAction.DontCare,
ClearFlag.None
);
CoreUtils.SetViewport(cmd, cameraDepth);
cmd.SetRandomWriteTarget(2, cameraNormal);
cmd.DrawProcedural(Matrix4x4.identity, passMaterial, PASS_DECODE, MeshTopology.Triangles, 3, 1);
cmd.ClearRandomWriteTargets();
// blur and re-encode normals in marked regions
cmd.SetGlobalTexture(rtRegions, rtRegions);
cmd.SetGlobalTexture(rtDecoded, rtDecoded);
if (GetDbufferNormalMaskRTIDs() != null)
{
CoreUtils.SetRenderTarget(cmd,
GetDbufferNormalMaskRTIDs(),
cameraDepth,
ClearFlag.None);
CoreUtils.SetViewport(cmd, cameraDepth);
cmd.SetRandomWriteTarget(2, cameraNormal);
cmd.DrawProcedural(Matrix4x4.identity, passMaterial, PASS_BLUR_AND_ENCODE_AND_DECAL, MeshTopology.Triangles, 3, 1);
cmd.ClearRandomWriteTargets();
}
else
{
CoreUtils.SetRenderTarget(cmd,
cameraDepth, RenderBufferLoadAction.Load, RenderBufferStoreAction.Store,
ClearFlag.None
);
CoreUtils.SetViewport(cmd, cameraDepth);
cmd.SetRandomWriteTarget(2, cameraNormal);
cmd.DrawProcedural(Matrix4x4.identity, passMaterial, PASS_BLUR_AND_ENCODE, MeshTopology.Triangles, 3, 1);
cmd.ClearRandomWriteTargets();
}
// free temporary buffers
cmd.ReleaseTemporaryRT(rtRegions);
cmd.ReleaseTemporaryRT(rtDecoded);
}
protected override void Cleanup()
{
base.Cleanup();
}
}
}