Files
2026-03-04 10:03:45 +08:00

145 lines
4.2 KiB
C#

using System;
using UnityEngine;
using UnityEngine.Rendering;
namespace PlanarReflections3
{
[ExecuteInEditMode]
public class PlanarReflectionsCaster : MonoBehaviour
{
public PlanarReflectionsRenderer castFromRenderer;
public bool[] castDepth = new bool[0];
public bool[] castReflection = new bool[0];
[SerializeField]
protected bool SRPMode;
private Renderer rend;
private Material[] sharedMats = new Material[0];
private MaterialPropertyBlock mBlock;
public bool isSRP => SRPMode;
public void OnEnable()
{
rend = GetComponent<Renderer>();
if (castDepth.Length != GetComponent<Renderer>().sharedMaterials.Length)
{
castDepth = new bool[GetComponent<Renderer>().sharedMaterials.Length];
}
if (castReflection.Length != castDepth.Length)
{
castReflection = new bool[castDepth.Length];
}
if (GraphicsSettings.renderPipelineAsset != null)
{
SRPMode = true;
}
else
{
SRPMode = false;
}
if (SRPMode)
{
RenderPipelineManager.beginCameraRendering -= CheckSRPVisibility;
RenderPipelineManager.beginCameraRendering += CheckSRPVisibility;
base.gameObject.layer = 4;
}
else
{
Camera.onPreRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPreRender, new Camera.CameraCallback(CheckVisibility));
Camera.onPreRender = (Camera.CameraCallback)Delegate.Combine(Camera.onPreRender, new Camera.CameraCallback(CheckVisibility));
}
}
public void CheckSRPVisibility(ScriptableRenderContext context, Camera srcCamera)
{
CheckVisibility(srcCamera);
for (int i = 0; i < castReflection.Length; i++)
{
MaterialPropertyBlock block = mBlock;
GetPropertyBlock(ref block, i);
block.SetTexture("_ReflectionTex", ((bool)castFromRenderer.ReflectionTex && castReflection[i] && srcCamera.cameraType != CameraType.Reflection && !srcCamera.name.Contains("PLANAR3_")) ? ((Texture)castFromRenderer.ReflectionTex) : ((Texture)Texture2D.blackTexture));
block.SetTexture("_ReflectionDepth", ((bool)castFromRenderer.ReflectionDepth && castDepth[i] && srcCamera.cameraType != CameraType.Reflection && !srcCamera.name.Contains("PLANAR3_")) ? ((Texture)castFromRenderer.ReflectionDepth) : ((Texture)Texture2D.whiteTexture));
SetPropertyBlock(block, i);
}
}
public void CheckVisibility(Camera cam)
{
if (mBlock == null)
{
mBlock = new MaterialPropertyBlock();
}
if ((bool)castFromRenderer && rend.isVisible)
{
castFromRenderer.castersActive = true;
for (int i = 0; i < castReflection.Length; i++)
{
MaterialPropertyBlock block = mBlock;
GetPropertyBlock(ref block, i);
block.SetTexture("_ReflectionTex", ((bool)castFromRenderer.ReflectionTex && castReflection[i] && cam.cameraType != CameraType.Reflection) ? ((Texture)castFromRenderer.ReflectionTex) : ((Texture)Texture2D.blackTexture));
block.SetTexture("_ReflectionDepth", ((bool)castFromRenderer.ReflectionDepth && castDepth[i] && cam.cameraType != CameraType.Reflection) ? ((Texture)castFromRenderer.ReflectionDepth) : ((Texture)Texture2D.whiteTexture));
SetPropertyBlock(block, i);
}
}
}
public void OnDisable()
{
if (SRPMode)
{
RenderPipelineManager.beginCameraRendering -= CheckSRPVisibility;
}
else
{
Camera.onPreRender = (Camera.CameraCallback)Delegate.Remove(Camera.onPreRender, new Camera.CameraCallback(CheckVisibility));
}
}
public void Update()
{
if ((bool)castFromRenderer)
{
_ = rend.isVisible;
}
}
private void GetPropertyBlock(ref MaterialPropertyBlock block, int index)
{
if (!rend)
{
rend = GetComponent<Renderer>();
}
if ((bool)rend && sharedMats.Length < 1)
{
sharedMats = rend.sharedMaterials;
}
if (block != null && index >= 0 && (bool)rend && sharedMats.Length > index)
{
rend.GetPropertyBlock(block, index);
}
}
private void SetPropertyBlock(MaterialPropertyBlock block, int index)
{
if (!rend)
{
rend = GetComponent<Renderer>();
}
if ((bool)rend && sharedMats.Length < 1)
{
sharedMats = rend.sharedMaterials;
}
if (block != null && index >= 0 && (bool)rend && sharedMats.Length > index)
{
rend.SetPropertyBlock(block, index);
}
}
}
}