BITFALL/Assets/Plugins/Le Tai's Asset/TranslucentImage/Script/UniversalRP/Render Pass/TranslucentImageBlurSource.cs

294 lines
8.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using UnityEngine.Scripting.APIUpdating;
using Debug = UnityEngine.Debug;
#if URP12_OR_NEWER
#if UNITY_2022_1_OR_NEWER
using RTH = UnityEngine.Rendering.RTHandle;
#else
using RTH = UnityEngine.Rendering.Universal.RenderTargetHandle;
#endif
#endif
[assembly:InternalsVisibleTo("LeTai.TranslucentImage.UniversalRP.Editor")]
namespace LeTai.Asset.TranslucentImage.UniversalRP
{
class URPRendererInternal
{
#if URP12_OR_NEWER
ScriptableRenderer renderer;
Func<RTH> getBackBufferDelegate;
Func<RTH> getAfterPostColorDelegate;
#endif
public void CacheRenderer(ScriptableRenderer renderer)
{
#if URP12_OR_NEWER
if (this.renderer == renderer) return;
this.renderer = renderer;
#if UNITY_2022_1_OR_NEWER
const string backBufferMethodName = "PeekBackBuffer";
#else
const string backBufferMethodName = "GetBackBuffer";
#endif
if (renderer is UniversalRenderer ur)
{
var cbs = ur.GetType()
.GetField("m_ColorBufferSystem",
BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(ur);
var gbb = cbs.GetType()
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.First(m => m.Name == backBufferMethodName && m.GetParameters().Length == 0);
getBackBufferDelegate = (Func<RTH>)gbb.CreateDelegate(typeof(Func<RTH>), cbs);
}
else
{
getAfterPostColorDelegate = (Func<RTH>)renderer.GetType()
.GetProperty("afterPostProcessColorHandle",
BindingFlags.NonPublic | BindingFlags.Instance)
.GetGetMethod(true)
.CreateDelegate(typeof(Func<RTH>), renderer);
}
#endif
}
#if URP12_OR_NEWER
public RenderTargetIdentifier GetBackBuffer()
{
Debug.Assert(getBackBufferDelegate != null);
var r = getBackBufferDelegate.Invoke();
#if UNITY_2022_1_OR_NEWER
return r.nameID;
#else
return r.Identifier();
#endif
}
public RenderTargetIdentifier GetAfterPostColor()
{
Debug.Assert(getAfterPostColorDelegate != null);
var r = getAfterPostColorDelegate.Invoke();
#if UNITY_2022_1_OR_NEWER
return r.nameID;
#else
return r.Identifier();
#endif
}
#endif
}
public enum RenderOrder
{
AfterPostProcessing,
BeforePostProcessing,
}
[MovedFrom("LeTai.Asset.TranslucentImage.LWRP")]
public class TranslucentImageBlurSource : ScriptableRendererFeature
{
#if URP12_OR_NEWER
public RenderOrder renderOrder = RenderOrder.AfterPostProcessing;
#endif
public BlitMode blitMode = BlitMode.Procedural;
readonly Dictionary<Camera, TranslucentImageSource> tisCache = new Dictionary<Camera, TranslucentImageSource>();
readonly Dictionary<Camera, Camera> baseCameraCache = new Dictionary<Camera, Camera>();
URPRendererInternal urpRendererInternal;
TranslucentImageBlurRenderPass pass;
IBlurAlgorithm blurAlgorithm;
internal RendererType rendererType;
BlitMode GetActiveBlitMode()
{
#if !UNITY_2023_1_OR_NEWER
if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.OpenGLES2)
return BlitMode.Triangle;
#endif
return blitMode;
}
/// <summary>
/// When adding new Translucent Image Source to existing Camera at run time, the new Source must be registered here
/// </summary>
/// <param name="source"></param>
public void RegisterSource(TranslucentImageSource source)
{
tisCache[source.GetComponent<Camera>()] = source;
}
public override void Create()
{
ShaderId.Init(32); //hack for now
blurAlgorithm = new ScalableBlur();
urpRendererInternal = new URPRendererInternal();
// ReSharper disable once JoinDeclarationAndInitializer
RenderPassEvent renderPassEvent;
#if URP12_OR_NEWER
renderPassEvent = renderOrder == RenderOrder.BeforePostProcessing
? RenderPassEvent.BeforeRenderingPostProcessing
: RenderPassEvent.AfterRenderingPostProcessing;
#else
renderPassEvent = RenderPassEvent.AfterRendering;
#endif
pass = new TranslucentImageBlurRenderPass(urpRendererInternal) {
renderPassEvent = renderPassEvent
};
tisCache.Clear();
}
void Setup(ScriptableRenderer renderer, in RenderingData renderingData)
{
var cameraData = renderingData.cameraData;
var tis = GetTIS(cameraData.camera);
if (tis == null)
return;
urpRendererInternal.CacheRenderer(renderer);
#if UNITY_2021_3_OR_NEWER
if (renderer is UniversalRenderer)
#else
if (renderer is ForwardRenderer)
#endif
{
rendererType = RendererType.Universal;
}
else
{
rendererType = RendererType.Renderer2D;
}
#if UNITY_BUGGED_HAS_PASSES_AFTER_POSTPROCESS
bool applyFinalPostProcessing = renderingData.postProcessingEnabled
&& cameraData.resolveFinalTarget
&& (cameraData.antialiasing == AntialiasingMode.FastApproximateAntialiasing
);
pass.renderPassEvent = applyFinalPostProcessing ? RenderPassEvent.AfterRenderingPostProcessing : RenderPassEvent.AfterRendering;
#endif
var passData = new TISPassData {
rendererType = rendererType,
#if UNITY_2022_1_OR_NEWER
cameraColorTarget = renderer.cameraColorTargetHandle,
#else
cameraColorTarget = renderer.cameraColorTarget,
#endif
blurAlgorithm = blurAlgorithm,
#if URP12_OR_NEWER
renderOrder = renderOrder,
#endif
blitMode = GetActiveBlitMode(),
blurSource = tis,
isPreviewing = tis.preview,
};
pass.Setup(passData);
}
#if UNITY_2022_1_OR_NEWER
public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
{
Setup(renderer, renderingData);
}
#endif
readonly FieldInfo cameraDataPixelRectField = typeof(CameraData).GetField("pixelRect", BindingFlags.Instance | BindingFlags.NonPublic);
public Rect GetPixelSize(CameraData cameraData)
{
if (cameraData.renderType == CameraRenderType.Base)
return cameraData.camera.pixelRect;
if (cameraDataPixelRectField == null)
Debug.LogError("CameraData.pixelRect does not exists in this version of URP. Please report a bug.");
return (Rect)cameraDataPixelRectField.GetValue(cameraData);
}
public override void AddRenderPasses(
ScriptableRenderer renderer,
ref RenderingData renderingData
)
{
#if !UNITY_2022_1_OR_NEWER
Setup(renderer, renderingData);
#endif
var cameraData = renderingData.cameraData;
var camera = renderingData.cameraData.camera;
var tis = GetTIS(camera);
if (tis == null || !tis.shouldUpdateBlur())
return;
tis.CamRectOverride = Rect.zero;
if (cameraData.renderType == CameraRenderType.Overlay)
{
var baseCam = GetBaseCamera(camera);
if (baseCam)
tis.CamRectOverride = baseCam.rect;
}
var camPixelSize = GetPixelSize(cameraData).size;
tis.OnBeforeBlur(Vector2Int.RoundToInt(camPixelSize));
blurAlgorithm.Init(tis.BlurConfig, GetActiveBlitMode());
renderer.EnqueuePass(pass);
}
TranslucentImageSource GetTIS(Camera camera)
{
if (!tisCache.ContainsKey(camera))
{
tisCache.Add(camera, camera.GetComponent<TranslucentImageSource>());
}
return tisCache[camera];
}
Camera GetBaseCamera(Camera camera)
{
if (!baseCameraCache.ContainsKey(camera))
{
Camera baseCamera = null;
foreach (var uacd in Shims.FindObjectsOfType<UniversalAdditionalCameraData>())
{
if (uacd.renderType != CameraRenderType.Base) continue;
if (uacd.cameraStack == null) continue;
if (!uacd.cameraStack.Contains(camera)) continue;
baseCamera = uacd.GetComponent<Camera>();
}
baseCameraCache.Add(camera, baseCamera);
}
return baseCameraCache[camera];
}
}
}