void CreateRenderTexture(int width, int height) { // Not sure why but it seems sometimes the Portals don't get OnDisable called when scene unloaded if (this == null) { OnDisable(); return; } debug.Log($"Creating render textures for new resolution {width}x{height}"); if (internalRenderTexturesCopy != null && (internalRenderTexturesCopy.mainTexture != null || internalRenderTexturesCopy.depthNormalsTexture != null)) { internalRenderTexturesCopy.Release(); } internalRenderTexturesCopy = RecursiveTextures.CreateTextures(ID); SetTexturesOnMaterial(); }
RecursiveTextures RenderPortalDepth(int depth, Portal portal, Rect[] portalScreenBounds, string tree) { if (depth == MaxDepth || renderSteps >= MaxRenderSteps) { Debug.LogError($"At max depth or max render steps:\nDepth: {depth}/{MaxDepth}\nRenderSteps: {renderSteps}/{MaxRenderSteps}"); return(null); } var index = renderSteps; renderSteps++; SetupPortalCameraForPortal(portal, portal.otherPortal, depth); CameraSettings modifiedCamSettings = new CameraSettings { camPosition = portalCamera.transform.position, camRotation = portalCamera.transform.rotation, camProjectionMatrix = portalCamera.projectionMatrix, edgeColors = new EDColors(portalCameraEdgeDetection) }; // Key == Visible Portal, Value == visible portal screen bounds Dictionary <Portal, Rect[]> visiblePortals = GetVisiblePortalsAndTheirScreenBounds(portal, portalScreenBounds); // Key == Visible Portal, Value == RecursiveTextures Dictionary <Portal, RecursiveTextures> visiblePortalTextures = new Dictionary <Portal, RecursiveTextures>(); debug.Log($"Index (Depth): {index} ({depth})\nPortal:{portal.name}\nNumVisible:{visiblePortals.Count}\nPortalCamPos:{portalCamera.transform.position}\nTree:{tree}\nScreenBounds:{string.Join(", ", portalScreenBounds)}"); foreach (var visiblePortalTuple in visiblePortals) { Portal visiblePortal = visiblePortalTuple.Key; if (ShouldRenderRecursively(depth, portal, visiblePortal)) { string nextTree = tree + ", " + visiblePortal.name; Rect[] visiblePortalRects = visiblePortalTuple.Value; Rect[] nextPortalBounds = IntersectionOfBounds(portalScreenBounds, visiblePortalRects); // Remember state visiblePortalTextures[visiblePortal] = RenderPortalDepth(depth + 1, visiblePortal, nextPortalBounds, nextTree); } else { visiblePortal.DefaultMaterial(); } // RESTORE STATE SetCameraSettings(portalCamera, modifiedCamSettings); } // RESTORE STATE foreach (var visiblePortalKeyVal in visiblePortals) { Portal visiblePortal = visiblePortalKeyVal.Key; if (ShouldRenderRecursively(depth, portal, visiblePortal)) { RecursiveTextures textures = visiblePortalTextures[visiblePortal]; // Restore the RenderTextures that were in use at this stage visiblePortal.SetTexture(textures.mainTexture); visiblePortal.SetDepthNormalsTexture(textures.depthNormalsTexture); } else { visiblePortal.DefaultMaterial(); } } SetCameraSettings(portalCamera, modifiedCamSettings); while (renderStepTextures.Count <= index) { renderStepTextures.Add(RecursiveTextures.CreateTextures($"VirtualPortalCamera_{index}")); } List <PillarDimensionObject> allRelevantPillarDimensionObjects = PillarDimensionObject.allPillarDimensionObjects .Where(dimensionObj => dimensionObj.IsVisibleFrom(portalCamera)) .ToList(); // Portals with PillarDimensionObjects are treated specially in that the effective pillar // dimension is set to the out portal's dimension before rendering PillarDimensionObject portalDimensionObj = (portal?.otherPortal?.dimensionObject is PillarDimensionObject pillarDimensionObject) ? pillarDimensionObject : null; DimensionPillar activePillar = portalDimensionObj?.activePillar; if (portalDimensionObj != null && activePillar != null) { activePillar.dimensionWall.UpdateStateForCamera(portalCamera); foreach (PillarDimensionObject dimensionObject in allRelevantPillarDimensionObjects) { if (dimensionObject == portalDimensionObj) { continue; } dimensionObject.UpdateStateForCamera(portalCamera, portalDimensionObj.Dimension); } } // RENDER RenderDepthNormalsToPortal(portal, index); RenderVisibilityMaskTexture(portal, modifiedCamSettings); RenderPortalMaskTexture(modifiedCamSettings); if (DEBUG) { while (portalMaskTextures.Count <= index) { portalMaskTextures.Add(new RenderTexture(SuperspectiveScreen.currentWidth, SuperspectiveScreen.currentHeight, 24, SuperspectiveScreen.instance.portalMaskCamera.targetTexture.format)); } Graphics.CopyTexture(SuperspectiveScreen.instance.portalMaskCamera.targetTexture, portalMaskTextures[index]); } debug.Log($"Rendering: {index} to {portal.name}'s RenderTexture, depth: {depth}"); portalCamera.targetTexture = renderStepTextures[index].mainTexture; portalCamera.Render(); portal.SetTexture(renderStepTextures[index].mainTexture); // Restore previous DimensionObject state if (activePillar != null) { activePillar.dimensionWall.UpdateStateForCamera(mainCamera); foreach (PillarDimensionObject dimensionObject in allRelevantPillarDimensionObjects) { if (dimensionObject == portalDimensionObj) { continue; } dimensionObject.UpdateStateForCamera(mainCamera, activePillar.curDimension); } } return(renderStepTextures[index]); }