/// <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; } }