251 lines
9.9 KiB
C#
251 lines
9.9 KiB
C#
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
using UnityEngine.Rendering.Universal;
|
|
#if UNITY_6000_0_OR_NEWER
|
|
using System;
|
|
using UnityEngine.Rendering.RenderGraphModule;
|
|
#endif
|
|
|
|
public class ScreenRenderPass : ScriptableRenderPass {
|
|
private Material _passMaterial;
|
|
private bool _requiresColor;
|
|
private bool _isBeforeTransparents;
|
|
private PassData _passData;
|
|
private ProfilingSampler _profilingSampler;
|
|
private RTHandle _copiedColor;
|
|
|
|
private static readonly Vector4 BlitScaleBias = new(1f, 1f, 0f, 0f);
|
|
private static readonly MaterialPropertyBlock SharedPropertyBlock = new();
|
|
private const string TexName = "_BlitTexture";
|
|
private static readonly int BlitTextureShaderID = Shader.PropertyToID(TexName);
|
|
private static readonly int BlitScaleBiasID = Shader.PropertyToID("_BlitScaleBias");
|
|
|
|
public void Setup(Material mat, bool requiresColor, bool isBeforeTransparents, string featureName,
|
|
in RenderingData renderingData) {
|
|
_passMaterial = mat;
|
|
_requiresColor = requiresColor;
|
|
_isBeforeTransparents = isBeforeTransparents;
|
|
_profilingSampler ??= new ProfilingSampler(featureName);
|
|
|
|
var colorCopyDescriptor = renderingData.cameraData.cameraTargetDescriptor;
|
|
colorCopyDescriptor.depthBufferBits = (int)DepthBits.None;
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
requiresIntermediateTexture = _requiresColor && !_isBeforeTransparents;
|
|
RenderingUtils.ReAllocateHandleIfNeeded(ref _copiedColor, colorCopyDescriptor, FilterMode.Point,
|
|
TextureWrapMode.Clamp, name: "_FullscreenPassColorCopy");
|
|
#elif UNITY_2022_3_OR_NEWER
|
|
RenderingUtils.ReAllocateIfNeeded(ref _copiedColor, colorCopyDescriptor, name: "_FullscreenPassColorCopy");
|
|
#endif
|
|
|
|
_passData ??= new PassData();
|
|
}
|
|
|
|
public void Dispose() {
|
|
_copiedColor?.Release();
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
|
|
var resourceData = frameData.Get<UniversalResourceData>();
|
|
var cameraData = frameData.Get<UniversalCameraData>();
|
|
|
|
if (_passMaterial == null) {
|
|
return;
|
|
}
|
|
|
|
if (!resourceData.activeColorTexture.IsValid()) {
|
|
return;
|
|
}
|
|
|
|
if (_requiresColor && resourceData.isActiveTargetBackBuffer) {
|
|
Debug.LogWarning("[Flat Kit] ScreenRenderPass requires sampling the active color buffer, but the renderer " +
|
|
"is currently writing directly to the backbuffer. Enable an intermediate color target " +
|
|
"(Renderer > Rendering > Intermediate Texture Mode = Always) or move the feature to an " +
|
|
"earlier render event.");
|
|
return;
|
|
}
|
|
|
|
TextureHandle copySource = TextureHandle.nullHandle;
|
|
|
|
if (_requiresColor) {
|
|
TextureDesc descriptor;
|
|
if (resourceData.cameraColor.IsValid()) {
|
|
descriptor = renderGraph.GetTextureDesc(resourceData.cameraColor);
|
|
} else {
|
|
descriptor = renderGraph.GetTextureDesc(resourceData.activeColorTexture);
|
|
}
|
|
|
|
descriptor.name = "_FlatKit_FullScreenCopy";
|
|
descriptor.clearBuffer = false;
|
|
|
|
TextureHandle copiedColor = renderGraph.CreateTexture(descriptor);
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<CopyPassData>("FlatKit Copy Color", out var passData,
|
|
_profilingSampler)) {
|
|
passData.source = resourceData.activeColorTexture;
|
|
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
builder.SetRenderAttachment(copiedColor, 0, AccessFlags.Write);
|
|
builder.SetRenderFunc((CopyPassData data, RasterGraphContext ctx) => {
|
|
Blitter.BlitTexture(ctx.cmd, data.source, BlitScaleBias, 0, false);
|
|
});
|
|
}
|
|
|
|
copySource = copiedColor;
|
|
}
|
|
|
|
using (var builder = renderGraph.AddRasterRenderPass<MainPassData>(_profilingSampler.name, out var passData,
|
|
_profilingSampler)) {
|
|
passData.material = _passMaterial;
|
|
passData.source = copySource;
|
|
|
|
if (passData.source.IsValid()) {
|
|
builder.UseTexture(passData.source, AccessFlags.Read);
|
|
}
|
|
|
|
var passInput = input;
|
|
bool needsColor = (passInput & ScriptableRenderPassInput.Color) != ScriptableRenderPassInput.None;
|
|
bool needsDepth = (passInput & ScriptableRenderPassInput.Depth) != ScriptableRenderPassInput.None;
|
|
bool needsNormals = (passInput & ScriptableRenderPassInput.Normal) != ScriptableRenderPassInput.None;
|
|
bool needsMotion = (passInput & ScriptableRenderPassInput.Motion) != ScriptableRenderPassInput.None;
|
|
|
|
if (needsColor && resourceData.cameraOpaqueTexture.IsValid()) {
|
|
builder.UseTexture(resourceData.cameraOpaqueTexture);
|
|
}
|
|
|
|
if (needsDepth && resourceData.cameraDepthTexture.IsValid()) {
|
|
builder.UseTexture(resourceData.cameraDepthTexture);
|
|
}
|
|
|
|
if (needsNormals && resourceData.cameraNormalsTexture.IsValid()) {
|
|
builder.UseTexture(resourceData.cameraNormalsTexture);
|
|
}
|
|
|
|
if (needsMotion && cameraData.renderer.SupportsMotionVectors()) {
|
|
if (resourceData.motionVectorColor.IsValid()) {
|
|
builder.UseTexture(resourceData.motionVectorColor);
|
|
}
|
|
|
|
if (resourceData.motionVectorDepth.IsValid()) {
|
|
builder.UseTexture(resourceData.motionVectorDepth);
|
|
}
|
|
}
|
|
|
|
builder.SetRenderAttachment(resourceData.activeColorTexture, 0, AccessFlags.Write);
|
|
|
|
builder.SetRenderFunc((MainPassData data, RasterGraphContext ctx) => {
|
|
SharedPropertyBlock.Clear();
|
|
|
|
if (data.source.IsValid()) {
|
|
SharedPropertyBlock.SetTexture(BlitTextureShaderID, data.source);
|
|
}
|
|
|
|
SharedPropertyBlock.SetVector(BlitScaleBiasID, BlitScaleBias);
|
|
|
|
ctx.cmd.DrawProcedural(Matrix4x4.identity, data.material, 0, MeshTopology.Triangles, 3, 1,
|
|
SharedPropertyBlock);
|
|
});
|
|
}
|
|
}
|
|
|
|
[Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled).", false)]
|
|
#endif
|
|
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
|
|
_passData.effectMaterial = _passMaterial;
|
|
_passData.requiresColor = _requiresColor;
|
|
_passData.isBeforeTransparents = _isBeforeTransparents;
|
|
_passData.profilingSampler = _profilingSampler;
|
|
_passData.copiedColor = _copiedColor;
|
|
|
|
ExecutePass(_passData, ref renderingData, ref context);
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
[Obsolete("This rendering path is for compatibility mode only (when Render Graph is disabled).", false)]
|
|
#endif
|
|
private static void ExecutePass(PassData passData, ref RenderingData renderingData,
|
|
ref ScriptableRenderContext context) {
|
|
var passMaterial = passData.effectMaterial;
|
|
var requiresColor = passData.requiresColor;
|
|
var copiedColor = passData.copiedColor;
|
|
var profilingSampler = passData.profilingSampler;
|
|
|
|
if (passMaterial == null) {
|
|
return;
|
|
}
|
|
|
|
if (renderingData.cameraData.isPreviewCamera) {
|
|
return;
|
|
}
|
|
|
|
CommandBuffer cmd;
|
|
bool releaseCommandBuffer;
|
|
// Unity 6.3+ no longer exposes RenderingData.commandBuffer outside URP, so rely on pooled buffers there (and on pre-2022.3).
|
|
|
|
#if UNITY_6000_3_OR_NEWER
|
|
cmd = CommandBufferPool.Get();
|
|
releaseCommandBuffer = true;
|
|
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
|
|
cmd = renderingData.commandBuffer;
|
|
releaseCommandBuffer = false;
|
|
#else
|
|
cmd = CommandBufferPool.Get();
|
|
releaseCommandBuffer = true;
|
|
#endif
|
|
var cameraData = renderingData.cameraData;
|
|
|
|
using (new ProfilingScope(cmd, profilingSampler)) {
|
|
if (requiresColor) {
|
|
#if UNITY_6000_3_OR_NEWER
|
|
RTHandle source = cameraData.renderer.cameraColorTargetHandle;
|
|
Blitter.BlitCameraTexture(cmd, source, copiedColor);
|
|
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
|
|
RTHandle source = passData.isBeforeTransparents
|
|
? cameraData.renderer.GetCameraColorBackBuffer(cmd)
|
|
: cameraData.renderer.cameraColorTargetHandle;
|
|
Blitter.BlitCameraTexture(cmd, source, copiedColor);
|
|
#else
|
|
RenderTargetIdentifier source = cameraData.renderer.cameraColorTarget;
|
|
cmd.Blit(source, copiedColor);
|
|
#endif
|
|
|
|
passMaterial.SetTexture(BlitTextureShaderID, copiedColor);
|
|
}
|
|
|
|
#if UNITY_6000_3_OR_NEWER
|
|
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTargetHandle);
|
|
#elif UNITY_2022_3_OR_NEWER && !UNITY_6000_3_OR_NEWER
|
|
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.GetCameraColorBackBuffer(cmd));
|
|
#else
|
|
CoreUtils.SetRenderTarget(cmd, cameraData.renderer.cameraColorTarget);
|
|
#endif
|
|
CoreUtils.DrawFullScreen(cmd, passMaterial);
|
|
context.ExecuteCommandBuffer(cmd);
|
|
|
|
if (releaseCommandBuffer) {
|
|
CommandBufferPool.Release(cmd);
|
|
} else {
|
|
cmd.Clear();
|
|
}
|
|
}
|
|
}
|
|
|
|
private class PassData {
|
|
internal Material effectMaterial;
|
|
internal bool requiresColor;
|
|
internal bool isBeforeTransparents;
|
|
public ProfilingSampler profilingSampler;
|
|
public RTHandle copiedColor;
|
|
}
|
|
|
|
#if UNITY_6000_0_OR_NEWER
|
|
private class CopyPassData {
|
|
internal TextureHandle source;
|
|
}
|
|
|
|
private class MainPassData {
|
|
internal TextureHandle source;
|
|
internal Material material;
|
|
}
|
|
#endif
|
|
} |