地块常压罐区
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

245 lines
9.5 KiB

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
#if UNITY_2023_3_OR_NEWER
using UnityEngine.Rendering.RenderGraphModule;
#endif
namespace HighlightPlus {
public class HighlightPlusRenderPassFeature : ScriptableRendererFeature {
class HighlightPass : ScriptableRenderPass {
class PassData {
public Camera camera;
#if UNITY_2022_1_OR_NEWER
public RTHandle colorTarget, depthTarget;
#else
public RenderTargetIdentifier colorTarget, depthTarget;
#endif
#if UNITY_2023_3_OR_NEWER
public TextureHandle colorTexture, depthTexture;
#endif
public bool clearStencil;
public CommandBuffer cmd;
}
readonly PassData passData = new PassData();
// far objects render first
class DistanceComparer : IComparer<HighlightEffect> {
public Vector3 camPos;
public int Compare(HighlightEffect e1, HighlightEffect e2) {
Vector3 e1Pos = e1.transform.position;
float dx1 = e1Pos.x - camPos.x;
float dy1 = e1Pos.y - camPos.y;
float dz1 = e1Pos.z - camPos.z;
float distE1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1 + e1.sortingOffset;
Vector3 e2Pos = e2.transform.position;
float dx2 = e2Pos.x - camPos.x;
float dy2 = e2Pos.y - camPos.y;
float dz2 = e2Pos.z - camPos.z;
float distE2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2 + e2.sortingOffset;
if (distE1 > distE2) return -1;
if (distE1 < distE2) return 1;
return 0;
}
}
public bool usesCameraOverlay;
ScriptableRenderer renderer;
RenderTextureDescriptor cameraTextureDescriptor;
static DistanceComparer effectDistanceComparer = new DistanceComparer();
bool clearStencil;
static int frameCount;
public void Setup(HighlightPlusRenderPassFeature passFeature, ScriptableRenderer renderer) {
this.renderPassEvent = passFeature.renderPassEvent;
this.clearStencil = passFeature.clearStencil;
this.renderer = renderer;
#if ENABLE_VR_MODULE
HighlightEffect.isVREnabled = UnityEngine.XR.XRSettings.enabled && Application.isPlaying;
#endif
}
#if UNITY_2023_3_OR_NEWER
[Obsolete]
#endif
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) {
this.cameraTextureDescriptor = cameraTextureDescriptor;
#if UNITY_2021_2_OR_NEWER
ConfigureInput(ScriptableRenderPassInput.Depth);
#endif
}
#if UNITY_2023_3_OR_NEWER
[Obsolete]
#endif
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) {
#if UNITY_2022_1_OR_NEWER
RTHandle cameraColorTarget = renderer.cameraColorTargetHandle;
RTHandle cameraDepthTarget = renderer.cameraDepthTargetHandle;
#else
RenderTargetIdentifier cameraColorTarget = renderer.cameraColorTarget;
RenderTargetIdentifier cameraDepthTarget = renderer.cameraDepthTarget;
#endif
#if !UNITY_2021_2_OR_NEWER
// In Unity 2021.2, when MSAA > 1, cameraDepthTarget is no longer cameraColorTarget
if (!usesCameraOverlay && (cameraTextureDescriptor.msaaSamples > 1 || cam.cameraType == CameraType.SceneView)) {
cameraDepthTarget = cameraColorTarget;
}
#endif
passData.clearStencil = clearStencil;
passData.camera = renderingData.cameraData.camera;
passData.colorTarget = cameraColorTarget;
passData.depthTarget = cameraDepthTarget;
CommandBuffer cmd = CommandBufferPool.Get("Highlight Plus");
cmd.Clear();
passData.cmd = cmd;
ExecutePass(passData);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}
static void ExecutePass(PassData passData) {
int count = HighlightEffect.effects.Count;
#if UNITY_EDITOR
// Safety check: in some circumstances, the render graph is executed when some components are null before being removed from the effects list
if (!Application.isPlaying) {
HighlightEffect.effects.RemoveAll( t => t == null);
count = HighlightEffect.effects.Count;
}
#endif
if (count == 0) return;
Camera cam = passData.camera;
int camLayer = 1 << cam.gameObject.layer;
CameraType camType = cam.cameraType;
if (!HighlightEffect.customSorting && ((camType == CameraType.Game && (frameCount++) % 10 == 0) || !Application.isPlaying)) {
effectDistanceComparer.camPos = cam.transform.position;
HighlightEffect.effects.Sort(effectDistanceComparer);
}
for (int k = 0; k < count; k++) {
HighlightEffect effect = HighlightEffect.effects[k];
if (!(effect.ignoreObjectVisibility || effect.isVisible)) continue;
if (!effect.isActiveAndEnabled) continue;
if (camType == CameraType.Reflection && !effect.reflectionProbes) continue;
if ((effect.camerasLayerMask & camLayer) == 0) continue;
effect.SetCommandBuffer(passData.cmd);
effect.BuildCommandBuffer(passData.camera, passData.colorTarget, passData.depthTarget, passData.clearStencil);
passData.clearStencil = false;
}
}
#if UNITY_2023_3_OR_NEWER
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData) {
using (var builder = renderGraph.AddUnsafePass<PassData>("Highlight Plus Pass RG", out var passData)) {
builder.AllowPassCulling(false);
passData.clearStencil = clearStencil;
passData.camera = frameData.Get<UniversalCameraData>().camera;
UniversalResourceData resourceData = frameData.Get<UniversalResourceData>();
passData.colorTexture = resourceData.activeColorTexture;
passData.depthTexture = resourceData.activeDepthTexture;
builder.UseTexture(resourceData.activeColorTexture, AccessFlags.ReadWrite);
builder.UseTexture(resourceData.activeDepthTexture, AccessFlags.Read);
builder.UseTexture(resourceData.cameraDepthTexture, AccessFlags.Read);
ConfigureInput(ScriptableRenderPassInput.Depth);
builder.SetRenderFunc((PassData passData, UnsafeGraphContext context) => {
CommandBuffer cmd = CommandBufferHelpers.GetNativeCommandBuffer(context.cmd);
passData.cmd = cmd;
passData.colorTarget = passData.colorTexture;
passData.depthTarget = passData.depthTexture;
ExecutePass(passData);
});
}
}
#endif
}
HighlightPass renderPass;
public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
[Tooltip("Clears stencil buffer before rendering highlight effects. This option can solve compatibility issues with shaders that also use stencil buffers.")]
public bool clearStencil;
/// <summary>
/// Makes the effects visible in Edit mode.
/// </summary>
[Tooltip("If enabled, effects will be visible also in Edit mode (when not in Play mode).")]
public bool previewInEditMode = true;
/// <summary>
/// Makes the effects visible in Edit mode.
/// </summary>
[Tooltip("If enabled, effects will be visible also in Preview camera (preview camera shown when a camera is selected in Editor).")]
public bool showInPreviewCamera = true;
public static bool installed;
public static bool showingInEditMode;
const string PREVIEW_CAMERA_NAME = "Preview Camera";
void OnDisable() {
installed = false;
}
public override void Create() {
renderPass = new HighlightPass();
}
// This method is called when setting up the renderer once per-camera.
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) {
showingInEditMode = previewInEditMode;
Camera cam = renderingData.cameraData.camera;
#if UNITY_EDITOR
if (!previewInEditMode && !Application.isPlaying) {
return;
}
if (cam.cameraType == CameraType.Preview) {
return;
}
if (!showInPreviewCamera && PREVIEW_CAMERA_NAME.Equals(cam.name)) {
return;
}
#endif
#if UNITY_2019_4_OR_NEWER
if (renderingData.cameraData.renderType == CameraRenderType.Base) {
renderPass.usesCameraOverlay = cam.GetUniversalAdditionalCameraData().cameraStack.Count > 0;
}
#endif
renderPass.Setup(this, renderer);
renderer.EnqueuePass(renderPass);
installed = true;
}
}
}