### Initialize Portal Rendering System (C#) Source: https://context7.com/daniel-ilett/portals-urp/llms.txt This C# script initializes the dual-portal rendering system by creating render textures, assigning them to portal materials, and subscribing to the camera rendering event. It requires Unity with URP. ```C# using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class DualPortalSetup : MonoBehaviour { [SerializeField] private Portal leftPortal; [SerializeField] private Portal rightPortal; [SerializeField] private Camera portalRenderCamera; [SerializeField] private int renderIterations = 7; private RenderTexture leftPortalTexture; private RenderTexture rightPortalTexture; private Camera mainCamera; void Awake() { mainCamera = GetComponent(); // Create render textures for each portal leftPortalTexture = new RenderTexture( Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32 ); rightPortalTexture = new RenderTexture( Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32 ); // Assign textures to portal materials leftPortal.Renderer.material.mainTexture = leftPortalTexture; rightPortal.Renderer.material.mainTexture = rightPortalTexture; Debug.Log("Portal rendering system initialized"); } void OnEnable() { RenderPipelineManager.beginCameraRendering += RenderPortals; } void OnDisable() { RenderPipelineManager.beginCameraRendering -= RenderPortals; } void RenderPortals(ScriptableRenderContext context, Camera camera) { if (camera != mainCamera) return; // Only render portals if both are placed if (!leftPortal.IsPlaced || !rightPortal.IsPlaced) return; // Render left portal if visible if (leftPortal.Renderer.isVisible) { portalRenderCamera.targetTexture = leftPortalTexture; for (int i = renderIterations - 1; i >= 0; i--) { RenderPortalIteration(context, leftPortal, rightPortal, i); } } // Render right portal if visible if (rightPortal.Renderer.isVisible) { portalRenderCamera.targetTexture = rightPortalTexture; for (int i = renderIterations - 1; i >= 0; i--) { RenderPortalIteration(context, rightPortal, leftPortal, i); } } } void RenderPortalIteration(ScriptableRenderContext context, Portal inPortal, Portal outPortal, int iteration) { // Copy main camera transform portalRenderCamera.transform.position = mainCamera.transform.position; portalRenderCamera.transform.rotation = mainCamera.transform.rotation; // Apply portal transformations for (int i = 0; i <= iteration; i++) { Vector3 relativePos = inPortal.transform.InverseTransformPoint(portalRenderCamera.transform.position); relativePos = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativePos; portalRenderCamera.transform.position = outPortal.transform.TransformPoint(relativePos); Quaternion relativeRot = Quaternion.Inverse(inPortal.transform.rotation) * portalRenderCamera.transform.rotation; relativeRot = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativeRot; portalRenderCamera.transform.rotation = outPortal.transform.rotation * relativeRot; } // Set oblique projection Plane clipPlane = new Plane(-outPortal.transform.forward, outPortal.transform.position); Vector4 clipPlaneWorld = new Vector4(clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.distance); Vector4 clipPlaneCamera = Matrix4x4.Transpose(Matrix4x4.Inverse(portalRenderCamera.worldToCameraMatrix)) * clipPlaneWorld; portalRenderCamera.projectionMatrix = mainCamera.CalculateObliqueMatrix(clipPlaneCamera); UniversalRenderPipeline.RenderSingleCamera(context, portalRenderCamera); } } ``` -------------------------------- ### Initialize Portal Transition with Visual Clone Source: https://context7.com/daniel-ilett/portals-urp/llms.txt Sets up a visual clone for objects entering a portal to ensure visual continuity during traversal. It also configures collision ignoring with the portal wall. The script depends on Unity's physics system and requires a Collider component. ```csharp using UnityEngine; public class PortalTransitionManager : MonoBehaviour { private GameObject visualClone; private Portal entryPortal; private Portal exitPortal; private Collider objectCollider; private int portalCount = 0; void Start() { objectCollider = GetComponent(); // Create visual clone for portal transitions visualClone = new GameObject("Portal Clone"); visualClone.SetActive(false); MeshFilter cloneMesh = visualClone.AddComponent(); MeshRenderer cloneRenderer = visualClone.AddComponent(); cloneMesh.mesh = GetComponent().mesh; cloneRenderer.materials = GetComponent().materials; visualClone.transform.localScale = transform.localScale; } void OnTriggerEnter(Collider other) { Portal portal = other.GetComponent(); if (portal != null) { EnterPortal(portal, portal.OtherPortal, other); } } void EnterPortal(Portal inPortal, Portal outPortal, Collider portalWall) { entryPortal = inPortal; exitPortal = outPortal; // Ignore collision with portal wall during transition Physics.IgnoreCollision(objectCollider, portalWall, true); // Activate clone for visual continuity visualClone.SetActive(true); portalCount++; Debug.Log($"Entered portal. Active portals: {portalCount}"); } void LateUpdate() { if (visualClone.activeSelf && entryPortal != null && exitPortal != null) { // Update clone position to appear on exit portal Vector3 relativePos = entryPortal.transform.InverseTransformPoint(transform.position); relativePos = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativePos; visualClone.transform.position = exitPortal.transform.TransformPoint(relativePos); // Update clone rotation Quaternion relativeRot = Quaternion.Inverse(entryPortal.transform.rotation) * transform.rotation; relativeRot = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativeRot; visualClone.transform.rotation = exitPortal.transform.rotation * relativeRot; } } void OnTriggerExit(Collider other) { Portal portal = other.GetComponent(); if (portal != null) { // Re-enable collision with portal wall Physics.IgnoreCollision(objectCollider, other, false); portalCount--; if (portalCount == 0) { visualClone.SetActive(false); entryPortal = null; exitPortal = null; } } } } ``` -------------------------------- ### Recursive Portal View Rendering in C# with URP Source: https://context7.com/daniel-ilett/portals-urp/llms.txt This script renders portal views recursively by transforming the camera through portal pairs and using oblique projection to clip at the portal plane. It depends on UnityEngine, UnityEngine.Rendering, and UnityEngine.Rendering.Universal namespaces, along with custom Portal components. Inputs include portal objects, camera, and recursion depth; outputs a rendered texture for the portal material. Limitations include performance impact from high recursion iterations and assumption of placed portals. ```csharp using UnityEngine; using UnityEngine.Rendering; using UnityEngine.Rendering.Universal; public class RecursivePortalRenderer : MonoBehaviour { [SerializeField] private Portal inPortal; [SerializeField] private Portal outPortal; [SerializeField] private Camera portalCamera; [SerializeField] private int recursionIterations = 7; private Camera mainCamera; private RenderTexture portalTexture; void Start() { mainCamera = Camera.main; // Create render texture for portal view portalTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); inPortal.Renderer.material.mainTexture = portalTexture; // Subscribe to render pipeline RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; } void OnDestroy() { RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; } void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { if (camera != mainCamera || !inPortal.IsPlaced || !outPortal.IsPlaced) return; if (inPortal.Renderer.isVisible) { portalCamera.targetTexture = portalTexture; // Render recursively from highest iteration to lowest for (int i = recursionIterations - 1; i >= 0; i--) { RenderPortalView(context, i); } } } void RenderPortalView(ScriptableRenderContext context, int iterationID) { Transform inTransform = inPortal.transform; Transform outTransform = outPortal.transform; // Initialize portal camera with main camera transform portalCamera.transform.position = mainCamera.transform.position; portalCamera.transform.rotation = mainCamera.transform.rotation; // Apply recursive transformation for each iteration for (int i = 0; i <= iterationID; i++) { // Transform camera position through portal Vector3 relativePos = inTransform.InverseTransformPoint(portalCamera.transform.position); relativePos = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativePos; portalCamera.transform.position = outTransform.TransformPoint(relativePos); // Transform camera rotation through portal Quaternion relativeRot = Quaternion.Inverse(inTransform.rotation) * portalCamera.transform.rotation; relativeRot = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativeRot; portalCamera.transform.rotation = outTransform.rotation * relativeRot; } // Set up oblique projection matrix to clip at portal plane Plane clipPlane = new Plane(-outTransform.forward, outTransform.position); Vector4 clipPlaneWorldSpace = new Vector4( clipPlane.normal.x, clipPlane.normal.y, clipPlane.normal.z, clipPlane.distance ); // Transform clip plane to camera space Vector4 clipPlaneCameraSpace = Matrix4x4.Transpose( Matrix4x4.Inverse(portalCamera.worldToCameraMatrix) ) * clipPlaneWorldSpace; // Calculate oblique projection matrix portalCamera.projectionMatrix = mainCamera.CalculateObliqueMatrix(clipPlaneCameraSpace); // Render the portal camera UniversalRenderPipeline.RenderSingleCamera(context, portalCamera); Debug.Log($"Rendered portal view at iteration {iterationID}"); } } ``` -------------------------------- ### Place Portal on Surface - Unity C# Source: https://context7.com/daniel-ilett/portals-urp/llms.txt Places a portal at a specified position with collision validation, correcting for overhangs and wall intersections. Calculates portal rotation based on surface normal and uses raycasting to find placement surfaces. The system validates placement and provides feedback on success or failure status. ```csharp using UnityEngine; public class PortalPlacementExample : MonoBehaviour { private Portal portal; void Start() { portal = GetComponent(); } void Update() { if (Input.GetMouseButtonDown(0)) { // Cast ray from camera to find placement surface Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit, 100f)) { // Calculate portal rotation based on surface normal Vector3 portalForward = -hit.normal; Vector3 portalRight = Vector3.Cross(Vector3.up, portalForward).normalized; Vector3 portalUp = Vector3.Cross(portalForward, portalRight); Quaternion rotation = Quaternion.LookRotation(portalForward, portalUp); // Attempt to place portal bool wasPlaced = portal.PlacePortal(hit.collider, hit.point, rotation); if (wasPlaced) { Debug.Log("Portal placed successfully at " + hit.point); } else { Debug.Log("Portal placement failed - invalid position"); } } } } } ``` -------------------------------- ### Fire Portal with Recursive Traversal in C# (Unity) Source: https://context7.com/daniel-ilett/portals-urp/llms.txt Implements portal shooting mechanics with recursive traversal through existing portals. Handles mouse input for left/right portal firing, calculates portal orientation, and manages portal chaining. Requires PortalPair component and placement LayerMask configuration. ```csharp using UnityEngine; public class PortalShootingExample : MonoBehaviour { [SerializeField] private PortalPair portalPair; [SerializeField] private LayerMask placementLayer; void Update() { // Fire left portal with left mouse button if (Input.GetButtonDown("Fire1")) { FirePortalFromCamera(0); } // Fire right portal with right mouse button else if (Input.GetButtonDown("Fire2")) { FirePortalFromCamera(1); } } void FirePortalFromCamera(int portalID) { Vector3 origin = transform.position; Vector3 direction = transform.forward; float maxDistance = 250.0f; RaycastHit hit; if (Physics.Raycast(origin, direction, out hit, maxDistance, placementLayer)) { // Check if we hit an existing portal if (hit.collider.CompareTag("Portal")) { Portal hitPortal = hit.collider.GetComponent(); Portal exitPortal = hitPortal.OtherPortal; // Transform ray through portal (recursive traversal) Vector3 relativePos = hitPortal.transform.InverseTransformPoint(hit.point + direction); relativePos = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativePos; Vector3 newOrigin = exitPortal.transform.TransformPoint(relativePos); Vector3 relativeDir = hitPortal.transform.InverseTransformDirection(direction); relativeDir = Quaternion.Euler(0.0f, 180.0f, 0.0f) * relativeDir; Vector3 newDirection = exitPortal.transform.TransformDirection(relativeDir); // Continue raycast from exit portal float remainingDistance = maxDistance - Vector3.Distance(origin, hit.point); Physics.Raycast(newOrigin, newDirection, out hit, remainingDistance, placementLayer); } // Calculate portal orientation Vector3 portalForward = -hit.normal; Vector3 cameraRight = Camera.main.transform.right; // Snap portal right vector to cardinal directions if (Mathf.Abs(cameraRight.x) >= Mathf.Abs(cameraRight.z)) { cameraRight = (cameraRight.x >= 0) ? Vector3.right : -Vector3.right; } else { cameraRight = (cameraRight.z >= 0) ? Vector3.forward : -Vector3.forward; } Vector3 portalUp = -Vector3.Cross(cameraRight, portalForward); Quaternion portalRotation = Quaternion.LookRotation(portalForward, portalUp); // Place the portal bool placed = portalPair.Portals[portalID].PlacePortal(hit.collider, hit.point, portalRotation); Debug.Log($"Portal {portalID} placement: {(placed ? "Success" : "Failed")}"); } } } ``` -------------------------------- ### Implement First-Person Camera Controls and Portal Warp Reset in Unity C# Source: https://context7.com/daniel-ilett/portals-urp/llms.txt This script handles first-person camera movement and rotation using Unity's input system, with smooth interpolation for rotation and rigidbody-based movement. It requires a Rigidbody component and is designed for Unity environments. The ResetTargetRotation method recalculates the target rotation to align with the world up vector while preserving forward direction, ideal for portal warping scenarios. Limitations include fixed look speed and clamp angles, which may need adjustment for different hardware. ```csharp using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class FirstPersonCamera : MonoBehaviour { private const float moveSpeed = 7.5f; private const float lookSpeed = 3.0f; private const float rotationSmoothness = 15.0f; public Quaternion TargetRotation { get; private set; } private Rigidbody rb; void Start() { rb = GetComponent(); Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; TargetRotation = transform.rotation; } void Update() { HandleCameraRotation(); HandleMovement(); } void HandleCameraRotation() { // Get mouse input float mouseX = Input.GetAxis("Mouse X") * lookSpeed; float mouseY = -Input.GetAxis("Mouse Y") * lookSpeed; // Calculate target rotation Vector3 currentEuler = TargetRotation.eulerAngles; currentEuler.y += mouseX; currentEuler.x += mouseY; // Normalize X rotation to [-180, 180] range if (currentEuler.x > 180.0f) { currentEuler.x -= 360.0f; } // Clamp vertical look angle currentEuler.x = Mathf.Clamp(currentEuler.x, -75.0f, 75.0f); TargetRotation = Quaternion.Euler(currentEuler); // Smoothly interpolate to target rotation transform.rotation = Quaternion.Slerp( transform.rotation, TargetRotation, Time.deltaTime * rotationSmoothness ); } void HandleMovement() { // Get movement input float horizontal = Input.GetAxis("Horizontal"); float vertical = Input.GetAxis("Vertical"); float elevation = Input.GetAxis("Elevation"); // Custom axis for up/down // Calculate movement vector in local space Vector3 moveVector = new Vector3(horizontal, 0.0f, vertical) * moveSpeed; // Transform to world space Vector3 worldMove = transform.TransformDirection(moveVector); worldMove.y = elevation * moveSpeed; // Apply velocity rb.velocity = worldMove; } public void ResetTargetRotation() { // Recalculate target rotation maintaining forward direction but aligning with world up Vector3 forward = transform.forward; TargetRotation = Quaternion.LookRotation(forward, Vector3.up); Debug.Log("Camera rotation reset to: " + TargetRotation.eulerAngles); } // Call this after warping through portals public void OnPortalWarp() { ResetTargetRotation(); } } ``` -------------------------------- ### Portal Outline Shader using Stencil Testing in HLSL Source: https://context7.com/daniel-ilett/portals-urp/llms.txt This shader renders a solid colored outline around portals by expanding vertices along normals and using stencil testing to draw only outside the masked area (stencil value 0). It takes outline color and width as inputs, outputting a uniform color fragment. Depends on URP core library; limited to opaque geometry queue and fixed expansion for width. ```HLSL Shader "Custom/PortalOutlineImplementation" { Properties { _OutlineColour("Outline Color", Color) = (1, 1, 1, 1) _OutlineWidth("Outline Width", Float) = 1.02 } SubShader { Tags { "RenderType" = "Opaque" "Queue" = "Geometry+2" "RenderPipeline" = "UniversalPipeline" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" ENDHLSL // Only render where stencil buffer is 0 (outside portal mask) Stencil { Ref 0 Comp Equal } Pass { Name "PortalOutline" HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct Attributes { float4 positionOS : POSITION; float3 normalOS : NORMAL; }; struct Varyings { float4 positionCS : SV_POSITION; }; CBUFFER_START(UnityPerMaterial) float4 _OutlineColour; float _OutlineWidth; CBUFFER_END Varyings vert(Attributes input) { Varyings output; // Expand vertex along normal for outline effect float3 expandedPos = input.positionOS.xyz + input.normalOS * 0.1; output.positionCS = TransformObjectToHClip(expandedPos); return output; } float4 frag(Varyings input) : SV_Target { // Return solid outline color return _OutlineColour; } ENDHLSL } } Fallback Off } ``` -------------------------------- ### Warp Player Through Portal using Unity C# Source: https://context7.com/daniel-ilett/portals-urp/llms.txt Implements player teleportation between linked portals, preserving position, rotation, and velocity while resetting camera orientation. Requires CameraMove and Rigidbody components attached to the player GameObject. Handles portal detection via trigger colliders and swaps portal references after warping. ```csharp using UnityEngine; [RequireComponent(typeof(CameraMove))] [RequireComponent(typeof(Rigidbody))] public class PlayerPortalController : MonoBehaviour { private CameraMove cameraController; private Rigidbody playerRigidbody; private Portal currentPortal; private Portal destinationPortal; void Start() { cameraController = GetComponent(); playerRigidbody = GetComponent(); } void OnTriggerEnter(Collider other) { Portal portal = other.GetComponent(); if (portal != null) { currentPortal = portal; destinationPortal = portal.OtherPortal; } } void Update() { if (currentPortal != null && destinationPortal != null) { // Check if player crossed portal threshold Vector3 localPos = currentPortal.transform.InverseTransformPoint(transform.position); if (localPos.z > 0.0f) { WarpPlayer(); } } } void WarpPlayer() { Transform inTransform = currentPortal.transform; Transform outTransform = destinationPortal.transform; Quaternion halfTurn = Quaternion.Euler(0.0f, 180.0f, 0.0f); // Transform player position Vector3 relativePos = inTransform.InverseTransformPoint(transform.position); relativePos = halfTurn * relativePos; transform.position = outTransform.TransformPoint(relativePos); // Transform player rotation Quaternion relativeRot = Quaternion.Inverse(inTransform.rotation) * transform.rotation; relativeRot = halfTurn * relativeRot; transform.rotation = outTransform.rotation * relativeRot; // Transform velocity Vector3 relativeVel = inTransform.InverseTransformDirection(playerRigidbody.velocity); relativeVel = halfTurn * relativeVel; playerRigidbody.velocity = outTransform.TransformDirection(relativeVel); // Reset camera target rotation to prevent disorientation cameraController.ResetTargetRotation(); // Swap portal references Portal temp = currentPortal; currentPortal = destinationPortal; destinationPortal = temp; Debug.Log("Player warped through portal to position: " + transform.position); } } ``` -------------------------------- ### Portal Mask Shader using Stencil Buffer in HLSL Source: https://context7.com/daniel-ilett/portals-urp/llms.txt This shader writes a reference value to the stencil buffer during rendering, masking the portal view texture to display only within the portal geometry bounds in URP. It requires a portal view texture as input and outputs the sampled texture color. Dependencies include Unity's URP shader library; limitations involve fixed stencil reference and opaque rendering queue. ```HLSL Shader "Custom/PortalMaskImplementation" { Properties { _MainTex("Portal View Texture", 2D) = "white" {} _StencilRef("Stencil Reference", Int) = 1 } SubShader { Tags { "RenderType" = "Opaque" "Queue" = "Geometry" "RenderPipeline" = "UniversalPipeline" } HLSLINCLUDE #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" ENDHLSL Pass { Name "PortalStencilMask" // Write to stencil buffer Stencil { Ref 1 Comp Always Pass Replace } HLSLPROGRAM #pragma vertex vert #pragma fragment frag struct Attributes { float4 positionOS : POSITION; }; struct Varyings { float4 positionCS : SV_POSITION; float4 screenPos : TEXCOORD0; }; sampler2D _MainTex; Varyings vert(Attributes input) { Varyings output; // Transform vertex to clip space output.positionCS = TransformObjectToHClip(input.positionOS.xyz); // Calculate screen-space position for texture sampling output.screenPos = ComputeScreenPos(output.positionCS); return output; } float4 frag(Varyings input) : SV_Target { // Sample portal view texture using screen coordinates float2 screenUV = input.screenPos.xy / input.screenPos.w; float4 portalColor = tex2D(_MainTex, screenUV); return portalColor; } ENDHLSL } } } ``` -------------------------------- ### Warp object through portal with physics transformation Source: https://context7.com/daniel-ilett/portals-urp/llms.txt Teleports a GameObject through a portal system while maintaining physics consistency. Requires a Rigidbody component and works with a paired Portal component. Transforms position, rotation, and velocity relative to portal orientations. Dependent on OnTriggerEnter detection and portal plane crossing checks. ```csharp using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class CustomPortalObject : MonoBehaviour { private Portal currentInPortal; private Portal currentOutPortal; private Rigidbody rb; void Start() { rb = GetComponent(); } void OnTriggerEnter(Collider other) { // Detect portal entry Portal portal = other.GetComponent(); if (portal != null) { currentInPortal = portal; currentOutPortal = portal.OtherPortal; } } void Update() { if (currentInPortal != null && currentOutPortal != null) { // Check if object has crossed portal plane Vector3 localPos = currentInPortal.transform.InverseTransformPoint(transform.position); if (localPos.z > 0.0f) { WarpThroughPortal(); } } } void WarpThroughPortal() { Transform inTransform = currentInPortal.transform; Transform outTransform = currentOutPortal.transform; Quaternion halfTurn = Quaternion.Euler(0.0f, 180.0f, 0.0f); // Transform position Vector3 relativePos = inTransform.InverseTransformPoint(transform.position); relativePos = halfTurn * relativePos; transform.position = outTransform.TransformPoint(relativePos); // Transform rotation Quaternion relativeRot = Quaternion.Inverse(inTransform.rotation) * transform.rotation; relativeRot = halfTurn * relativeRot; transform.rotation = outTransform.rotation * relativeRot; // Transform velocity Vector3 relativeVel = inTransform.InverseTransformDirection(rb.velocity); relativeVel = halfTurn * relativeVel; rb.velocity = outTransform.TransformDirection(relativeVel); // Swap portal references Portal temp = currentInPortal; currentInPortal = currentOutPortal; currentOutPortal = temp; Debug.Log("Object warped through portal with velocity: " + rb.velocity); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.