/// <inheritdoc />
        private void OnPreCull()
        {
            if (!ReadingModeEnabled)
            {
                return;
            }

            const float ResolutionScale = 45.0f / 33.0f;

            StartCoroutine(ResetViewMatricesOnFrameEnd());

            Matrix4x4 leftProj  = CameraCache.Main.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
            Matrix4x4 rightProj = CameraCache.Main.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);

            leftProj.m00  *= ResolutionScale;
            leftProj.m11  *= ResolutionScale;
            rightProj.m00 *= ResolutionScale;
            rightProj.m11 *= ResolutionScale;
            CameraCache.Main.SetStereoProjectionMatrix(Camera.StereoscopicEye.Left, leftProj);
            CameraCache.Main.SetStereoProjectionMatrix(Camera.StereoscopicEye.Right, rightProj);

            HolographicFrame holographicFrame = WindowsMixedRealityUtilities.CurrentWindowsHolographicFrame;

            if (holographicFrame != null)
            {
                HolographicFramePrediction prediction = holographicFrame.CurrentPrediction;

                for (int i = 0; i < prediction.CameraPoses.Count; ++i)
                {
                    HolographicCameraPose cameraPose = prediction.CameraPoses[i];

                    if (cameraPose.HolographicCamera.CanOverrideViewport)
                    {
                        HolographicStereoTransform stereoProjection = cameraPose.ProjectionTransform;

                        stereoProjection.Left.M11  *= ResolutionScale;
                        stereoProjection.Left.M22  *= ResolutionScale;
                        stereoProjection.Right.M11 *= ResolutionScale;
                        stereoProjection.Right.M22 *= ResolutionScale;

                        cameraPose.OverrideProjectionTransform(stereoProjection);
                    }
                }
            }
        }
        /// <summary>
        /// Updates the constant buffer for the display with view and projection
        /// matrices for the current frame.
        /// </summary>
        public void UpdateViewProjectionBuffer(
            DeviceResources deviceResources,
            HolographicCameraPose cameraPose,
            SpatialCoordinateSystem coordinateSystem
            )
        {
            // The system changes the viewport on a per-frame basis for system optimizations.
            d3dViewport.X        = (float)cameraPose.Viewport.Left;
            d3dViewport.Y        = (float)cameraPose.Viewport.Top;
            d3dViewport.Width    = (float)cameraPose.Viewport.Width;
            d3dViewport.Height   = (float)cameraPose.Viewport.Height;
            d3dViewport.MinDepth = 0;
            d3dViewport.MaxDepth = 1;

            // The projection transform for each frame is provided by the HolographicCameraPose.
            HolographicStereoTransform cameraProjectionTransform = cameraPose.ProjectionTransform;

            // Get a container object with the view and projection matrices for the given
            // pose in the given coordinate system.
            HolographicStereoTransform?viewTransformContainer = cameraPose.TryGetViewTransform(coordinateSystem);

            // If TryGetViewTransform returns null, that means the pose and coordinate system
            // cannot be understood relative to one another; content cannot be rendered in this
            // coordinate system for the duration of the current frame.
            // This usually means that positional tracking is not active for the current frame, in
            // which case it is possible to use a SpatialLocatorAttachedFrameOfReference to render
            // content that is not world-locked instead.
            ViewProjectionConstantBuffer viewProjectionConstantBufferData = new ViewProjectionConstantBuffer();
            bool viewTransformAcquired = viewTransformContainer.HasValue;

            if (viewTransformAcquired)
            {
                // Otherwise, the set of view transforms can be retrieved.
                HolographicStereoTransform viewCoordinateSystemTransform = viewTransformContainer.Value;

                // Update the view matrices. Holographic cameras (such as Microsoft HoloLens) are
                // constantly moving relative to the world. The view matrices need to be updated
                // every frame.
                viewProjectionConstantBufferData.viewProjectionLeft = Matrix4x4.Transpose(
                    viewCoordinateSystemTransform.Left * cameraProjectionTransform.Left
                    );
                viewProjectionConstantBufferData.viewProjectionRight = Matrix4x4.Transpose(
                    viewCoordinateSystemTransform.Right * cameraProjectionTransform.Right
                    );
            }

            // Use the D3D device context to update Direct3D device-based resources.
            var context = deviceResources.D3DDeviceContext;

            // Loading is asynchronous. Resources must be created before they can be updated.
            if (context == null || viewProjectionConstantBuffer == null || !viewTransformAcquired)
            {
                framePending = false;
            }
            else
            {
                // Update the view and projection matrices.
                context.UpdateSubresource(ref viewProjectionConstantBufferData, viewProjectionConstantBuffer);

                framePending = true;
            }
        }