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(); if (castDepth.Length != GetComponent().sharedMaterials.Length) { castDepth = new bool[GetComponent().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(); } 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(); } if ((bool)rend && sharedMats.Length < 1) { sharedMats = rend.sharedMaterials; } if (block != null && index >= 0 && (bool)rend && sharedMats.Length > index) { rend.SetPropertyBlock(block, index); } } } }