226 lines
8.4 KiB
C#
226 lines
8.4 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
namespace VLB
|
|
{
|
|
[ExecuteInEditMode]
|
|
[HelpURL(Consts.Help.SD.UrlDynamicOcclusionDepthBuffer)]
|
|
public class DynamicOcclusionDepthBuffer : DynamicOcclusionAbstractBase
|
|
{
|
|
public new const string ClassName = "DynamicOcclusionDepthBuffer";
|
|
|
|
/// <summary>
|
|
/// The beam can only be occluded by objects located on the layers matching this mask.
|
|
/// It's very important to set it as restrictive as possible (checking only the layers which are necessary)
|
|
/// to perform a more efficient process in order to increase the performance.
|
|
/// It should NOT include the layer on which the beams are generated.
|
|
/// </summary>
|
|
public LayerMask layerMask = Consts.DynOcclusion.LayerMaskDefault;
|
|
|
|
/// <summary>
|
|
/// Whether or not the virtual camera will use occlusion culling during rendering from the beam's POV.
|
|
/// </summary>
|
|
public bool useOcclusionCulling = Consts.DynOcclusion.DepthBufferOcclusionCullingDefault;
|
|
|
|
/// <summary>
|
|
/// Controls how large the depth texture captured by the virtual camera is.
|
|
/// The lower the resolution, the better the performance, but the less accurate the rendering.
|
|
/// </summary>
|
|
public int depthMapResolution = Consts.DynOcclusion.DepthBufferDepthMapResolutionDefault;
|
|
|
|
/// <summary>
|
|
/// Fade out the beam before the occlusion surface in order to soften the transition.
|
|
/// </summary>
|
|
public float fadeDistanceToSurface = Consts.DynOcclusion.DepthBufferFadeDistanceToSurfaceDefault;
|
|
|
|
|
|
protected override string GetShaderKeyword() { return ShaderKeywords.SD.OcclusionDepthTexture; }
|
|
protected override MaterialManager.SD.DynamicOcclusion GetDynamicOcclusionMode() { return MaterialManager.SD.DynamicOcclusion.DepthTexture; }
|
|
|
|
Camera m_DepthCamera = null;
|
|
bool m_NeedToUpdateOcclusionNextFrame = false;
|
|
|
|
void ProcessOcclusionInternal()
|
|
{
|
|
UpdateDepthCameraPropertiesAccordingToBeam();
|
|
m_DepthCamera.Render();
|
|
}
|
|
|
|
protected override bool OnProcessOcclusion(ProcessOcclusionSource source)
|
|
{
|
|
Debug.Assert(m_Master && m_DepthCamera);
|
|
|
|
if (SRPHelper.IsUsingCustomRenderPipeline()) // Recursive rendering is not supported on SRP
|
|
m_NeedToUpdateOcclusionNextFrame = true;
|
|
else
|
|
ProcessOcclusionInternal();
|
|
|
|
return true;
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (m_NeedToUpdateOcclusionNextFrame && m_Master && m_DepthCamera
|
|
&& Time.frameCount > 1) // fix NullReferenceException in UnityEngine.Rendering.Universal.Internal.CopyDepthPass.Execute when using SRP
|
|
{
|
|
ProcessOcclusionInternal();
|
|
m_NeedToUpdateOcclusionNextFrame = false;
|
|
}
|
|
}
|
|
|
|
void UpdateDepthCameraPropertiesAccordingToBeam()
|
|
{
|
|
Debug.Assert(m_Master);
|
|
|
|
Utils.SetupDepthCamera(m_DepthCamera
|
|
, m_Master.coneApexOffsetZ, m_Master.maxGeometryDistance, m_Master.coneRadiusStart, m_Master.coneRadiusEnd
|
|
, m_Master.beamLocalForward, m_Master.GetLossyScale(), m_Master.IsScalable(), m_Master.beamInternalLocalRotation
|
|
, true);
|
|
}
|
|
|
|
public bool HasLayerMaskIssues()
|
|
{
|
|
if(Config.Instance.geometryOverrideLayer)
|
|
{
|
|
int layerBit = 1 << Config.Instance.geometryLayerID;
|
|
return ((layerMask.value & layerBit) == layerBit);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected override void OnValidateProperties()
|
|
{
|
|
base.OnValidateProperties();
|
|
depthMapResolution = Mathf.Clamp(Mathf.NextPowerOfTwo(depthMapResolution), 8, 2048);
|
|
fadeDistanceToSurface = Mathf.Max(fadeDistanceToSurface, 0f);
|
|
}
|
|
|
|
void InstantiateOrActivateDepthCamera()
|
|
{
|
|
if (m_DepthCamera != null)
|
|
{
|
|
m_DepthCamera.gameObject.SetActive(true); // active it in case it has been disabled by OnDisable()
|
|
}
|
|
else
|
|
{
|
|
// delete old depth cameras when duplicating the GAO
|
|
gameObject.ForeachComponentsInDirectChildrenOnly<Camera>(cam => DestroyImmediate(cam.gameObject), true);
|
|
|
|
m_DepthCamera = Utils.NewWithComponent<Camera>("Depth Camera");
|
|
|
|
if (m_DepthCamera && m_Master)
|
|
{
|
|
m_DepthCamera.enabled = false;
|
|
m_DepthCamera.cullingMask = layerMask;
|
|
m_DepthCamera.clearFlags = CameraClearFlags.Depth;
|
|
m_DepthCamera.depthTextureMode = DepthTextureMode.Depth;
|
|
m_DepthCamera.renderingPath = RenderingPath.VertexLit; // faster
|
|
m_DepthCamera.useOcclusionCulling = useOcclusionCulling;
|
|
m_DepthCamera.gameObject.hideFlags = Consts.Internal.ProceduralObjectsHideFlags;
|
|
m_DepthCamera.transform.SetParent(transform, false);
|
|
Config.Instance.SetURPScriptableRendererIndexToDepthCamera(m_DepthCamera);
|
|
|
|
var rt = new RenderTexture(depthMapResolution, depthMapResolution, 16, RenderTextureFormat.Depth);
|
|
m_DepthCamera.targetTexture = rt;
|
|
|
|
UpdateDepthCameraPropertiesAccordingToBeam();
|
|
|
|
#if UNITY_EDITOR
|
|
UnityEditor.GameObjectUtility.SetStaticEditorFlags(m_DepthCamera.gameObject, m_Master.GetStaticEditorFlagsForSubObjects());
|
|
m_DepthCamera.gameObject.SetSameSceneVisibilityStatesThan(m_Master.gameObject);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnEnablePostValidate()
|
|
{
|
|
InstantiateOrActivateDepthCamera();
|
|
}
|
|
|
|
protected override void OnDisable()
|
|
{
|
|
base.OnDisable();
|
|
if (m_DepthCamera) m_DepthCamera.gameObject.SetActive(false);
|
|
}
|
|
|
|
protected override void Awake()
|
|
{
|
|
base.Awake();
|
|
|
|
#if UNITY_EDITOR
|
|
MarkMaterialAsDirty();
|
|
#endif
|
|
}
|
|
|
|
protected override void OnDestroy()
|
|
{
|
|
base.OnDestroy();
|
|
|
|
DestroyDepthCamera();
|
|
|
|
#if UNITY_EDITOR
|
|
MarkMaterialAsDirty();
|
|
#endif
|
|
}
|
|
|
|
void DestroyDepthCamera()
|
|
{
|
|
if (m_DepthCamera)
|
|
{
|
|
if (m_DepthCamera.targetTexture)
|
|
{
|
|
m_DepthCamera.targetTexture.Release();
|
|
DestroyImmediate(m_DepthCamera.targetTexture);
|
|
m_DepthCamera.targetTexture = null;
|
|
}
|
|
|
|
DestroyImmediate(m_DepthCamera.gameObject); // Make sure to delete the GAO
|
|
m_DepthCamera = null;
|
|
}
|
|
}
|
|
|
|
protected override void OnModifyMaterialCallback(MaterialModifier.Interface owner)
|
|
{
|
|
Debug.Assert(owner != null);
|
|
owner.SetMaterialProp(ShaderProperties.SD.DynamicOcclusionDepthTexture, m_DepthCamera.targetTexture);
|
|
var scale = m_Master.GetLossyScale();
|
|
owner.SetMaterialProp(ShaderProperties.SD.DynamicOcclusionDepthProps, new Vector4(Mathf.Sign(scale.x) * Mathf.Sign(scale.z), Mathf.Sign(scale.y), fadeDistanceToSurface, m_DepthCamera.orthographic ? 0f : 1f));
|
|
}
|
|
|
|
#if UNITY_EDITOR
|
|
bool m_NeedToReinstantiateDepthCamera = false;
|
|
|
|
void MarkMaterialAsDirty()
|
|
{
|
|
// when adding/removing this component in editor, we might need to switch from a GPU Instanced material to a custom one,
|
|
// since this feature doesn't support GPU Instancing
|
|
if (!Application.isPlaying)
|
|
m_Master._EditorSetBeamGeomDirty();
|
|
}
|
|
|
|
protected override void OnValidate()
|
|
{
|
|
base.OnValidate();
|
|
m_NeedToReinstantiateDepthCamera = true;
|
|
}
|
|
|
|
void LateUpdate()
|
|
{
|
|
if (!Application.isPlaying)
|
|
{
|
|
if (m_NeedToReinstantiateDepthCamera)
|
|
{
|
|
DestroyDepthCamera();
|
|
InstantiateOrActivateDepthCamera();
|
|
m_NeedToReinstantiateDepthCamera = false;
|
|
}
|
|
|
|
if(m_Master && m_Master.enabled)
|
|
ProcessOcclusion(ProcessOcclusionSource.EditorUpdate);
|
|
}
|
|
}
|
|
#endif // UNITY_EDITOR
|
|
}
|
|
}
|