151 lines
5.5 KiB
C#
151 lines
5.5 KiB
C#
|
|
using System;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEngine.Experimental.Rendering;
|
||
|
|
using UnityEngine.Experimental.Rendering.Universal;
|
||
|
|
using UnityEngine.Rendering;
|
||
|
|
using UnityEngine.Rendering.Universal;
|
||
|
|
|
||
|
|
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 mainTexID = Shader.PropertyToID("_MainTex");
|
||
|
|
|
||
|
|
RTHandle[] oitRTids = new RTHandle[2];
|
||
|
|
private ShaderTagId shaderTagId = new ShaderTagId("DoOIT");
|
||
|
|
|
||
|
|
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()
|
||
|
|
{
|
||
|
|
oitRTids[0]?.Release();
|
||
|
|
oitRTids[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 oitRTids[0], desc, filterMode: FilterMode.Bilinear);
|
||
|
|
RenderingUtils.ReAllocateIfNeeded(ref destinationRT, desc, filterMode: FilterMode.Bilinear);
|
||
|
|
|
||
|
|
cmd.SetRenderTarget(oitRTids[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 oitRTids[1], desc, filterMode: FilterMode.Bilinear);
|
||
|
|
|
||
|
|
cmd.SetRenderTarget(oitRTids[1]);
|
||
|
|
cmd.ClearRenderTarget(false, true, new Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||
|
|
|
||
|
|
RenderQueueRange renderQueueRange = (settings.FilterSettings.RenderQueueType == RenderQueueType.Transparent)
|
||
|
|
? RenderQueueRange.transparent
|
||
|
|
: RenderQueueRange.opaque;
|
||
|
|
|
||
|
|
var filteringSettings = new FilteringSettings(renderQueueRange, settings.FilterSettings.LayerMask);
|
||
|
|
var renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
|
||
|
|
SortingCriteria sortingCriteria = (filteringSettings.renderQueueRange == RenderQueueRange.transparent)
|
||
|
|
? SortingCriteria.CommonTransparent
|
||
|
|
: renderingData.cameraData.defaultOpaqueSortFlags;
|
||
|
|
|
||
|
|
DrawingSettings drawSettings = CreateDrawingSettings(shaderTagId, ref renderingData, sortingCriteria);
|
||
|
|
|
||
|
|
#region Draw Weighted Blended Order-Independent Transparency
|
||
|
|
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings, ref renderStateBlock);
|
||
|
|
#endregion
|
||
|
|
|
||
|
|
#region Blend
|
||
|
|
cmd.SetGlobalTexture(accumTexID, oitRTids[0]);
|
||
|
|
cmd.SetGlobalTexture(revealageTexID, oitRTids[1]);
|
||
|
|
cmd.SetGlobalTexture(mainTexID, rdr.cameraColorTargetHandle);
|
||
|
|
|
||
|
|
cmd.SetRenderTarget(destinationRT, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
|
||
|
|
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);
|
||
|
|
}
|
||
|
|
#endregion
|
||
|
|
context.ExecuteCommandBuffer(cmd);
|
||
|
|
cmd.Clear();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|