private PortalRenderTexturePoolItem AllocatePortalRenderTexture(bool used = false) { RenderTexture renderTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.DefaultHDR); renderTexture.Create(); PortalRenderTexturePoolItem item = new PortalRenderTexturePoolItem(renderTexture, used); portalRenderTexturesPool.Add(item); return(item); }
/// <summary> /// Renders a portal, with recursions. /// The portal will follow the manually-defined portal visibility graph up to a certain number of recursions, depth-first. /// It will then render the innermost portals first, followed by outer ones, all the way until the original one is rendered. /// GameManager.instance.mainCamera MUST be defined before calling this function. /// </summary> /// <param name="portalToRender">Which portal are we rendering?</param> /// <param name="refPosition">The reference camera's position</param> /// <param name="refRotation">The reference camera's rotation</param> /// <param name="temporaryRenderTexturePoolItem">Handle to the temporay render texture pool item used to render the portal. CALLEE MUST RELEASE AFTER USE!!!</param> /// <param name="originalTexture">Handle to the original texture on the portal. Reset material back to this after use</param> /// <param name="currentRecursion">How deep are we?</param> /// <param name="overrideMaxRecursion">Override the global GameManager maxRecursion value</param> public static void RenderViewThroughRecursive( Portal portalToRender, Vector3 refPosition, Quaternion refRotation, out PortalRenderTexturePoolItem temporaryRenderTexturePoolItem, out Texture originalTexture, out int renderCount, int currentRecursion = 0, int?overrideMaxRecursion = null) { renderCount = 1; // ======= // RECURSE // ======= // Override max recursions int maxRecursions = overrideMaxRecursion.HasValue ? overrideMaxRecursion.Value : GameManager.instance.portalMaxRecursion; // Calculate target view through camera position Vector3 targetRefPosition = TransformPositionBetweenPortals(portalToRender, portalToRender.target, refPosition); Quaternion targetRefRotation = TransformRotationBetweenPortals(portalToRender, portalToRender.target, refRotation); // Store visible portal resources to release and reset (see function description for details) List <VisiblePortalResources> visiblePortalResourcesList = new List <VisiblePortalResources>(); // Recurse if not at limit if (currentRecursion < maxRecursions) { foreach (Portal visiblePortal in portalToRender.target.viewThroughFromVisiblePortals) { RenderViewThroughRecursive( visiblePortal, targetRefPosition, targetRefRotation, out PortalRenderTexturePoolItem visiblePortalTemporaryRenderTexturePoolItem, out Texture visiblePortalOriginalTexture, out int visiblePortalRenderCount, currentRecursion + 1, overrideMaxRecursion); visiblePortalResourcesList.Add( new VisiblePortalResources(visiblePortal, visiblePortalTemporaryRenderTexturePoolItem, visiblePortalOriginalTexture)); renderCount += visiblePortalRenderCount; } } // ====== // RENDER // ====== // Get new temporary render texture and set to portal's material // Will be released by CALLEE, not by this function. This is so that the callee can use the render texture // for their own purposes, such as a Render() or a main camera render, before releasing it. temporaryRenderTexturePoolItem = GameManager.instance.GetPortalRenderTexture(); originalTexture = portalToRender.viewThroughToMaterial.GetTexture("_MainTex"); portalToRender.viewThroughToMaterial.SetTexture("_MainTex", temporaryRenderTexturePoolItem.renderTexture); // Use portal camera Camera portalCamera = GameManager.instance.portalCamera; portalCamera.targetTexture = temporaryRenderTexturePoolItem.renderTexture; // Set target camera transform portalCamera.transform.SetPositionAndRotation(targetRefPosition, targetRefRotation); // Convert target portal's plane to camera space (relative to target camera) // Explanation: https://danielilett.com/2019-12-18-tut4-3-matrix-matching/ Vector4 targetViewThroughPlaneCameraSpace = Matrix4x4.Transpose(Matrix4x4.Inverse(portalCamera.worldToCameraMatrix)) * portalToRender.target.viewThroughFromPlane; // Set target camera projection matrix to clip walls between target portal and target camera // Portal camera will inherit FOV and near/clip values from main camera. portalCamera.projectionMatrix = GameManager.instance.mainCamera.CalculateObliqueMatrix(targetViewThroughPlaneCameraSpace); // Render portal camera to target texture portalCamera.Render(); // ================= // RELEASE AND RESET // ================= foreach (VisiblePortalResources resources in visiblePortalResourcesList) { // Reset to original texture // So that it will remain correct if the visible portal is still expecting to be rendered // on another camera but has already rendered its texture. Originally the texture may be overriden by other renders. resources.visiblePortal.viewThroughToMaterial.SetTexture("_MainTex", resources.originalTexture); // Release temp render texture GameManager.instance.ReleasePortalRenderTexture(resources.portalRenderTexturePoolItem); } }
/// <summary> /// Releases the PortalRenderTexturePoolItem. /// </summary> /// <param name="item">The PortalRenderTexturePoolItem.</param> public void ReleasePortalRenderTexture(PortalRenderTexturePoolItem item) { item.used = false; }
public VisiblePortalResources(Portal visiblePortal, PortalRenderTexturePoolItem temporaryRenderTexture, Texture originalTexture) { this.visiblePortal = visiblePortal; this.portalRenderTexturePoolItem = temporaryRenderTexture; this.originalTexture = originalTexture; }