using System; using System.Collections.Generic; using UnityEngine.Rendering; namespace UnityEngine.Experimental.Rendering.HDPipeline.Internal { class ReflectionSystemInternal { static Camera s_RenderCamera = null; static HDAdditionalCameraData s_RenderCameraData; HashSet m_PlanarReflectionProbes; HashSet m_PlanarReflectionProbe_DirtyBounds; HashSet m_PlanarReflectionProbe_RequestRealtimeRender; HashSet m_PlanarReflectionProbe_RealtimeUpdate; PlanarReflectionProbe[] m_PlanarReflectionProbe_RealtimeUpdate_WorkArray; Dictionary m_PlanarReflectionProbeBounds; PlanarReflectionProbe[] m_PlanarReflectionProbesArray; BoundingSphere[] m_PlanarReflectionProbeBoundsArray; ReflectionSystemParameters m_Parameters; public ReflectionSystemInternal(ReflectionSystemParameters parameters, ReflectionSystemInternal previous) { m_Parameters = parameters; m_PlanarReflectionProbes = new HashSet(); m_PlanarReflectionProbe_DirtyBounds = new HashSet(); m_PlanarReflectionProbeBounds = new Dictionary(parameters.maxPlanarReflectionProbes); m_PlanarReflectionProbesArray = new PlanarReflectionProbe[parameters.maxPlanarReflectionProbes]; m_PlanarReflectionProbeBoundsArray = new BoundingSphere[parameters.maxPlanarReflectionProbes]; m_PlanarReflectionProbe_RequestRealtimeRender = new HashSet(); m_PlanarReflectionProbe_RealtimeUpdate = new HashSet(); m_PlanarReflectionProbe_RealtimeUpdate_WorkArray = new PlanarReflectionProbe[parameters.maxPlanarReflectionProbes]; if (previous != null) { m_PlanarReflectionProbes.UnionWith(previous.m_PlanarReflectionProbes); m_PlanarReflectionProbe_DirtyBounds.UnionWith(m_PlanarReflectionProbes); } } public void RegisterProbe(PlanarReflectionProbe planarProbe) { m_PlanarReflectionProbes.Add(planarProbe); SetProbeBoundsDirty(planarProbe); if (planarProbe.mode == ReflectionProbeMode.Realtime) { switch (planarProbe.refreshMode) { case ReflectionProbeRefreshMode.OnAwake: m_PlanarReflectionProbe_RequestRealtimeRender.Add(planarProbe); break; case ReflectionProbeRefreshMode.EveryFrame: m_PlanarReflectionProbe_RealtimeUpdate.Add(planarProbe); break; } } } public void UnregisterProbe(PlanarReflectionProbe planarProbe) { m_PlanarReflectionProbes.Remove(planarProbe); m_PlanarReflectionProbe_DirtyBounds.Remove(planarProbe); m_PlanarReflectionProbe_RequestRealtimeRender.Remove(planarProbe); m_PlanarReflectionProbe_RealtimeUpdate.Remove(planarProbe); } public void Cull(Camera camera, ReflectionProbeCullResults results) { UpdateAllPlanarReflectionProbeBounds(); var cullingGroup = new CullingGroup(); cullingGroup.targetCamera = camera; cullingGroup.SetBoundingSpheres(m_PlanarReflectionProbeBoundsArray); cullingGroup.SetBoundingSphereCount(m_PlanarReflectionProbeBounds.Count); results.CullPlanarReflectionProbes(cullingGroup, m_PlanarReflectionProbesArray); cullingGroup.Dispose(); } public void RenderAllRealtimeProbes() { // Discard disabled probes in requested render probes m_PlanarReflectionProbe_RequestRealtimeRender.IntersectWith(m_PlanarReflectionProbes); // Include all realtime probe modes m_PlanarReflectionProbe_RequestRealtimeRender.UnionWith(m_PlanarReflectionProbe_RealtimeUpdate); var length = Mathf.Min(m_PlanarReflectionProbe_RequestRealtimeRender.Count, m_PlanarReflectionProbe_RealtimeUpdate_WorkArray.Length); m_PlanarReflectionProbe_RequestRealtimeRender.CopyTo(m_PlanarReflectionProbe_RealtimeUpdate_WorkArray); m_PlanarReflectionProbe_RequestRealtimeRender.Clear(); // 1. Allocate if necessary target texture var camera = GetRenderCamera(); for (var i = 0; i < length; i++) { var probe = m_PlanarReflectionProbe_RealtimeUpdate_WorkArray[i]; var hdCamera = HDCamera.Get(camera, null, probe.frameSettings); if (!IsRealtimeTextureValid(probe.realtimeTexture, hdCamera)) { if( probe.realtimeTexture != null) probe.realtimeTexture.Release(); probe.realtimeTexture = NewRenderTarget(probe); } } // 2. Render for (var i = 0; i < length; i++) { var probe = m_PlanarReflectionProbe_RealtimeUpdate_WorkArray[i]; Render(probe, probe.realtimeTexture); } } public RenderTexture NewRenderTarget(PlanarReflectionProbe probe) { var desc = GetRenderHDCamera(probe).renderTextureDesc; desc.width = m_Parameters.planarReflectionProbeSize; desc.height = m_Parameters.planarReflectionProbeSize; desc.colorFormat = RenderTextureFormat.ARGBHalf; var rt = new RenderTexture(desc); return rt; } bool IsRealtimeTextureValid(RenderTexture renderTexture, HDCamera hdCamera) { return renderTexture != null && renderTexture.width == m_Parameters.planarReflectionProbeSize && renderTexture.height == m_Parameters.planarReflectionProbeSize && renderTexture.format == RenderTextureFormat.ARGBHalf; } public void RequestRealtimeRender(PlanarReflectionProbe probe) { m_PlanarReflectionProbe_RequestRealtimeRender.Add(probe); } public void Render(PlanarReflectionProbe probe, RenderTexture target) { var renderCamera = GetRenderHDCamera(probe); renderCamera.camera.targetTexture = target; SetupCameraForRender(renderCamera.camera, probe); renderCamera.camera.Render(); renderCamera.camera.targetTexture = null; } void SetProbeBoundsDirty(PlanarReflectionProbe planarProbe) { m_PlanarReflectionProbe_DirtyBounds.Add(planarProbe); } void UpdateAllPlanarReflectionProbeBounds() { if (m_PlanarReflectionProbe_DirtyBounds.Count > 0) { m_PlanarReflectionProbe_DirtyBounds.IntersectWith(m_PlanarReflectionProbes); foreach (var planarReflectionProbe in m_PlanarReflectionProbe_DirtyBounds) UpdatePlanarReflectionProbeBounds(planarReflectionProbe); m_PlanarReflectionProbeBounds.Values.CopyTo(m_PlanarReflectionProbeBoundsArray, 0); m_PlanarReflectionProbeBounds.Keys.CopyTo(m_PlanarReflectionProbesArray, 0); } } void UpdatePlanarReflectionProbeBounds(PlanarReflectionProbe planarReflectionProbe) { m_PlanarReflectionProbeBounds[planarReflectionProbe] = planarReflectionProbe.boundingSphere; } static void SetupCameraForRender(Camera camera, PlanarReflectionProbe probe) { camera.transform.position = probe.capturePosition; throw new NotImplementedException(); } static HDCamera GetRenderHDCamera(PlanarReflectionProbe probe) { var camera = GetRenderCamera(); probe.frameSettings.CopyTo(s_RenderCameraData.GetFrameSettings()); return HDCamera.Get(camera, null, probe.frameSettings); } static Camera GetRenderCamera() { if (s_RenderCamera == null) { s_RenderCamera = new GameObject("Probe Render Camera"). AddComponent(); s_RenderCameraData = s_RenderCamera.gameObject.AddComponent(); s_RenderCamera.gameObject.SetActive(false); } return s_RenderCamera; } } }