render stencil portals (opaque)
This commit is contained in:
113
Assets/Portal/Runtime/RenderPortalCameras.cs
Normal file
113
Assets/Portal/Runtime/RenderPortalCameras.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System.Collections.Generic;
|
||||
using EscapeRoomEngine.VR.Runtime;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using UnityEngine.Rendering.Universal;
|
||||
|
||||
namespace EscapeRoomEngine.Portal.Runtime
|
||||
{
|
||||
public class RenderPortalCameras : ScriptableRendererFeature
|
||||
{
|
||||
private enum PassType
|
||||
{
|
||||
Opaque,
|
||||
Transparent
|
||||
}
|
||||
|
||||
private class PortalCameraRenderPass : ScriptableRenderPass
|
||||
{
|
||||
private static readonly List<ShaderTagId> ShaderTagIds = new List<ShaderTagId>
|
||||
{
|
||||
new("SRPDefaultUnlit"), new("UniversalForward"), new("UniversalForwardOnly")
|
||||
};
|
||||
|
||||
private RenderStateBlock _renderStateBlock;
|
||||
private CommandBuffer _commandBuffer;
|
||||
|
||||
private readonly LayerMask _layers;
|
||||
private readonly PassType _passType;
|
||||
|
||||
public PortalCameraRenderPass(LayerMask layers, PassType passType)
|
||||
{
|
||||
_layers = layers;
|
||||
_passType = passType;
|
||||
|
||||
renderPassEvent = RenderPassEvent.AfterRenderingOpaques;
|
||||
_renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
|
||||
|
||||
// set stencil
|
||||
var stencilState = StencilState.defaultValue;
|
||||
stencilState.enabled = true;
|
||||
stencilState.SetCompareFunction(CompareFunction.Equal);
|
||||
stencilState.SetPassOperation(StencilOp.Keep);
|
||||
stencilState.SetFailOperation(StencilOp.Keep);
|
||||
stencilState.SetZFailOperation(StencilOp.Keep);
|
||||
_renderStateBlock.mask |= RenderStateMask.Stencil;
|
||||
_renderStateBlock.stencilState = stencilState;
|
||||
}
|
||||
|
||||
public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
|
||||
{
|
||||
// we need to store a reference to the command buffer before executing, because the reference in RenderingData is internal
|
||||
_commandBuffer = cmd;
|
||||
}
|
||||
|
||||
public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
|
||||
{
|
||||
if (Player.Instance)
|
||||
{
|
||||
var drawingSettings = CreateDrawingSettings(ShaderTagIds, ref renderingData, _passType == PassType.Opaque ? renderingData.cameraData.defaultOpaqueSortFlags : SortingCriteria.CommonTransparent);
|
||||
var filteringSettings = new FilteringSettings(_passType == PassType.Opaque ? RenderQueueRange.opaque : RenderQueueRange.transparent, _layers);
|
||||
|
||||
foreach (var portal in FindObjectsByType<Portal>(FindObjectsInactive.Exclude, FindObjectsSortMode.None))
|
||||
{
|
||||
var linkedPortal = portal.linkedPortal;
|
||||
if (linkedPortal)
|
||||
{
|
||||
// set which portal to render
|
||||
_renderStateBlock.stencilReference = portal.PortalNumber;
|
||||
|
||||
// prepare the camera
|
||||
ref var cameraData = ref renderingData.cameraData;
|
||||
var camera = cameraData.camera;
|
||||
var cameraTransform = camera.transform;
|
||||
var originalPosition = cameraTransform.position;
|
||||
var originalRotation = cameraTransform.rotation;
|
||||
var originalProjection = camera.projectionMatrix;
|
||||
camera = linkedPortal.SetUpCamera(camera);
|
||||
RenderingUtils.SetViewAndProjectionMatrices(_commandBuffer, camera.worldToCameraMatrix, GL.GetGPUProjectionMatrix(camera.projectionMatrix, true), false);
|
||||
|
||||
// execute command buffer
|
||||
context.ExecuteCommandBuffer(_commandBuffer);
|
||||
_commandBuffer.Clear();
|
||||
|
||||
// render the portal
|
||||
context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref filteringSettings, ref _renderStateBlock);
|
||||
|
||||
// reset
|
||||
RenderingUtils.SetViewAndProjectionMatrices(_commandBuffer, cameraData.GetViewMatrix(), cameraData.GetGPUProjectionMatrix(), false);
|
||||
camera.transform.SetPositionAndRotation(originalPosition, originalRotation);
|
||||
camera.projectionMatrix = originalProjection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private PortalCameraRenderPass _opaquePass, _transparentPass;
|
||||
|
||||
public LayerMask layers;
|
||||
|
||||
public override void Create()
|
||||
{
|
||||
_opaquePass = new PortalCameraRenderPass(layers, PassType.Opaque);
|
||||
_transparentPass = new PortalCameraRenderPass(layers, PassType.Transparent);
|
||||
}
|
||||
|
||||
public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
|
||||
{
|
||||
renderer.EnqueuePass(_opaquePass);
|
||||
// renderer.EnqueuePass(_transparentPass); TODO: enable
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user