using System; using UnityEngine; using UnityEngine.Rendering; #if MODULE_URP_ENABLED using UnityEngine.Rendering.Universal; #elif MODULE_LWRP_ENABLED using UnityEngine.Rendering.LWRP; #else using ScriptableRendererFeature = UnityEngine.ScriptableObject; #endif namespace UnityEngine.XR.ARFoundation { /// /// A render feature for rendering the camera background for AR devies. /// public class ARBackgroundRendererFeature : ScriptableRendererFeature { #if MODULE_URP_ENABLED || MODULE_LWRP_ENABLED /// /// The scriptable render pass to be added to the renderer when the camera background is to be rendered. /// CustomRenderPass m_ScriptablePass; /// /// The mesh for rendering the background shader. /// Mesh m_BackgroundMesh; /// /// Create the scriptable render pass. /// public override void Create() { #if !UNITY_EDITOR m_ScriptablePass = new CustomRenderPass(RenderPassEvent.BeforeRenderingOpaques); m_BackgroundMesh = new Mesh(); m_BackgroundMesh.vertices = new Vector3[] { new Vector3(0f, 0f, 0.1f), new Vector3(0f, 1f, 0.1f), new Vector3(1f, 1f, 0.1f), new Vector3(1f, 0f, 0.1f), }; m_BackgroundMesh.uv = new Vector2[] { new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(1f, 0f), }; m_BackgroundMesh.triangles = new int[] {0, 1, 2, 0, 2, 3}; #endif // !UNITY_EDITOR } /// /// Add the background rendering pass when rendering a game camera with an enabled AR camera background component. /// /// The scriptable renderer in which to enqueue the render pass. /// Additional rendering data about the current state of rendering. public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData) { #if !UNITY_EDITOR Camera currentCamera = renderingData.cameraData.camera; if ((currentCamera != null) && (currentCamera.cameraType == CameraType.Game)) { ARCameraBackground cameraBackground = currentCamera.gameObject.GetComponent(); if ((cameraBackground != null) && cameraBackground.backgroundRenderingEnabled && (cameraBackground.material != null)) { bool invertCulling = cameraBackground.GetComponent()?.subsystem?.invertCulling ?? false; m_ScriptablePass.Setup(m_BackgroundMesh, cameraBackground.material, invertCulling); renderer.EnqueuePass(m_ScriptablePass); } } #endif // !UNITY_EDITOR } /// /// The custom render pass to render the camera background. /// class CustomRenderPass : ScriptableRenderPass { /// /// The name for the custom render pass which will display in graphics debugging tools. /// const string k_CustomRenderPassName = "AR Background Pass (URP)"; /// /// The orthogonal projection matrix for the background rendering. /// static readonly Matrix4x4 k_BackgroundOrthoProjection = Matrix4x4.Ortho(0f, 1f, 0f, 1f, -0.1f, 9.9f); /// /// The mesh for rendering the background material. /// Mesh m_BackgroundMesh; /// /// The material used for rendering the device background using the camera video texture and potentially /// other device-specific properties and textures. /// Material m_BackgroundMaterial; /// /// Whether the culling mode should be inverted. /// ([CommandBuffer.SetInvertCulling](https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.SetInvertCulling.html)). /// bool m_InvertCulling; /// /// Constructs the background render pass. /// /// The render pass event when this pass should be rendered. public CustomRenderPass(RenderPassEvent renderPassEvent) { this.renderPassEvent = renderPassEvent; } /// /// Set up the background render pass. /// /// The mesh used for rendering the device background. /// The material used for rendering the device background. /// Whether the culling mode should be inverted. public void Setup(Mesh backgroundMesh, Material backgroundMaterial, bool invertCulling) { m_BackgroundMesh = backgroundMesh; m_BackgroundMaterial = backgroundMaterial; m_InvertCulling = invertCulling; } /// /// Configure the render pass by configuring the render target and clear values. /// /// The command buffer for configuration. /// The descriptor of the target render texture. public override void Configure(CommandBuffer commandBuffer, RenderTextureDescriptor renderTextureDescriptor) { ConfigureClear(ClearFlag.Depth, Color.clear); } /// /// Execute the commands to render the camera background. /// /// The render context for executing the render commands. /// Additional rendering data about the current state of rendering. public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { var cmd = CommandBufferPool.Get(k_CustomRenderPassName); cmd.BeginSample(k_CustomRenderPassName); ARCameraBackground.AddBeforeBackgroundRenderHandler(cmd); cmd.SetInvertCulling(m_InvertCulling); cmd.SetViewProjectionMatrices(Matrix4x4.identity, k_BackgroundOrthoProjection); cmd.DrawMesh(m_BackgroundMesh, Matrix4x4.identity, m_BackgroundMaterial); cmd.SetViewProjectionMatrices(renderingData.cameraData.camera.worldToCameraMatrix, renderingData.cameraData.camera.projectionMatrix); cmd.EndSample(k_CustomRenderPassName); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); } /// /// Clean up any resources for the render pass. /// /// The command buffer for frame cleanup. public override void FrameCleanup(CommandBuffer commandBuffer) { } } #endif // MODULE_URP_ENABLED || MODULE_LWRP_ENABLED } }