Skip to content

Instantly share code, notes, and snippets.

@limdingwen
Created April 17, 2020 00:56
Show Gist options
  • Save limdingwen/74bc278db0a37316f83aa93e34aff503 to your computer and use it in GitHub Desktop.
Save limdingwen/74bc278db0a37316f83aa93e34aff503 to your computer and use it in GitHub Desktop.
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// Starts the recursive portal rendering process, taking into account portal occlusion volumes.
/// </summary>
public class PortalRenderer : MonoBehaviour
{
private PortalOcclusionVolume[] portalOcclusionVolumes;
[SerializeField] private Camera portalCamera;
[SerializeField] private int maxRecursions = 2;
[SerializeField] private LayerMask noCloneMask;
[SerializeField] private LayerMask renderCloneMask;
/// <summary>
/// Debug read only: Indicates the total amount of recursive renders performed by portals this frame.
/// </summary>
public int debugTotalRenderCount;
/// <summary>
/// Debug read only: Indicates how many portal renders were due to being directly visible by the player.
/// Use this field to debug the size of portal occlusion volumes.
/// </summary>
public int debugDirectRenderCount;
private void OnEnable()
{
RenderPipelineManager.beginFrameRendering += RenderPipelineManagerOnBeginFrameRendering;
RenderPipelineManager.endFrameRendering += RenderPipelineManagerOnEndFrameRendering;
}
private void OnDisable()
{
RenderPipelineManager.beginFrameRendering -= RenderPipelineManagerOnBeginFrameRendering;
RenderPipelineManager.endFrameRendering -= RenderPipelineManagerOnEndFrameRendering;
}
private void Start()
{
portalOcclusionVolumes = FindObjectsOfType<PortalOcclusionVolume>();
}
/// <summary>
/// Note: Does not support multiple cameras. Renders with mainCamera as reference.
/// Multi camera support easily possible!
/// </summary>
private void RenderPipelineManagerOnBeginFrameRendering(ScriptableRenderContext context, Camera[] cameras)
{
// Find the current occlusion volume
PortalOcclusionVolume currentOcclusionVolume = null;
foreach (var portalOcclusionVolume in portalOcclusionVolumes)
{
if (portalOcclusionVolume.PositionInVolume(GameManager.Instance.MainCamera.transform.position))
{
currentOcclusionVolume = portalOcclusionVolume;
}
}
// Render portals in occlusion volume
if (currentOcclusionVolume == null)
return;
var mainCamera = GameManager.Instance.MainCamera;
var mainCameraTransform = mainCamera.transform;
var cameraPlanes = GeometryUtility.CalculateFrustumPlanes(mainCamera);
debugTotalRenderCount = 0;
debugDirectRenderCount = 0;
foreach (var portal in currentOcclusionVolume.Portals)
{
if (!portal.ShouldRender(cameraPlanes))
continue;
portal.RenderViewthroughRecursive(
mainCameraTransform.position,
mainCameraTransform.rotation,
out _,
out _,
out var renderCount,
context,
portalCamera,
0,
maxRecursions,
currentOcclusionVolume,
noCloneMask,
renderCloneMask);
debugTotalRenderCount += renderCount;
debugDirectRenderCount++;
}
}
private void RenderPipelineManagerOnEndFrameRendering(ScriptableRenderContext context, Camera[] cameras)
{
PortalRenderTexturePoolManager.Instance.ReleaseAll();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment