non-VR portal rendering
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace Escape_Room_Engine.Portal
|
||||
{
|
||||
public class Portal : MonoBehaviour
|
||||
{
|
||||
private static readonly Matrix4x4 HalfRotation = Matrix4x4.Rotate(Quaternion.Euler(0, 180, 0));
|
||||
|
||||
/// <summary>
|
||||
/// The portal that is connected with this one.
|
||||
/// </summary>
|
||||
@@ -12,25 +16,65 @@ namespace Escape_Room_Engine.Portal
|
||||
/// <summary>
|
||||
/// The main camera to take the position for the portal camera from.
|
||||
/// </summary>
|
||||
[SerializeField] private Transform playerCamera;
|
||||
[SerializeField] private Camera playerCamera;
|
||||
/// <summary>
|
||||
/// The camera that will draw the view for this portal.
|
||||
/// </summary>
|
||||
[SerializeField] private Transform portalCamera;
|
||||
[SerializeField] private Camera portalCamera;
|
||||
/// <summary>
|
||||
/// The quad where the rendered texture will be drawn on.
|
||||
/// </summary>
|
||||
[SerializeField] private MeshRenderer portalQuad;
|
||||
|
||||
private void Start()
|
||||
private RenderTexture _texture;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// check whether the other portal is set up
|
||||
if (!other || other.other != this) throw new Exception("Other Portal not set up correctly.");
|
||||
// check whether the player camera is set up
|
||||
if (!playerCamera) throw new Exception("No camera initialised.");
|
||||
|
||||
// create render texture
|
||||
_texture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
private void Start()
|
||||
{
|
||||
var portalCameraMatrix = transform.localToWorldMatrix * other.transform.worldToLocalMatrix *
|
||||
playerCamera.localToWorldMatrix;
|
||||
portalCamera.SetPositionAndRotation(portalCameraMatrix.GetPosition(), portalCameraMatrix.rotation);
|
||||
// assign render texture
|
||||
portalCamera.targetTexture = _texture;
|
||||
other.portalQuad.material.mainTexture = _texture;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
RenderPipelineManager.beginCameraRendering += Render;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
RenderPipelineManager.beginCameraRendering -= Render;
|
||||
}
|
||||
|
||||
private void Render(ScriptableRenderContext scriptableRenderContext, Camera camera)
|
||||
{
|
||||
var t = transform;
|
||||
|
||||
// position portal camera
|
||||
var portalCameraMatrix = t.localToWorldMatrix * HalfRotation * other.transform.worldToLocalMatrix *
|
||||
playerCamera.transform.localToWorldMatrix;
|
||||
portalCamera.transform.SetPositionAndRotation(portalCameraMatrix.GetPosition(), portalCameraMatrix.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
|
||||
var n = -t.forward; // clip plane normal
|
||||
var portalPlane = new Plane(n, t.position); // clip plane in world space
|
||||
var clipPlane = portalCamera.worldToCameraMatrix.inverse.transpose *
|
||||
new Vector4(n.x, n.y, n.z, portalPlane.distance); // vector format clip plane in camera space
|
||||
portalCamera.projectionMatrix = playerCamera.CalculateObliqueMatrix(clipPlane);
|
||||
|
||||
// render portal view
|
||||
UniversalRenderPipeline.RenderSingleCamera(scriptableRenderContext, portalCamera);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user