// Renders a single camera in a single texture with occlusion only from opaque objects. // This is the most performant option for mixed reality. // It does not support any transparency in the foreground layer. private void RenderOptimized() { bool debugClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.DEBUG_CLIP_PLANE); bool renderComplexClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.COMPLEX_CLIP_PLANE); bool renderGroundClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.GROUND_CLIP_PLANE); SDKUtils.SetCamera(_cameraInstance, _cameraInstance.transform, _inputFrame, localToWorldMatrix, spectatorLayerMask); _cameraInstance.targetTexture = _optimizedRenderTexture; // Clear alpha channel _writeMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, (int)ColorWriteMask.Alpha); _optimizedRenderingCommandBuffer.Blit(BuiltinRenderTextureType.None, BuiltinRenderTextureType.CurrentActive, _writeMaterial); // Render opaque pixels into alpha channel _writeOpaqueToAlphaMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, (int)ColorWriteMask.Alpha); _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, Matrix4x4.identity, _writeOpaqueToAlphaMaterial, 0, 0); // Render clip plane Matrix4x4 clipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.clipPlane.transform; _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, clipPlaneTransform, GetClipPlaneMaterial(debugClipPlane, renderComplexClipPlane, ColorWriteMask.Alpha), 0, 0); // Render ground clip plane if (renderGroundClipPlane) { Matrix4x4 groundClipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.groundClipPlane.transform; _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, groundClipPlaneTransform, GetGroundClipPlaneMaterial(debugClipPlane, ColorWriteMask.Alpha), 0, 0); } _cameraInstance.AddCommandBuffer(CameraEvent.AfterEverything, _optimizedRenderingCommandBuffer); // TODO: this is just proprietary SDKShaders.StartRendering(); SDKShaders.StartBackgroundRendering(); InvokePreRenderBackground(); SendTextureToBridge(_optimizedRenderTexture, TEXTURE_ID.OPTIMIZED_COLOR_BUFFER_ID); _cameraInstance.Render(); if (uiRendered) { Graphics.Blit(_uiRenderTexture, _backgroundRenderTexture, _uiTransparentMaterial); } InvokePostRenderBackground(); _cameraInstance.targetTexture = null; SDKShaders.StopBackgroundRendering(); SDKShaders.StopRendering(); _cameraInstance.RemoveCommandBuffer(CameraEvent.AfterEverything, _optimizedRenderingCommandBuffer); _optimizedRenderingCommandBuffer.Clear(); }
// Default render without any special changes private void RenderBackground() { SDKUtils.SetCamera(_cameraInstance, _cameraInstance.transform, _inputFrame, localToWorldMatrix, spectatorLayerMask); _cameraInstance.targetTexture = _backgroundRenderTexture; RenderTexture tempRenderTexture = null; bool overridePostProcessing = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.OVERRIDE_POST_PROCESSING); if (overridePostProcessing) { tempRenderTexture = RenderTexture.GetTemporary(_backgroundRenderTexture.width, _backgroundRenderTexture.height, 0, _backgroundRenderTexture.format); _captureTextureCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, tempRenderTexture); _applyTextureCommandBuffer.Blit(tempRenderTexture, BuiltinRenderTextureType.CurrentActive); _cameraInstance.AddCommandBuffer(_captureTextureEvent, _captureTextureCommandBuffer); _cameraInstance.AddCommandBuffer(_applyTextureEvent, _applyTextureCommandBuffer); } SDKShaders.StartRendering(); SDKShaders.StartBackgroundRendering(); InvokePreRenderBackground(); SendTextureToBridge(_backgroundRenderTexture, TEXTURE_ID.BACKGROUND_COLOR_BUFFER_ID); _cameraInstance.Render(); if (uiRendered) { Graphics.Blit(_uiRenderTexture, _backgroundRenderTexture, _uiTransparentMaterial); } InvokePostRenderBackground(); _cameraInstance.targetTexture = null; SDKShaders.StopBackgroundRendering(); SDKShaders.StopRendering(); if (overridePostProcessing) { _cameraInstance.RemoveCommandBuffer(_captureTextureEvent, _captureTextureCommandBuffer); _cameraInstance.RemoveCommandBuffer(_applyTextureEvent, _applyTextureCommandBuffer); _captureTextureCommandBuffer.Clear(); _applyTextureCommandBuffer.Clear(); RenderTexture.ReleaseTemporary(tempRenderTexture); } }
// Default render without any special changes private void RenderBackground() { SDKUtils.SetCamera(_cameraInstance, _cameraInstance.transform, _inputFrame, localToWorldMatrix, spectatorLayerMask); _cameraInstance.targetTexture = _backgroundRenderTexture; RenderTexture tempRenderTexture = null; bool overridePostProcessing = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.OVERRIDE_POST_PROCESSING); if (overridePostProcessing) { tempRenderTexture = RenderTexture.GetTemporary(_backgroundRenderTexture.width, _backgroundRenderTexture.height, 0, _backgroundRenderTexture.format); #if UNITY_EDITOR tempRenderTexture.name = "LIV.TemporaryRenderTexture"; #endif _captureTexturePass.commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, tempRenderTexture); _applyTexturePass.commandBuffer.Blit(tempRenderTexture, BuiltinRenderTextureType.CurrentActive); SDKUniversalRenderFeature.AddPass(_captureTexturePass); SDKUniversalRenderFeature.AddPass(_applyTexturePass); } SDKShaders.StartRendering(); SDKShaders.StartBackgroundRendering(); InvokePreRenderBackground(); SendTextureToBridge(_backgroundRenderTexture, TEXTURE_ID.BACKGROUND_COLOR_BUFFER_ID); _cameraInstance.Render(); InvokePostRenderBackground(); _cameraInstance.targetTexture = null; SDKShaders.StopBackgroundRendering(); SDKShaders.StopRendering(); if (overridePostProcessing) { _captureTexturePass.commandBuffer.Clear(); _applyTexturePass.commandBuffer.Clear(); RenderTexture.ReleaseTemporary(tempRenderTexture); } SDKUniversalRenderFeature.ClearPasses(); }
// Renders a single camera in a single texture with occlusion only from opaque objects. // This is the most performant option for mixed reality. // It does not support any transparency in the foreground layer. private void RenderOptimized() { if (!SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.BACKGROUND_RENDER) || _backgroundRenderTexture == null || _foregroundRenderTexture == null) { return; } bool debugClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.DEBUG_CLIP_PLANE); bool renderComplexClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.COMPLEX_CLIP_PLANE); bool renderGroundClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.GROUND_CLIP_PLANE); MonoBehaviour[] behaviours = null; bool[] wasBehaviourEnabled = null; if (disableStandardAssets) { SDKUtils.DisableStandardAssets(_cameraInstance, ref behaviours, ref wasBehaviourEnabled); } SDKUtils.SetCamera(_cameraInstance, _cameraInstance.transform, _inputFrame, localToWorldMatrix, spectatorLayerMask); _cameraInstance.targetTexture = _foregroundRenderTexture; // Clear alpha channel _writeMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, (int)ColorWriteMask.Alpha); _optimizedRenderingCommandBuffer.Blit(BuiltinRenderTextureType.None, BuiltinRenderTextureType.CurrentActive, _writeMaterial); // Render opaque pixels into alpha channel _writeOpaqueToAlphaMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, (int)ColorWriteMask.Alpha); _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, Matrix4x4.identity, _writeOpaqueToAlphaMaterial, 0, 0); // Render clip plane Matrix4x4 clipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.clipPlane.transform; _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, clipPlaneTransform, GetClipPlaneMaterial(debugClipPlane, renderComplexClipPlane, ColorWriteMask.Alpha), 0, 0); // Render ground clip plane if (renderGroundClipPlane) { Matrix4x4 groundClipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.groundClipPlane.transform; _optimizedRenderingCommandBuffer.DrawMesh(_clipPlaneMesh, groundClipPlaneTransform, GetGroundClipPlaneMaterial(debugClipPlane, ColorWriteMask.Alpha), 0, 0); } // Copy content to background texture _optimizedRenderingCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, _backgroundRenderTexture); _cameraInstance.AddCommandBuffer(CameraEvent.AfterEverything, _optimizedRenderingCommandBuffer); if (useDeferredRendering) { SDKUtils.ForceForwardRendering(cameraInstance, _clipPlaneMesh, _forceForwardRenderingMaterial); } // TODO: this is just proprietary SDKShaders.StartRendering(); SDKShaders.StartBackgroundRendering(); InvokePreRenderBackground(); SendTextureToBridge(_backgroundRenderTexture, TEXTURE_ID.BACKGROUND_COLOR_BUFFER_ID); SendTextureToBridge(_foregroundRenderTexture, TEXTURE_ID.FOREGROUND_COLOR_BUFFER_ID); _cameraInstance.Render(); InvokePostRenderBackground(); _cameraInstance.targetTexture = null; SDKShaders.StopBackgroundRendering(); SDKShaders.StopRendering(); _cameraInstance.RemoveCommandBuffer(CameraEvent.AfterEverything, _optimizedRenderingCommandBuffer); _optimizedRenderingCommandBuffer.Clear(); SDKUtils.RestoreStandardAssets(ref behaviours, ref wasBehaviourEnabled); }
// Extract the image which is in front of our clip plane // The compositing is heavily relying on the alpha channel, therefore we want to make sure it does // not get corrupted by the postprocessing or any shader private void RenderForeground() { bool debugClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.DEBUG_CLIP_PLANE); bool renderComplexClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.COMPLEX_CLIP_PLANE); bool renderGroundClipPlane = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.GROUND_CLIP_PLANE); bool overridePostProcessing = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.OVERRIDE_POST_PROCESSING); bool fixPostEffectsAlpha = SDKUtils.FeatureEnabled(inputFrame.features, FEATURES.FIX_FOREGROUND_ALPHA) | _liv.fixPostEffectsAlpha; MonoBehaviour[] behaviours = null; bool[] wasBehaviourEnabled = null; if (disableStandardAssets) { SDKUtils.DisableStandardAssets(_cameraInstance, ref behaviours, ref wasBehaviourEnabled); } // Capture camera defaults CameraClearFlags capturedClearFlags = _cameraInstance.clearFlags; Color capturedBgColor = _cameraInstance.backgroundColor; Color capturedFogColor = RenderSettings.fogColor; // Make sure that fog does not corrupt alpha channel RenderSettings.fogColor = new Color(capturedFogColor.r, capturedFogColor.g, capturedFogColor.b, 0f); SDKUtils.SetCamera(_cameraInstance, _cameraInstance.transform, _inputFrame, localToWorldMatrix, spectatorLayerMask); _cameraInstance.clearFlags = CameraClearFlags.Color; _cameraInstance.backgroundColor = Color.clear; _cameraInstance.targetTexture = _foregroundRenderTexture; RenderTexture capturedAlphaRenderTexture = RenderTexture.GetTemporary(_foregroundRenderTexture.width, _foregroundRenderTexture.height, 0, _foregroundRenderTexture.format); #if UNITY_EDITOR capturedAlphaRenderTexture.name = "LIV.CapturedAlphaRenderTexture"; #endif // Render opaque pixels into alpha channel _clipPlaneCommandBuffer.DrawMesh(_clipPlaneMesh, Matrix4x4.identity, _writeOpaqueToAlphaMaterial, 0, 0); // Render clip plane Matrix4x4 clipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.clipPlane.transform; _clipPlaneCommandBuffer.DrawMesh(_clipPlaneMesh, clipPlaneTransform, GetClipPlaneMaterial(debugClipPlane, renderComplexClipPlane, ColorWriteMask.All), 0, 0); // Render ground clip plane if (renderGroundClipPlane) { Matrix4x4 groundClipPlaneTransform = localToWorldMatrix * (Matrix4x4)_inputFrame.groundClipPlane.transform; _clipPlaneCommandBuffer.DrawMesh(_clipPlaneMesh, groundClipPlaneTransform, GetGroundClipPlaneMaterial(debugClipPlane, ColorWriteMask.All), 0, 0); } // Copy alpha in to texture _clipPlaneCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, capturedAlphaRenderTexture); _cameraInstance.AddCommandBuffer(_clipPlaneCameraEvent, _clipPlaneCommandBuffer); // Fix alpha corruption by post processing RenderTexture tempRenderTexture = null; if (overridePostProcessing || fixPostEffectsAlpha) { tempRenderTexture = RenderTexture.GetTemporary(_foregroundRenderTexture.width, _foregroundRenderTexture.height, 0, _foregroundRenderTexture.format); #if UNITY_EDITOR tempRenderTexture.name = "LIV.TemporaryRenderTexture"; #endif _captureTextureCommandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, tempRenderTexture); _cameraInstance.AddCommandBuffer(_captureTextureEvent, _captureTextureCommandBuffer); _writeMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, overridePostProcessing ? (int)ColorWriteMask.All : (int)ColorWriteMask.Alpha); _applyTextureCommandBuffer.Blit(tempRenderTexture, BuiltinRenderTextureType.CurrentActive, _writeMaterial); _cameraInstance.AddCommandBuffer(_applyTextureEvent, _applyTextureCommandBuffer); } // Combine captured alpha with result alpha _combineAlphaMaterial.SetInt(SDKShaders.LIV_COLOR_MASK, (int)ColorWriteMask.Alpha); _combineAlphaCommandBuffer.Blit(capturedAlphaRenderTexture, BuiltinRenderTextureType.CurrentActive, _combineAlphaMaterial); _cameraInstance.AddCommandBuffer(_clipPlaneCombineAlphaCameraEvent, _combineAlphaCommandBuffer); if (useDeferredRendering) { SDKUtils.ForceForwardRendering(cameraInstance, _clipPlaneMesh, _forceForwardRenderingMaterial); } SDKShaders.StartRendering(); SDKShaders.StartForegroundRendering(); InvokePreRenderForeground(); SendTextureToBridge(_foregroundRenderTexture, TEXTURE_ID.FOREGROUND_COLOR_BUFFER_ID); _cameraInstance.Render(); InvokePostRenderForeground(); _cameraInstance.targetTexture = null; SDKShaders.StopForegroundRendering(); SDKShaders.StopRendering(); if (overridePostProcessing || fixPostEffectsAlpha) { _cameraInstance.RemoveCommandBuffer(_captureTextureEvent, _captureTextureCommandBuffer); _cameraInstance.RemoveCommandBuffer(_applyTextureEvent, _applyTextureCommandBuffer); _captureTextureCommandBuffer.Clear(); _applyTextureCommandBuffer.Clear(); RenderTexture.ReleaseTemporary(tempRenderTexture); } _cameraInstance.RemoveCommandBuffer(_clipPlaneCameraEvent, _clipPlaneCommandBuffer); _cameraInstance.RemoveCommandBuffer(_clipPlaneCombineAlphaCameraEvent, _combineAlphaCommandBuffer); RenderTexture.ReleaseTemporary(capturedAlphaRenderTexture); _clipPlaneCommandBuffer.Clear(); _combineAlphaCommandBuffer.Clear(); // Revert camera defaults _cameraInstance.clearFlags = capturedClearFlags; _cameraInstance.backgroundColor = capturedBgColor; RenderSettings.fogColor = capturedFogColor; SDKUtils.RestoreStandardAssets(ref behaviours, ref wasBehaviourEnabled); }