170 lines
6.3 KiB
C#
170 lines
6.3 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Experimental.Rendering;
|
|
using UnityEngine.Experimental.Rendering.Universal;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.RendererUtils;
|
|
using UnityEngine.Rendering.Universal;
|
|
|
|
[DisallowMultipleRendererFeature]
|
|
public class WBOITFeature : ScriptableRendererFeature
|
|
{
|
|
[Serializable]
|
|
public class FilterSettings
|
|
{
|
|
public RenderQueueType RenderQueueType;
|
|
public LayerMask LayerMask;
|
|
|
|
public FilterSettings()
|
|
{
|
|
RenderQueueType = RenderQueueType.Transparent;
|
|
LayerMask = 0;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class OITSettings
|
|
{
|
|
public RenderPassEvent RenderPassEvent = RenderPassEvent.AfterRenderingOpaques;
|
|
public FilterSettings FilterSettings = new FilterSettings();
|
|
public Shader BlendShader;
|
|
}
|
|
|
|
[SerializeField]
|
|
OITSettings settings;
|
|
|
|
OITRenderPass pass;
|
|
|
|
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
|
{
|
|
var cam = renderingData.cameraData;
|
|
if (cam.cameraType != CameraType.Game && cam.cameraType != CameraType.SceneView)
|
|
{
|
|
return;
|
|
}
|
|
|
|
renderer.EnqueuePass(pass);
|
|
}
|
|
|
|
public override void Create()
|
|
{
|
|
pass = new OITRenderPass(settings);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
base.Dispose(disposing);
|
|
pass.Dispose();
|
|
}
|
|
|
|
class OITRenderPass : ScriptableRenderPass, IDisposable
|
|
{
|
|
private ProfilingSampler profiler;
|
|
private CommandBuffer commandBuffer;
|
|
private OITSettings settings;
|
|
private Material blendMaterial;
|
|
|
|
static readonly int accumTexID = Shader.PropertyToID("_AccumTex");
|
|
static readonly int revealageTexID = Shader.PropertyToID("_RevealageTex");
|
|
static readonly int cameraColorTex = Shader.PropertyToID("_CameraColorTex");
|
|
|
|
RTHandle[] oitRTs = new RTHandle[2];
|
|
RenderTargetIdentifier[] oitRtIds = new RenderTargetIdentifier[2];
|
|
|
|
private ShaderTagId shaderTagId = new ShaderTagId("WBOIT");
|
|
|
|
public OITRenderPass(OITSettings settings)
|
|
{
|
|
this.settings = settings;
|
|
profiler = new(nameof(OITRenderPass));
|
|
commandBuffer = new CommandBuffer();
|
|
commandBuffer.name = profiler.name;
|
|
renderPassEvent = settings.RenderPassEvent;
|
|
blendMaterial = new Material(settings.BlendShader);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
oitRTs[0]?.Release();
|
|
oitRTs[1]?.Release();
|
|
commandBuffer.Release();
|
|
GameObject.DestroyImmediate(blendMaterial);
|
|
}
|
|
|
|
RTHandle destinationRT;
|
|
|
|
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
|
{
|
|
var cmd = commandBuffer;
|
|
using var scp = new ProfilingScope(cmd, profiler);
|
|
var rdr = renderingData.cameraData.renderer;
|
|
var desc = renderingData.cameraData.cameraTargetDescriptor;
|
|
desc.depthBufferBits = 0;
|
|
desc.sRGB = false;
|
|
RenderingUtils.ReAllocateIfNeeded(ref destinationRT, desc, filterMode: FilterMode.Bilinear);
|
|
|
|
desc.graphicsFormat = GraphicsFormat.R16G16B16A16_SFloat;
|
|
RenderingUtils.ReAllocateIfNeeded(ref oitRTs[0], desc, filterMode: FilterMode.Bilinear, name: "_AccumTex");
|
|
|
|
cmd.SetRenderTarget(oitRTs[0]);
|
|
cmd.ClearRenderTarget(false, true, new Color(0.0f, 0.0f, 0.0f, 0.0f));
|
|
desc.graphicsFormat = SystemInfo.IsFormatSupported(GraphicsFormat.R16_SFloat, FormatUsage.Render) ? GraphicsFormat.R16_SFloat : GraphicsFormat.R32_SFloat;
|
|
|
|
RenderingUtils.ReAllocateIfNeeded(ref oitRTs[1], desc, filterMode: FilterMode.Bilinear, name: "_RevealageTex");
|
|
|
|
cmd.SetRenderTarget(oitRTs[1]);
|
|
cmd.ClearRenderTarget(false, true, new Color(1.0f, 1.0f, 1.0f, 1.0f));
|
|
oitRtIds[0] = oitRTs[0];
|
|
oitRtIds[1] = oitRTs[1];
|
|
|
|
RenderQueueRange renderQueueRange = (settings.FilterSettings.RenderQueueType == RenderQueueType.Transparent)
|
|
? RenderQueueRange.transparent
|
|
: RenderQueueRange.opaque;
|
|
|
|
var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
|
|
SortingCriteria sortingCriteria = (renderQueueRange == RenderQueueRange.transparent)
|
|
? SortingCriteria.CommonTransparent
|
|
: renderingData.cameraData.defaultOpaqueSortFlags;
|
|
|
|
DrawingSettings drawSettings = CreateDrawingSettings(shaderTagId, ref renderingData, sortingCriteria);
|
|
|
|
#region Draw Weighted Blended Order-Independent Transparency
|
|
cmd.SetRenderTarget(oitRtIds, rdr.cameraDepthTargetHandle);
|
|
RendererList rendererList = context.CreateRendererList(new RendererListDesc(shaderTagId, renderingData.cullResults, renderingData.cameraData.camera)
|
|
{
|
|
renderQueueRange = renderQueueRange,
|
|
sortingCriteria = sortingCriteria,
|
|
rendererConfiguration = renderingData.perObjectData,
|
|
layerMask = settings.FilterSettings.LayerMask,
|
|
stateBlock = renderStateBlock,
|
|
});
|
|
|
|
cmd.DrawRendererList(rendererList);
|
|
#endregion
|
|
|
|
#region Blend
|
|
cmd.BeginSample("Blend");
|
|
cmd.SetGlobalTexture(accumTexID, oitRTs[0]);
|
|
cmd.SetGlobalTexture(revealageTexID, oitRTs[1]);
|
|
cmd.SetGlobalTexture(cameraColorTex, rdr.cameraColorTargetHandle);
|
|
|
|
cmd.SetRenderTarget(destinationRT, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare);
|
|
cmd.DrawProcedural(Matrix4x4.identity, blendMaterial, 0, MeshTopology.Triangles, 3);
|
|
|
|
if (SystemInfo.copyTextureSupport != CopyTextureSupport.None)
|
|
{
|
|
cmd.CopyTexture(destinationRT, rdr.cameraColorTargetHandle);
|
|
}
|
|
else
|
|
{
|
|
Blit(cmd, destinationRT, rdr.cameraColorTargetHandle);
|
|
}
|
|
cmd.EndSample("Blend");
|
|
#endregion
|
|
context.ExecuteCommandBuffer(cmd);
|
|
cmd.Clear();
|
|
}
|
|
}
|
|
}
|