/// <summary> /// Create VR swap texture set /// </summary> /// <returns>The result creation vr texture swap</returns> private OVR.ovrResult CreateVRSwapTextureSet() { var renderTargetManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager; OVR.ovrResult result; this.recommendedTextureSize = new OVR.Sizei[2]; this.recommendedTextureSize[0] = this.Hmd.GetFovTextureSize(OVR.EyeType.Left, this.Hmd.DefaultEyeFov[0], 1); this.recommendedTextureSize[1] = this.Hmd.GetFovTextureSize(OVR.EyeType.Right, this.Hmd.DefaultEyeFov[1], 1); int rtWidth = this.recommendedTextureSize[0].Width + this.recommendedTextureSize[1].Width; int rtHeight = Math.Max(this.recommendedTextureSize[0].Height, this.recommendedTextureSize[1].Height); var eyeDepthTexture = renderTargetManager.CreateDepthTexture(rtWidth, rtHeight, this.msaaSampleCount); if (this.msaaSampleCount > 1) { // Create MSAA renderTarget this.msaaRenderTarget = renderTargetManager.CreateRenderTarget(rtWidth, rtHeight, PixelFormat.R8G8BA8_sRGB, this.msaaSampleCount); this.msaaRenderTarget.DepthTexture = eyeDepthTexture; } // Define a texture at the size recommended for the eye texture. Texture2DDescription eyeSwapTextureDescription = new Texture2DDescription(); eyeSwapTextureDescription.Width = rtWidth; eyeSwapTextureDescription.Height = rtHeight; eyeSwapTextureDescription.ArraySize = 1; eyeSwapTextureDescription.MipLevels = 1; eyeSwapTextureDescription.Format = Format.R8G8B8A8_UNorm_SRgb; eyeSwapTextureDescription.SampleDescription = new SampleDescription(1, 0); eyeSwapTextureDescription.Usage = ResourceUsage.Default; eyeSwapTextureDescription.CpuAccessFlags = CpuAccessFlags.None; eyeSwapTextureDescription.BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget; // Convert the SharpDX texture description to the native Direct3D texture description. OVR.D3D11.D3D11_TEXTURE2D_DESC swapTextureDescriptionD3D11 = OculusVRHelpers.CreateTexture2DDescription(eyeSwapTextureDescription); // Create a SwapTextureSet, which will contain the textures to render to, for the current eye. result = this.Hmd.CreateSwapTextureSetD3D11(this.device.NativePointer, ref swapTextureDescriptionD3D11, OVR.D3D11.SwapTextureSetD3D11Flags.None, out this.eyeSwapTextureSet); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create swap texture set."); this.swapRenderTargets = new RenderTarget[this.eyeSwapTextureSet.TextureCount]; // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet. for (int textureIndex = 0; textureIndex < this.eyeSwapTextureSet.TextureCount; textureIndex++) { // Retrieve the current textureData object. OVR.D3D11.D3D11TextureData textureData = this.eyeSwapTextureSet.Textures[textureIndex]; this.swapRenderTargets[textureIndex] = renderTargetManager.CreateRenderTarget(textureData.Texture); if (this.msaaSampleCount == 1) { this.swapRenderTargets[textureIndex].DepthTexture = eyeDepthTexture; } } return(result); }
/// <summary> /// OVRRender renderer /// </summary> protected override void Render() { OVRTypes.Result result; int currentIndex = 0; if (this.IsConnected) { double frameTiming = this.Hmd.GetPredictedDisplayTime(0); OVRTypes.TrackingState trackingState = this.Hmd.GetTrackingState(frameTiming, true); // Update tracker camera pose var trackerPoseOVR = this.Hmd.GetTrackerPose(0); trackerPoseOVR.Pose.Position.ToVector3(out this.trackerCameraPose.Position); trackerPoseOVR.Pose.Orientation.ToQuaternion(out this.trackerCameraPose.Orientation); // Update controller poses var leftControllerPoseOVR = trackingState.HandPoses[(int)HandType.Left]; leftControllerPoseOVR.ThePose.Position.ToVector3(out this.leftControllerPose.Position); leftControllerPoseOVR.ThePose.Orientation.ToQuaternion(out this.leftControllerPose.Orientation); var rightControllerPoseOVR = trackingState.HandPoses[(int)HandType.Right]; rightControllerPoseOVR.ThePose.Position.ToVector3(out this.rightControllerPose.Position); rightControllerPoseOVR.ThePose.Orientation.ToQuaternion(out this.rightControllerPose.Orientation); // Calculate the position and orientation of each eye. this.Oculus.CalcEyePoses(trackingState.HeadPose.ThePose, this.hmdToEyeViewOffsets, ref this.oculusEyePoses); // Retrieve the index of the active texture result = this.eyeTextureSwapChain.GetCurrentIndex(out currentIndex); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to retrieve texture swap chain current index."); for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { var eyeTexture = (OculusVREyeTexture)this.eyeProperties[eyeIndex].Texture; var eyePose = this.eyeProperties[eyeIndex].Pose; this.oculusEyePoses[eyeIndex].Position.ToVector3(out eyePose.Position); this.oculusEyePoses[eyeIndex].Orientation.ToQuaternion(out eyePose.Orientation); this.eyeProperties[eyeIndex].Pose = eyePose; eyeTexture.RenderTarget = (this.msaaSampleCount > 1) ? this.msaaRenderTarget : this.swapRenderTargets[currentIndex]; // Get eye projection var eyeProjection = this.eyeProperties[eyeIndex].Projection; this.Oculus.Matrix4f_Projection(eyeTexture.FieldOfView, eyeTexture.NearPlane, eyeTexture.FarPlane, OVRTypes.ProjectionModifier.None).ToMatrix(out eyeProjection); this.eyeProperties[eyeIndex].Projection = eyeProjection; this.layerEyeFov.RenderPose[eyeIndex] = this.oculusEyePoses[eyeIndex]; } // Commits any pending changes to the TextureSwapChain, and advances its current index result = this.eyeTextureSwapChain.Commit(); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to commit the swap chain texture."); // Calc central pose var leftEyePose = this.eyeProperties[(int)VREyeType.LeftEye].Pose; var rightEyePose = this.eyeProperties[(int)VREyeType.RightEye].Pose; var centerEyePose = this.eyeProperties[(int)VREyeType.CenterEye].Pose; Vector3.Lerp(ref leftEyePose.Position, ref rightEyePose.Position, 0.5f, out centerEyePose.Position); Quaternion.Lerp(ref leftEyePose.Orientation, ref rightEyePose.Orientation, 0.5f, out centerEyePose.Orientation); this.eyeProperties[(int)VREyeType.CenterEye].Pose = centerEyePose; } base.Render(); if (this.IsConnected) { if (this.msaaSampleCount > 1) { var rtManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager; var dxRt = rtManager.TargetFromHandle <DXRenderTarget>(this.msaaRenderTarget.TextureHandle); var dxSwapRt = rtManager.TargetFromHandle <DXRenderTarget>(this.swapRenderTargets[currentIndex].TextureHandle); this.context.ResolveSubresource(dxRt.Target, 0, dxSwapRt.Target, 0, Format.R8G8B8A8_UNorm_SRgb); } // Submit frame to HMD result = this.Hmd.SubmitFrame(0, this.ovrLayers); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to submit the frame of the current layers."); if (this.ShowHMDMirrorTexture) { // Show mirror texture into BackBuffer this.device.ImmediateContext.CopyResource(this.mirrorTexture, this.backBuffer); } } }
/// <summary> /// Create VR swap texture set /// </summary> /// <returns>The result creation vr texture swap</returns> private OVRTypes.Result CreateVRSwapTextureSet() { var renderTargetManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager; OVRTypes.Result result; this.recommendedTextureSize = new OVRTypes.Sizei[2]; this.recommendedTextureSize[0] = this.Hmd.GetFovTextureSize(OVRTypes.EyeType.Left, this.Hmd.DefaultEyeFov[0], 1); this.recommendedTextureSize[1] = this.Hmd.GetFovTextureSize(OVRTypes.EyeType.Right, this.Hmd.DefaultEyeFov[1], 1); int rtWidth = this.recommendedTextureSize[0].Width + this.recommendedTextureSize[1].Width; int rtHeight = Math.Max(this.recommendedTextureSize[0].Height, this.recommendedTextureSize[1].Height); var eyeDepthTexture = renderTargetManager.CreateDepthTexture(rtWidth, rtHeight, this.msaaSampleCount); if (this.msaaSampleCount > 1) { // Create MSAA renderTarget this.msaaRenderTarget = renderTargetManager.CreateRenderTarget(rtWidth, rtHeight, PixelFormat.R8G8BA8_sRGB, this.msaaSampleCount); this.msaaRenderTarget.DepthTexture = eyeDepthTexture; } // Define a texture at the size recommended for the eye texture. OVRTypes.TextureSwapChainDesc eyeSwapTextureDescription = new OVRTypes.TextureSwapChainDesc() { Type = OVRTypes.TextureType.Texture2D, Format = OVRTypes.TextureFormat.R8G8B8A8_UNORM_SRGB, ArraySize = 1, Width = rtWidth, Height = rtHeight, MipLevels = 1, SampleCount = 1, StaticImage = 0, MiscFlags = OVRTypes.TextureMiscFlags.None, BindFlags = OVRTypes.TextureBindFlags.DX_RenderTarget }; // Create a SwapTextureSet, which will contain the textures to render to, for the current eye. result = this.Hmd.CreateTextureSwapChainDX(this.device.NativePointer, eyeSwapTextureDescription, out this.eyeTextureSwapChain); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create swap texture set."); // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet. int textureCount = 0; this.eyeTextureSwapChain.GetLength(out textureCount); this.swapRenderTargets = new RenderTarget[textureCount]; for (int textureIndex = 0; textureIndex < textureCount; textureIndex++) { // Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer. IntPtr swapChainTextureComPtr = IntPtr.Zero; this.eyeTextureSwapChain.GetBufferDX(textureIndex, this.textureInterfaceId, out swapChainTextureComPtr); this.swapRenderTargets[textureIndex] = renderTargetManager.CreateRenderTarget(swapChainTextureComPtr); if (this.msaaSampleCount == 1) { this.swapRenderTargets[textureIndex].DepthTexture = eyeDepthTexture; } } return(result); }
/// <summary> /// OVR initialization /// </summary> private void OVRInitialization() { try { this.adapter.GraphicsDevice.IsSrgbModeEnabled = true; var renderTargetManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager; OVRTypes.Result result; // Retrieve the DXGI device, in order to set the maximum frame latency. using (SharpDX.DXGI.Device1 dxgiDevice = this.device.QueryInterface <SharpDX.DXGI.Device1>()) { dxgiDevice.MaximumFrameLatency = 1; } this.ovrLayers = new Layers(); this.layerEyeFov = this.ovrLayers.AddLayerEyeFov(); // Create a set of layers to submit. this.eyeProperties = new VREye[3]; this.oculusEyePoses = new OVRTypes.Posef[2]; this.hmdToEyeViewOffsets = new OVRTypes.Vector3f[2]; for (int i = 0; i < this.eyeProperties.Length; i++) { this.eyeProperties[i] = new VREye(); } result = this.CreateVRSwapTextureSet(); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create swap texture set."); for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { OVRTypes.EyeType eye = (OVRTypes.EyeType)eyeIndex; OculusVREyeTexture eyeTexture = new OculusVREyeTexture(); this.eyeProperties[eyeIndex].Texture = eyeTexture; // Retrieve size and position of the texture for the current eye. eyeTexture.FieldOfView = this.Hmd.DefaultEyeFov[eyeIndex]; eyeTexture.NearPlane = DefaultNearClip; eyeTexture.FarPlane = DefaultFarClip; eyeTexture.TextureSize = new OVRTypes.Sizei(this.swapRenderTargets[0].Width, this.swapRenderTargets[0].Height); eyeTexture.RenderDescription = this.Hmd.GetRenderDesc(eye, this.Hmd.DefaultEyeFov[eyeIndex]); eyeTexture.HmdToEyeViewOffset = eyeTexture.RenderDescription.HmdToEyeOffset; eyeTexture.ViewportSize.Position = new OVRTypes.Vector2i(this.recommendedTextureSize[0].Width * eyeIndex, 0); eyeTexture.ViewportSize.Size = this.recommendedTextureSize[eyeIndex]; eyeTexture.Viewport = new Viewport( eyeTexture.ViewportSize.Position.x / (float)this.swapRenderTargets[0].Width, eyeTexture.ViewportSize.Position.y / (float)this.swapRenderTargets[0].Height, eyeTexture.ViewportSize.Size.Width / (float)this.swapRenderTargets[0].Width, eyeTexture.ViewportSize.Size.Height / (float)this.swapRenderTargets[0].Height); this.hmdToEyeViewOffsets[eyeIndex] = eyeTexture.HmdToEyeViewOffset; // Specify the texture to show on the HMD. this.layerEyeFov.ColorTexture[eyeIndex] = this.eyeTextureSwapChain.TextureSwapChainPtr; this.layerEyeFov.Viewport[eyeIndex] = eyeTexture.ViewportSize; this.layerEyeFov.Fov[eyeIndex] = eyeTexture.FieldOfView; this.layerEyeFov.Header.Flags = OVRTypes.LayerFlags.HighQuality; } // Define the texture used to display the rendered result on the computer monitor. OVRTypes.MirrorTextureDesc mirrorTextureDescription = new OVRTypes.MirrorTextureDesc() { Format = OVRTypes.TextureFormat.R8G8B8A8_UNORM_SRGB, Width = this.Width, Height = this.Height, MiscFlags = OVRTypes.TextureMiscFlags.None }; OculusWrap.MirrorTexture mirrorTexture; // Create the texture used to display the rendered result on the computer monitor. result = this.Hmd.CreateMirrorTextureDX(this.device.NativePointer, mirrorTextureDescription, out mirrorTexture); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create mirror texture."); // Retrieve the Direct3D texture contained in the Oculus MirrorTexture. IntPtr mirrorTextureComPtr = IntPtr.Zero; result = mirrorTexture.GetBufferDX(this.textureInterfaceId, out mirrorTextureComPtr); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to retrieve the texture from the created mirror texture buffer."); this.mirrorTexture = new Texture2D(mirrorTextureComPtr); this.HMDMirrorRenderTarget = renderTargetManager.CreateRenderTarget(this.mirrorTexture.NativePointer); WaveServices.RegisterService(new OculusVRService(this)); this.IsConnected = true; } catch (Exception e) { Console.WriteLine(e); } }
/// <summary> /// OVR initialization /// </summary> private void OVRInitialization() { try { this.adapter.GraphicsDevice.IsSrgbModeEnabled = true; var renderTargetManager = this.adapter.Graphics.RenderTargetManager as RenderTargetManager; // Specify which head tracking capabilities to enable. this.Hmd.SetEnabledCaps(OVR.HmdCaps.DebugDevice); // Start the sensor which informs of the Rift's pose and motion this.Hmd.ConfigureTracking(OVR.TrackingCaps.ovrTrackingCap_Orientation | OVR.TrackingCaps.ovrTrackingCap_MagYawCorrection | OVR.TrackingCaps.ovrTrackingCap_Position, OVR.TrackingCaps.None); OVR.ovrResult result; // Retrieve the DXGI device, in order to set the maximum frame latency. using (SharpDX.DXGI.Device1 dxgiDevice = device.QueryInterface <SharpDX.DXGI.Device1>()) { dxgiDevice.MaximumFrameLatency = 1; } this.ovrLayers = new Layers(); this.layerEyeFov = this.ovrLayers.AddLayerEyeFov(); // Create a set of layers to submit. this.eyeTextures = new OculusVREyeTexture[2]; this.eyePoses = new VREyePose[3]; this.oculusEyePoses = new OVR.Posef[2]; this.hmdToEyeViewOffsets = new OVR.Vector3f[2]; result = this.CreateVRSwapTextureSet(); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create swap texture set."); for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { OVR.EyeType eye = (OVR.EyeType)eyeIndex; OculusVREyeTexture eyeTexture = new OculusVREyeTexture(); this.eyeTextures[eyeIndex] = eyeTexture; // Retrieve size and position of the texture for the current eye. eyeTexture.FieldOfView = this.Hmd.DefaultEyeFov[eyeIndex]; eyeTexture.NearPlane = DefaultNearClip; eyeTexture.FarPlane = DefaultFarClip; eyeTexture.TextureSize = new OVR.Sizei(this.swapRenderTargets[0].Width, this.swapRenderTargets[0].Height); eyeTexture.RenderDescription = this.Hmd.GetRenderDesc(eye, this.Hmd.DefaultEyeFov[eyeIndex]); eyeTexture.HmdToEyeViewOffset = eyeTexture.RenderDescription.HmdToEyeViewOffset; eyeTexture.ViewportSize.Position = new OVR.Vector2i(this.recommendedTextureSize[0].Width * eyeIndex, 0); eyeTexture.ViewportSize.Size = this.recommendedTextureSize[eyeIndex]; eyeTexture.Viewport = new Viewport( eyeTexture.ViewportSize.Position.x / (float)this.swapRenderTargets[0].Width, eyeTexture.ViewportSize.Position.y / (float)this.swapRenderTargets[0].Height, eyeTexture.ViewportSize.Size.Width / (float)this.swapRenderTargets[0].Width, eyeTexture.ViewportSize.Size.Height / (float)this.swapRenderTargets[0].Height, 0.0f, 1.0f); this.hmdToEyeViewOffsets[eyeIndex] = eyeTexture.HmdToEyeViewOffset; // Specify the texture to show on the HMD. this.layerEyeFov.ColorTexture[eyeIndex] = this.eyeSwapTextureSet.SwapTextureSetPtr; this.layerEyeFov.Viewport[eyeIndex] = eyeTexture.ViewportSize; this.layerEyeFov.Fov[eyeIndex] = eyeTexture.FieldOfView; this.layerEyeFov.Header.Flags = OVR.LayerFlags.HighQuality; } // Define the texture used to display the rendered result on the computer monitor. Texture2DDescription mirrorTextureDescription = new Texture2DDescription(); mirrorTextureDescription.Width = this.Width; mirrorTextureDescription.Height = this.Height; mirrorTextureDescription.ArraySize = 1; mirrorTextureDescription.MipLevels = 1; mirrorTextureDescription.Format = Format.R8G8B8A8_UNorm_SRgb; mirrorTextureDescription.SampleDescription = new SampleDescription(1, 0); mirrorTextureDescription.Usage = ResourceUsage.Default; mirrorTextureDescription.CpuAccessFlags = CpuAccessFlags.None; mirrorTextureDescription.BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget; // Convert the SharpDX texture description to the native Direct3D texture description. OVR.D3D11.D3D11_TEXTURE2D_DESC mirrorTextureDescriptionD3D11 = OculusVRHelpers.CreateTexture2DDescription(mirrorTextureDescription); OculusWrap.D3D11.MirrorTexture mirrorTexture; // Create the texture used to display the rendered result on the computer monitor. result = this.Hmd.CreateMirrorTextureD3D11(device.NativePointer, ref mirrorTextureDescriptionD3D11, OVR.D3D11.SwapTextureSetD3D11Flags.None, out mirrorTexture); OculusVRHelpers.WriteErrorDetails(this.Oculus, result, "Failed to create mirror texture."); this.mirrorTexture = new Texture2D(mirrorTexture.Texture.Texture); this.HMDMirrorRenderTarget = renderTargetManager.CreateRenderTarget(this.mirrorTexture.NativePointer); WaveServices.RegisterService(new OculusVRService(this)); this.IsConnected = true; } catch (Exception e) { Console.WriteLine(e); } }