render stencil portals (opaque)

This commit is contained in:
2023-03-03 16:25:24 +01:00
parent 5e911f2df1
commit 6d2b5c52a1
16 changed files with 781 additions and 947 deletions

View File

@@ -4,7 +4,6 @@ using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using NaughtyAttributes;
using UnityEngine;
using UnityEngine.Serialization;
namespace EscapeRoomEngine.Portal.Runtime
{
@@ -23,9 +22,13 @@ namespace EscapeRoomEngine.Portal.Runtime
/// </summary>
public Portal linkedPortal;
/// <summary>
/// The camera that will draw the view for this portal.
/// The minimum near clip plane distance to be used when calculating the oblique clip plane.
/// </summary>
[BoxGroup("Internal")] public PortalCamera portalCamera;
public float minNearClipPlane = 0.0001f;
/// <summary>
/// The mesh where the portal will be drawn.
/// </summary>
[BoxGroup("Internal")] public MeshRenderer screen;
/// <summary>
/// The transform marking the edge of the portal plane.
/// </summary>
@@ -51,12 +54,10 @@ namespace EscapeRoomEngine.Portal.Runtime
{
case DoorEventType.Connected:
linkedPortal = FromDoorState(Module.ConnectedDoorState);
portalCamera.screen.gameObject.SetActive(true);
portalCamera.enabled = true;
screen.gameObject.SetActive(true);
break;
case DoorEventType.Locked:
portalCamera.enabled = false;
portalCamera.screen.gameObject.SetActive(false);
screen.gameObject.SetActive(false);
linkedPortal = null;
break;
}
@@ -85,6 +86,31 @@ namespace EscapeRoomEngine.Portal.Runtime
}
}
public Camera SetUpCamera(Camera playerCamera)
{
// place camera
var m = portalTransform.localToWorldMatrix * HalfRotation *
linkedPortal.portalTransform.worldToLocalMatrix * playerCamera.transform.localToWorldMatrix;
playerCamera.transform.SetPositionAndRotation(m.GetPosition(), m.rotation);
// set camera clip plane to portal (otherwise the wall behind the portal would be rendered)
// calculating the clip plane: https://computergraphics.stackexchange.com/a/1506
// clip plane normal
var n = -portalTransform.forward;
// clip plane in world space
var portalPlane = new Plane(n, portalTransform.position);
if (-portalPlane.GetDistanceToPoint(playerCamera.transform.position) >= minNearClipPlane)
{
// vector format clip plane in camera space
var clipPlane = playerCamera.worldToCameraMatrix.inverse.transpose *
new Vector4(n.x, n.y, n.z, portalPlane.distance);
// only adjust the near clip plane if it doesn't intersect with the camera
playerCamera.projectionMatrix = playerCamera.CalculateObliqueMatrix(clipPlane);
}
return playerCamera;
}
/// <summary>
/// Begin tracking a portal driver that came close to this portal and might need to be teleported.
/// </summary>