/// <summary> /// /// </summary> public override void CreateDisplayResources() { base.CreateDisplayResources(); backbufferColor = new RenderTarget2D(device, swapChain.GetBackBuffer <D3D.Texture2D>(0)); oculusSwapChains = new OculusTextureSwapChain[2]; eyeTextures = new EyeTexture[2]; for (int i = 0; i < 2; i++) { OVR.Sizei idealSize = hmd.GetFovTextureSize((OVR.EyeType)i, hmd.DefaultEyeFov[i], 1.0f); oculusSwapChains[i] = hmd.CreateTextureSwapChain(d3dDevice.NativePointer, idealSize.Width, idealSize.Height); eyeTextures[i] = new EyeTexture(device, oculusSwapChains[i]) { DepthStencil2D = new DepthStencil2D(device, DepthFormat.D24S8, idealSize.Width, idealSize.Height), Viewport = new Viewport(0, 0, idealSize.Width, idealSize.Height), ViewportSize = new OVR.Recti(new OVR.Vector2i(0, 0), new OVR.Sizei { Width = idealSize.Width, Height = idealSize.Height }) }; //eyeTextures[i].DepthBufferDescription = new Texture2DDescription { // Width = idealSize.Width, // Height = idealSize.Height, // ArraySize = 1, // MipLevels = 1, // Format = Format.D32_Float, // CpuAccessFlags = CpuAccessFlags.None, // Usage = ResourceUsage.Default, // BindFlags = BindFlags.DepthStencil, // OptionFlags = ResourceOptionFlags.None, // SampleDescription = new SampleDescription(1, 0) //}; } hmd.CreateMirrorTexture(d3dDevice.NativePointer, new OVR.MirrorTextureDesc { Format = OVR.TextureFormat.OVR_FORMAT_R8G8B8A8_UNORM_SRGB, Width = backbufferColor.Width, Height = backbufferColor.Height, MiscFlags = OVR.TextureMiscFlags.None }, out mirrorTexture); layers = new Layers(); layerEyeFov = layers.AddLayerEyeFov(); hmd.SetTrackingOriginType(OVR.TrackingOrigin.EyeLevel); frameIndex = 0; Game.RenderSystem.Width = eyeTextures[0].Viewport.Width; Game.RenderSystem.Height = eyeTextures[0].Viewport.Height; }
protected override void Initialize() { base.Initialize(); if (UsePsMove) { var manager = new PSMoveManager(); manager.Initialize(); ToDispose(manager); PsMoveController = new PSMoveController(Vector3.Zero); ToDispose(PsMoveController); PsMoveController.OnButtonSelectPressed += (sender, args) => PsMoveController.ResetYaw(); PsMoveController.OnButtonStartPressed += (sender, args) => PsMoveController.ResetYaw(); } eyeTexture[0] = hmd.CreateSwapTexture(GraphicsDevice, Format.B8G8R8A8_UNorm, hmd.GetFovTextureSize(EyeType.Left, hmd.DefaultEyeFov[0]), true); eyeTexture[1] = hmd.CreateSwapTexture(GraphicsDevice, Format.B8G8R8A8_UNorm, hmd.GetFovTextureSize(EyeType.Right, hmd.DefaultEyeFov[1]), true); ToDispose(eyeTexture[0]); ToDispose(eyeTexture[1]); // Create our layer layerEyeFov = new LayerEyeFov { Header = new LayerHeader(LayerType.EyeFov, LayerFlags.None), ColorTextureLeft = eyeTexture[0].TextureSet, ColorTextureRight = eyeTexture[1].TextureSet, ViewportLeft = new Rect(0, 0, eyeTexture[0].Size.Width, eyeTexture[0].Size.Height), ViewportRight = new Rect(0, 0, eyeTexture[1].Size.Width, eyeTexture[1].Size.Height), FovLeft = hmd.DefaultEyeFov[0], FovRight = hmd.DefaultEyeFov[1], }; // Keep eye view offsets eyeRenderDesc[0] = hmd.GetRenderDesc(EyeType.Left, hmd.DefaultEyeFov[0]); eyeRenderDesc[1] = hmd.GetRenderDesc(EyeType.Right, hmd.DefaultEyeFov[1]); hmdToEyeViewOffset[0] = eyeRenderDesc[0].HmdToEyeViewOffset; hmdToEyeViewOffset[1] = eyeRenderDesc[1].HmdToEyeViewOffset; // Create a mirror texture mirrorTexture = hmd.CreateMirrorTexture(GraphicsDevice, GraphicsDevice.BackBuffer.Description); // Set presentation interval to immediate as SubmitFrame will be taking care of VSync GraphicsDevice.Presenter.PresentInterval = PresentInterval.Immediate; // Configure tracking hmd.ConfigureTracking( TrackingCapabilities.Orientation | TrackingCapabilities.Position | TrackingCapabilities.MagYawCorrection, TrackingCapabilities.None); // Set enabled capabilities hmd.EnabledCaps = HMDCapabilities.LowPersistence | HMDCapabilities.DynamicPrediction; }
protected override void Initialize() { Window.Title = "CsEx"; // Create our render target eyeTexture[0] = hmd.CreateSwapTexture(GraphicsDevice, Format.R8G8B8A8_UNorm, hmd.GetFovTextureSize(EyeType.Left, hmd.DefaultEyeFov[0]), true); eyeTexture[1] = hmd.CreateSwapTexture(GraphicsDevice, Format.R8G8B8A8_UNorm, hmd.GetFovTextureSize(EyeType.Right, hmd.DefaultEyeFov[1]), true); // Create our layer layerEyeFov = new LayerEyeFov { Header = new LayerHeader(LayerType.EyeFov, LayerFlags.None), ColorTextureLeft = eyeTexture[0].TextureSet, ColorTextureRight = eyeTexture[1].TextureSet, ViewportLeft = new Rect(0, 0, eyeTexture[0].Size.Width, eyeTexture[0].Size.Height), ViewportRight = new Rect(0, 0, eyeTexture[1].Size.Width, eyeTexture[1].Size.Height), FovLeft = hmd.DefaultEyeFov[0], FovRight = hmd.DefaultEyeFov[1] }; // Keep eye view offsets eyeRenderDesc[0] = hmd.GetRenderDesc(EyeType.Left, hmd.DefaultEyeFov[0]); eyeRenderDesc[1] = hmd.GetRenderDesc(EyeType.Right, hmd.DefaultEyeFov[1]); hmdToEyeViewOffset[0] = eyeRenderDesc[0].HmdToEyeViewOffset; hmdToEyeViewOffset[1] = eyeRenderDesc[1].HmdToEyeViewOffset; // Create a mirror Texture mirrorTexture = hmd.CreateMirrorTexture(GraphicsDevice, GraphicsDevice.BackBuffer.Description); // Set presentation interval to immediate as SubmitFrame will be taking care of VSync GraphicsDevice.Presenter.PresentInterval = PresentInterval.Immediate; // Configure tracking hmd.ConfigureTracking(TrackingCapabilities.Orientation | TrackingCapabilities.Position | TrackingCapabilities.MagYawCorrection, TrackingCapabilities.None); // Set enabled capabilities hmd.EnabledCaps = HMDCapabilities.LowPersistence | HMDCapabilities.DynamicPrediction; base.Initialize(); }
/// <summary> /// CreateResources is called when the VirtualRealityProvider is initialized and should create the DirectX resources. /// </summary> /// <remarks> /// <para> /// <b>CreateResources</b> is called when the VirtualRealityProvider is initialized and should create the DirectX resources. /// </para> /// <para> /// This method is called after this virtual reality provider is registered with calling the <see cref="DXScene.InitializeVirtualRealityRendering"/> method. /// This method then calls the <see cref="DXSceneResource.InitializeResources"/> and the <see cref="VirtualRealityProviderBase.OnInitializeResources"/>. /// OnInitializeResources calls the this CreateResources method and then <see cref="VirtualRealityProviderBase.InitializeRenderingSteps"/> method. /// </para> /// <para> /// This method usually creates pixel shaders and constant buffers. /// Other resources (back buffers and views) are usually created in <see cref="VirtualRealityProviderBase.UpdateRenderingContext"/> where the size of the current back buffer is compared with the size of back buffers for virtual reality. /// </para> /// </remarks> /// <param name="dxScene">parent DXScene</param> protected override void CreateResources(DXScene dxScene) { if (_eyeTextureSwapChains != null) { if (_eyeTextureSwapChains[0] != null) { _eyeTextureSwapChains[0].Dispose(); } if (_eyeTextureSwapChains[1] != null) { _eyeTextureSwapChains[1].Dispose(); } } else { _eyeTextureSwapChains = new OculusTextureSwapChain[2]; } _eyeTextureSwapChains[0] = new OculusTextureSwapChain(_ovr, _sessionPtr, dxScene.Device, EyeType.Left, Format.B8G8R8A8_UNorm_SRgb, _ovr.GetFovTextureSize(_sessionPtr, EyeType.Left, _hmdDesc.DefaultEyeFov[0], 1.0f), createDepthStencilView: true, isDebugDevice: dxScene.DXDevice.IsDebugDevice); _eyeTextureSwapChains[1] = new OculusTextureSwapChain(_ovr, _sessionPtr, dxScene.Device, EyeType.Left, Format.B8G8R8A8_UNorm_SRgb, _ovr.GetFovTextureSize(_sessionPtr, EyeType.Right, _hmdDesc.DefaultEyeFov[1], 1.0f), createDepthStencilView: true, isDebugDevice: dxScene.DXDevice.IsDebugDevice); _layerShared = new LayerEyeFov(); _layerShared.Header = new LayerHeader() { Type = LayerType.EyeFov, Flags = LayerFlags.HighQuality }; // Specify the texture to show on the HMD. _layerShared.ColorTextureLeft = _eyeTextureSwapChains[0].TextureSwapChainPtr; _layerShared.ColorTextureRight = _eyeTextureSwapChains[1].TextureSwapChainPtr; _layerShared.ViewportLeft.Position = new Vector2i(0, 0); _layerShared.ViewportLeft.Size = _eyeTextureSwapChains[0].Size; _layerShared.ViewportRight.Position = new Vector2i(0, 0); _layerShared.ViewportRight.Size = _eyeTextureSwapChains[1].Size; _layerShared.FovLeft = _hmdDesc.DefaultEyeFov[0]; _layerShared.FovRight = _hmdDesc.DefaultEyeFov[1]; _eyeRenderDesc[0] = _ovr.GetRenderDesc(_sessionPtr, EyeType.Left, _hmdDesc.DefaultEyeFov[0]); _hmdToEyeOffset[1] = _eyeRenderDesc[1].HmdToEyePose.Position; _eyeRenderDesc[1] = _ovr.GetRenderDesc(_sessionPtr, EyeType.Right, _hmdDesc.DefaultEyeFov[1]); _hmdToEyeOffset[1] = _eyeRenderDesc[1].HmdToEyePose.Position; // Create MSAA back buffer if needed UpdateMsaaBackBuffer(_eyeTextureSwapChains[0].Size.Width, _eyeTextureSwapChains[0].Size.Height, _multisamplingCount); _mirrorTextureDesc = new MirrorTextureDesc() { Format = SharpDXHelpers.GetTextureFormat(dxScene.BackBufferDescription.Format), Height = dxScene.BackBufferDescription.Height, MiscFlags = dxScene.BackBufferDescription.MipLevels != 1 ? TextureMiscFlags.AllowGenerateMips : TextureMiscFlags.None, Width = dxScene.BackBufferDescription.Width }; // FloorLevel will give tracking poses where the floor height is 0 _ovr.SetTrackingOriginType(_sessionPtr, TrackingOrigin.EyeLevel); IntPtr mirrorTexturePtr; var result = _ovr.CreateMirrorTextureDX(_sessionPtr, dxScene.Device.NativePointer, ref _mirrorTextureDesc, out mirrorTexturePtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to create Oculus mirror texture: " + lastError.ErrorString, lastError.Result); } _mirrorTexture = new OculusMirrorTexture(_ovr, _sessionPtr, mirrorTexturePtr); // Retrieve the Direct3D texture contained in the Oculus MirrorTexture. IntPtr mirrorTextureComPtr; result = _mirrorTexture.GetBufferDX(typeof(Texture2D).GUID, out mirrorTextureComPtr); if (result < Ab3d.OculusWrap.Result.Success) { var lastError = _ovr.GetLastErrorInfo(); throw new OvrException("Failed to retrieve the texture from the created mirror texture buffer: " + lastError.ErrorString, lastError.Result); } // Create a managed Texture2D, based on the unmanaged texture pointer. _mirrorTextureDX = new Texture2D(mirrorTextureComPtr); if (dxScene.DXDevice.IsDebugDevice) { _mirrorTextureDX.DebugName = "OculusMirrorTexture"; } // To prevent DirectX from rendering more then one frame in the background, // we need to set the MaximumFrameLatency to 1. // This prevents occasional dropped frames in Oculus Rift. var dxgiDevice = dxScene.Device.QueryInterface <SharpDX.DXGI.Device1>(); if (dxgiDevice != null) { dxgiDevice.MaximumFrameLatency = 1; dxgiDevice.Dispose(); } _frameIndex = 0; _matrixCamera = new MatrixCamera(); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); InitShader(); InitBuffer(); // Define initialization parameters with debug flag. OVRTypes.InitParams initializationParameters = new OVRTypes.InitParams(); initializationParameters.Flags = OVRTypes.InitFlags.Debug; // Initialize the Oculus runtime. bool success = wrap.Initialize(initializationParameters); if (!success) { MessageBox.Show("Failed to initialize the Oculus runtime library.", "Uh oh", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } // Use the head mounted display. OVRTypes.GraphicsLuid graphicsLuid; hmd = wrap.Hmd_Create(out graphicsLuid); if (hmd == null) { MessageBox.Show("Oculus Rift not detected.", "Uh oh", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } if (hmd.ProductName == string.Empty) { MessageBox.Show("The HMD is not enabled.", "There's a tear in the Rift", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } Console.WriteLine("SDK Version: " + wrap.GetVersionString()); try { for (int i = 0; i < 2; i++) { OVRTypes.Sizei idealTextureSize = hmd.GetFovTextureSize((OVRTypes.EyeType)i, hmd.DefaultEyeFov[i], 1); eyeRenderTexture[i] = new TextureBuffer(wrap, hmd, true, true, idealTextureSize, 1, IntPtr.Zero, 1); eyeDepthBuffer[i] = new DepthBuffer(eyeRenderTexture[i].GetSize(), 0); } // Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution windowSize = new OVRTypes.Sizei(hmd.Resolution.Width / 2, hmd.Resolution.Height / 2); //For image displayed at ordinary monitor - copy of Oculus rendered one. OVRTypes.MirrorTextureDesc mirrorTextureDescription = new OVRTypes.MirrorTextureDesc(); mirrorTextureDescription.Format = OVRTypes.TextureFormat.R8G8B8A8_UNORM_SRGB; mirrorTextureDescription.Width = windowSize.Width; mirrorTextureDescription.Height = windowSize.Height; mirrorTextureDescription.MiscFlags = OVRTypes.TextureMiscFlags.None; // Create the texture used to display the rendered result on the computer monitor. OVRTypes.Result result; result = hmd.CreateMirrorTextureGL(mirrorTextureDescription, out mirrorTexture); WriteErrorDetails(wrap, result, "Failed to create mirror texture."); layerFov = layers.AddLayerEyeFov(); layerFov.Header.Flags = OVRTypes.LayerFlags.TextureOriginAtBottomLeft; // OpenGL Texture coordinates start from bottom left layerFov.Header.Type = OVRTypes.LayerType.EyeFov; // Configure the mirror read buffer uint texId; result = mirrorTexture.GetBufferGL(out texId); WriteErrorDetails(wrap, result, "Failed to retrieve the texture from the created mirror texture buffer."); //Rendertarget for mirror desktop window GL.GenFramebuffers(1, out mirrorFbo); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, mirrorFbo); GL.FramebufferTexture2D(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, texId, 0); GL.FramebufferRenderbuffer(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, 0); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, 0); // Turn off vsync to let the compositor do its magic this.VSync = VSyncMode.Off; //wglSwapIntervalEXT(0); // FloorLevel will give tracking poses where the floor height is 0 result = hmd.SetTrackingOriginType(OVRTypes.TrackingOrigin.FloorLevel); WriteErrorDetails(wrap, result, "Failed to set tracking origin type."); GL.Enable(EnableCap.DepthTest); //DO NOT DELETE IT IN FUTURE UPDATES! } catch { // Release all resources Dispose(layers); if (mirrorFbo != 0) GL.DeleteFramebuffers(1, ref mirrorFbo); Dispose(mirrorTexture); for (int eyeIndex = 0; eyeIndex < 2; ++eyeIndex) { Dispose(eyeRenderTexture[eyeIndex]); Dispose(eyeDepthBuffer[eyeIndex]); } // Disposing the device, before the hmd, will cause the hmd to fail when disposing. // Disposing the device, after the hmd, will cause the dispose of the device to fail. // It looks as if the hmd steals ownership of the device and destroys it, when it's shutting down. // device.Dispose(); Dispose(hmd); Dispose(wrap); } }
protected override void OnRenderFrame(FrameEventArgs e) { base.OnRenderFrame(e); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Vector3 camPos = new Vector3(0, 2, 5); Quaternion camOri = Quaternion.Identity; #if RENDER_OCULUS for (int i = 0; i < 2; i++) { //zoom field of view var fov = new FovPort { DownTan = eyes[i].desc.Fov.DownTan / zoomFactor, UpTan = eyes[i].desc.Fov.UpTan / zoomFactor, LeftTan = eyes[i].desc.Fov.LeftTan / zoomFactor, RightTan = eyes[i].desc.Fov.RightTan / zoomFactor }; eyes[i].proj = OvrDLL.ovrMatrix4f_Projection(fov, 0.1f, 1000.0f, ProjectionModifier.ClipRangeOpenGL); //bind eye fbo bindFbo(eyes[i]); //combine the "camera" position/rotation with the position/rotation of the eye Vector3 finalPos = camPos + (camOri * eyes[i].pose.Position); Matrix4 finalRot = Matrix4.CreateFromQuaternion(camOri * eyes[i].pose.Orientation); //create the view matrix with a lookat basis vectors Vector3 up = eyes[i].pose.Orientation * Vector3.UnitY; Vector3 fwd = eyes[i].pose.Orientation * -Vector3.UnitZ; Matrix4 view = Matrix4.LookAt(finalPos, finalPos + fwd, up); //draw the scene drawScene(view, eyes[i].proj); //commit the swapchain OvrDLL.ovr_CommitTextureSwapChain(session, eyes[i].swapChain); } //send to Oculus LayerEyeFov eyeFov = layers[0] as LayerEyeFov; eyeFov.Header.Flags = LayerFlags.TextureOriginAtBottomLeft; eyeFov.ColorTexture[0] = eyes[0].swapChain; eyeFov.ColorTexture[1] = eyes[1].swapChain; eyeFov.Fov[0] = eyes[0].desc.Fov; eyeFov.Fov[1] = eyes[1].desc.Fov; eyeFov.Viewport[0] = new Recti(new Vector2i(0,0), eyes[0].renderTargetSize); eyeFov.Viewport[1] = new Recti(new Vector2i(0, 0), eyes[1].renderTargetSize); eyeFov.RenderPose[0] = eyes[0].pose; eyeFov.RenderPose[1] = eyes[1].pose; ViewScaleDesc viewScale = new ViewScaleDesc(); result = OvrDLL.ovr_SubmitFrame(session, 0, ref viewScale, layers.GetUnmanagedLayers(), 1); if (result < 0) { Console.WriteLine("Error submitting frame"); OvrDLL.ovr_GetLastErrorInfo(ref error); Console.WriteLine("Last Error Info: {0}-{1}", error.result, error.ErrorString); } //blit mirror to fbo OvrDLL.ovr_GetMirrorTextureBufferGL(session, mirror, ref myMirrorTexture); blitMirror((int)myMirrorTexture); #else Matrix4 view = Matrix4.CreateTranslation(-camPos); Matrix4 proj = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(60.0f), 1.0f, 0.1f, 1000.0f); drawScene(view, proj); #endif SwapBuffers(); }
override protected void Render() { Lock = true; using (Wrap oculus = new Wrap()) { // Initialize the Oculus runtime. if (!oculus.Initialize(initializationParameters)) { throw new HeadsetError("Failed to initialize the Oculus runtime library."); } OVRTypes.GraphicsLuid graphicsLuid; // Create a set of layers to submit. EyeTexture[] eyeTextures = new EyeTexture[2]; // Create a depth buffer, using the same width and height as the back buffer. Texture2DDescription depthBufferDescription = new Texture2DDescription() { Format = Format.D32_Float, ArraySize = 1, MipLevels = 1, Width = 1920, // TODO: FIXME? Height = 1080, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None }; // Define how the depth buffer will be used to filter out objects, based on their distance from the viewer. DepthStencilStateDescription depthStencilStateDescription = new DepthStencilStateDescription() { IsDepthEnabled = true, DepthComparison = Comparison.Less, DepthWriteMask = DepthWriteMask.Zero }; //#if DEBUG // SharpDX.Configuration.EnableObjectTracking = true; //#endif using (Hmd hmd = oculus.Hmd_Create(out graphicsLuid)) // Create DirectX drawing device. using (_device = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.BgraSupport, new SharpDX.Direct3D.FeatureLevel[] { SharpDX.Direct3D.FeatureLevel.Level_10_0 })) // Create DirectX Graphics Interface factory, used to create the swap chain. using (Factory factory = new Factory()) using (DeviceContext immediateContext = _device.ImmediateContext) // Create the depth buffer. using (Texture2D depthBuffer = new Texture2D(_device, depthBufferDescription)) using (DepthStencilView depthStencilView = new DepthStencilView(_device, depthBuffer)) using (DepthStencilState depthStencilState = new DepthStencilState(_device, depthStencilStateDescription)) using (Layers layers = new Layers()) using (_gd = SharpDX.Toolkit.Graphics.GraphicsDevice.New(_device)) using (vrui = new VRUI(_device, _gd)) using (customEffectL = GetCustomEffect(_gd)) using (customEffectR = GetCustomEffect(_gd)) //using (SharpDX.Toolkit.Graphics.GeometricPrimitive primitive = GraphicTools.CreateGeometry(_projection, _gd, false)) { if (hmd == null) { throw new HeadsetError("Oculus Rift not detected."); } if (hmd.ProductName == string.Empty) { throw new HeadsetError("The HMD is not enabled."); } Viewport viewport = new Viewport(0, 0, hmd.Resolution.Width, hmd.Resolution.Height, 0.0f, 1.0f); LayerEyeFov layerEyeFov = layers.AddLayerEyeFov(); // 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; } for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { OVRTypes.EyeType eye = (OVRTypes.EyeType)eyeIndex; var textureSize = hmd.GetFovTextureSize(eye, hmd.DefaultEyeFov[eyeIndex], 1.0f); var renderDescription = hmd.GetRenderDesc(eye, hmd.DefaultEyeFov[eyeIndex]); EyeTexture eyeTexture = eyeTextures[eyeIndex] = new EyeTexture() { // Retrieve size and position of the texture for the current eye. FieldOfView = hmd.DefaultEyeFov[eyeIndex], TextureSize = textureSize, RenderDescription = renderDescription, // Define a texture at the size recommended for the eye texture. Viewport = new Viewport(0, 0, textureSize.Width, textureSize.Height, 0.0f, 1.0f), HmdToEyeViewOffset = renderDescription.HmdToEyeOffset, Texture2DDescription = new Texture2DDescription() { Width = textureSize.Width, Height = textureSize.Height, ArraySize = 1, MipLevels = 1, Format = Format.R8G8B8A8_UNorm_SRgb, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, CpuAccessFlags = CpuAccessFlags.None, BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget } }; eyeTexture.ViewportSize.Position = new OVRTypes.Vector2i(0, 0); eyeTexture.ViewportSize.Size = textureSize; // Convert the SharpDX texture description to the native Direct3D texture description. OVRTypes.TextureSwapChainDesc textureSwapChainDesc = SharpDXHelpers.CreateTextureSwapChainDescription(eyeTexture.Texture2DDescription); AssertSuccess(hmd.CreateTextureSwapChainDX(_device.NativePointer, textureSwapChainDesc, out eyeTexture.SwapTextureSet), oculus, "Failed to create swap chain."); // Retrieve the number of buffers of the created swap chain. int textureSwapChainBufferCount; AssertSuccess(eyeTexture.SwapTextureSet.GetLength(out textureSwapChainBufferCount), oculus, "Failed to retrieve the number of buffers of the created swap chain."); // Create room for each DirectX texture in the SwapTextureSet. eyeTexture.Textures = new Texture2D[textureSwapChainBufferCount]; eyeTexture.RenderTargetViews = new RenderTargetView[textureSwapChainBufferCount]; // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet. for (int textureIndex = 0; textureIndex < textureSwapChainBufferCount; textureIndex++) { // Interface ID of the Direct3D Texture2D interface. Guid textureInterfaceId = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); // Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer. IntPtr swapChainTextureComPtr = IntPtr.Zero; AssertSuccess(eyeTexture.SwapTextureSet.GetBufferDX(textureIndex, textureInterfaceId, out swapChainTextureComPtr), oculus, "Failed to retrieve a texture from the created swap chain."); // Create a managed Texture2D, based on the unmanaged texture pointer. eyeTexture.Textures[textureIndex] = new Texture2D(swapChainTextureComPtr); // Create a render target view for the current Texture2D. eyeTexture.RenderTargetViews[textureIndex] = new RenderTargetView(_device, eyeTexture.Textures[textureIndex]); } // Define the depth buffer, at the size recommended for the eye texture. eyeTexture.DepthBufferDescription = new Texture2DDescription() { Format = Format.D32_Float, Width = eyeTexture.TextureSize.Width, Height = eyeTexture.TextureSize.Height, ArraySize = 1, MipLevels = 1, SampleDescription = new SampleDescription(1, 0), Usage = ResourceUsage.Default, BindFlags = BindFlags.DepthStencil, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None }; // Create the depth buffer. eyeTexture.DepthBuffer = new Texture2D(_device, eyeTexture.DepthBufferDescription); eyeTexture.DepthStencilView = new DepthStencilView(_device, eyeTexture.DepthBuffer); // Specify the texture to show on the HMD. layerEyeFov.ColorTexture[eyeIndex] = eyeTexture.SwapTextureSet.TextureSwapChainPtr; layerEyeFov.Viewport[eyeIndex].Position = new OVRTypes.Vector2i(0, 0); layerEyeFov.Viewport[eyeIndex].Size = eyeTexture.TextureSize; layerEyeFov.Fov[eyeIndex] = eyeTexture.FieldOfView; layerEyeFov.Header.Flags = OVRTypes.LayerFlags.HighQuality; } #region Render loop DateTime startTime = DateTime.Now; DateTime lastTime = DateTime.Now; float deltaTime = 0; // Start with default background SetDefaultScene(); while (!abort) { UpdateContentIfRequested(); OVRTypes.Vector3f[] hmdToEyeViewOffsets = { eyeTextures[0].HmdToEyeViewOffset, eyeTextures[1].HmdToEyeViewOffset }; //OVR.FrameTiming frameTiming = hmd.GetFrameTiming(0); //OVR.TrackingState trackingState = hmd.GetTrackingState(frameTiming.DisplayMidpointSeconds); double displayMidpoint = hmd.GetPredictedDisplayTime(0); OVRTypes.TrackingState trackingState = hmd.GetTrackingState(displayMidpoint, true); OVRTypes.Posef[] eyePoses = new OVRTypes.Posef[2]; // Calculate the position and orientation of each eye. oculus.CalcEyePoses(trackingState.HeadPose.ThePose, hmdToEyeViewOffsets, ref eyePoses); float timeSinceStart = (float)(DateTime.Now - startTime).TotalSeconds; deltaTime = (float)(DateTime.Now - lastTime).TotalSeconds; lastTime = DateTime.Now; Vector3 centerEye = (eyePoses[0].Position.ToVector3() + eyePoses[1].Position.ToVector3()) * 0.5f; for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { OVRTypes.EyeType eye = (OVRTypes.EyeType)eyeIndex; EyeTexture eyeTexture = eyeTextures[eyeIndex]; layerEyeFov.RenderPose[eyeIndex] = eyePoses[eyeIndex]; // Update the render description at each frame, as the HmdToEyeOffset can change at runtime. eyeTexture.RenderDescription = hmd.GetRenderDesc(eye, hmd.DefaultEyeFov[eyeIndex]); // Retrieve the index of the active texture int textureIndex; AssertSuccess(eyeTexture.SwapTextureSet.GetCurrentIndex(out textureIndex), oculus, "Failed to retrieve texture swap chain current index."); immediateContext.OutputMerger.SetRenderTargets(eyeTexture.DepthStencilView, eyeTexture.RenderTargetViews[textureIndex]); immediateContext.ClearRenderTargetView(eyeTexture.RenderTargetViews[textureIndex], Color.Black); immediateContext.ClearDepthStencilView(eyeTexture.DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); immediateContext.Rasterizer.SetViewport(eyeTexture.Viewport); // Retrieve the eye rotation quaternion and use it to calculate the LookAt direction and the LookUp direction. Quaternion lookRotation = SharpDXHelpers.ToQuaternion(eyePoses[eyeIndex].Orientation); lookRotation = new Quaternion(1, 0, 0, 0) * lookRotation; Matrix rotationMatrix = Matrix.RotationQuaternion(lookRotation); Vector3 lookUp = Vector3.Transform(new Vector3(0, -1, 0), rotationMatrix).ToVector3(); Vector3 lookAt = Vector3.Transform(new Vector3(0, 0, 1), rotationMatrix).ToVector3(); //Vector3 eyeDiff = eyePoses[eyeIndex].Position.ToVector3() - eyePoses[1 - eyeIndex].Position.ToVector3(); Vector3 lookPosition = new Vector3( -eyePoses[eyeIndex].Position.X, eyePoses[eyeIndex].Position.Y, eyePoses[eyeIndex].Position.Z ); Matrix worldMatrix = Matrix.Translation(lookPosition); Matrix viewMatrix = Matrix.LookAtLH(lookPosition, lookPosition + lookAt, lookUp); Matrix projectionMatrix = oculus.Matrix4f_Projection(eyeTexture.FieldOfView, 0.1f, 100.0f, OVRTypes.ProjectionModifier.LeftHanded).ToMatrix(); projectionMatrix.Transpose(); Matrix MVP = worldMatrix * viewMatrix * projectionMatrix; customEffectL.Parameters["WorldViewProj"].SetValue(MVP); customEffectR.Parameters["WorldViewProj"].SetValue(MVP); lock (localCritical) { try { if (eyeIndex == 0) { primitive?.Draw(customEffectL); } if (eyeIndex == 1) { primitive?.Draw(customEffectR); } } catch (NullReferenceException) { ; } } if (ProvideLook != null && eyeIndex == 0) { lookRotation.Invert(); lookRotation = lookRotation * new Quaternion(1, 0, 0, 0); // rotate 180 in x Vector3 forward = Vector3.Transform(Vector3.ForwardRH, lookRotation); Vector3 up = Vector3.Transform(Vector3.Up, lookRotation); log.Publish("oculus.forward", forward.ToString("0.00")); log.Publish("oculus.up", up.ToString("0.00")); log.Publish("oculus.lookAt", lookAt.ToString("0.00")); log.Publish("oculus.lookUp", lookUp.ToString("0.00")); log.Publish("oculus.vr_quat", lookRotation); log.Publish("q.sent", lookRotation); ProvideLook(lookPosition, lookRotation, OculusFOV); } // reset UI position every frame if it is not visible if (vrui.isUIHidden) { vrui.SetWorldPosition(viewMatrix.Forward, lookPosition, false); } vrui.Draw(Media, currentTime, Duration); vrui.Render(deltaTime, viewMatrix, projectionMatrix, lookPosition, ShouldShowVRUI); // Commits any pending changes to the TextureSwapChain, and advances its current index AssertSuccess(eyeTexture.SwapTextureSet.Commit(), oculus, "Failed to commit the swap chain texture."); //Console.WriteLine("xbox: " + ((hmd.ovr_GetConnectedControllerTypes() & OVRTypes.ControllerType.XBox) != 0)); //Console.WriteLine("remote: " + ((hmd.ovr_GetConnectedControllerTypes() & OVRTypes.ControllerType.Remote) != 0)); //Console.WriteLine("active: " + hmd.GetInputState(OVRTypes.ControllerType.Active)); //Console.WriteLine("buttons: " + hmd.GetInputState(OVRTypes.ControllerType.Remote).Buttons); } hmd.SubmitFrame(0, layers); } #endregion //debugWindow.Stop(); waitForRendererStop.Set(); // Release all resources primitive?.Dispose(); eyeTextures[0].Dispose(); eyeTextures[1].Dispose(); immediateContext.ClearState(); immediateContext.Flush(); } } Lock = false; }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); InitShader(); InitBuffer(); // Initialize the Oculus runtime. bool success = wrap.Initialize(); if (!success) { MessageBox.Show("Failed to initialize the Oculus runtime library.", "Uh oh", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } // Use the head mounted display. OVR.GraphicsLuid graphicsLuid; hmd = wrap.Hmd_Create(out graphicsLuid); if (hmd == null) { MessageBox.Show("Oculus Rift not detected.", "Uh oh", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } if (hmd.ProductName == string.Empty) { MessageBox.Show("The HMD is not enabled.", "There's a tear in the Rift", MessageBoxButtons.OK, MessageBoxIcon.Error); Exit(); return; } Console.WriteLine("SDK Version: " + wrap.GetVersionString()); for (int i = 0; i < 2; i++) { OVR.Sizei idealTextureSize = hmd.GetFovTextureSize((OVR.EyeType)i, hmd.DefaultEyeFov[i], 1); eyeRenderTexture[i] = new OvrSharedRendertarget(idealTextureSize.Width, idealTextureSize.Height, hmd); eyeDepthBuffer[i] = new DepthBuffer(eyeRenderTexture[i].Width, eyeRenderTexture[i].Height); } //For image displayed at ordinary monitor - copy of Oculus rendered one. hmd.CreateMirrorTextureGL((uint)All.Srgb8Alpha8, this.Width, this.Height, out mirrorTex); layerFov = layers.AddLayerEyeFov(); layerFov.Header.Flags = OVR.LayerFlags.TextureOriginAtBottomLeft; // OpenGL Texture coordinates start from bottom left layerFov.Header.Type = OVR.LayerType.EyeFov; //Rendertarget for mirror desktop window GL.GenFramebuffers(1, out mirrorFbo); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, mirrorFbo); GL.FramebufferTexture2D(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, mirrorTex.Texture.TexId, 0); GL.FramebufferRenderbuffer(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, 0); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, 0); EyeRenderDesc[0] = hmd.GetRenderDesc(OVR.EyeType.Left, hmd.DefaultEyeFov[0]); EyeRenderDesc[1] = hmd.GetRenderDesc(OVR.EyeType.Right, hmd.DefaultEyeFov[1]); // Specify which head tracking capabilities to enable. hmd.SetEnabledCaps(OVR.HmdCaps.DebugDevice); // Start the sensor //Update SDK 0.8: Usage of ovr_ConfigureTracking is no longer needed unless you want to disable tracking features. By default, ovr_Create enables the full tracking capabilities supported by any given device. //hmd.ConfigureTracking(OVR.TrackingCaps.ovrTrackingCap_Orientation | OVR.TrackingCaps.ovrTrackingCap_MagYawCorrection | OVR.TrackingCaps.ovrTrackingCap_Position, OVR.TrackingCaps.None); this.VSync = VSyncMode.Off; hmd.RecenterPose(); // Init GL GL.Enable(EnableCap.DepthTest); }
/// <summary> /// /// </summary> public override void CreateDisplayResources() { base.CreateDisplayResources(); backbufferColor = new RenderTarget2D(device, swapChain.GetBackBuffer<D3D.Texture2D>(0)); oculusSwapChains = new OculusTextureSwapChain[2]; eyeTextures = new EyeTexture[2]; for (int i = 0; i < 2; i++) { OVR.Sizei idealSize = hmd.GetFovTextureSize((OVR.EyeType)i, hmd.DefaultEyeFov[i], 1.0f); oculusSwapChains[i] = hmd.CreateTextureSwapChain(d3dDevice.NativePointer, idealSize.Width, idealSize.Height); eyeTextures[i] = new EyeTexture(device, oculusSwapChains[i]) { DepthStencil2D = new DepthStencil2D(device, DepthFormat.D24S8, idealSize.Width, idealSize.Height), Viewport = new Viewport(0, 0, idealSize.Width, idealSize.Height), ViewportSize = new OVR.Recti(new OVR.Vector2i(0, 0), new OVR.Sizei {Width = idealSize.Width, Height = idealSize.Height}) }; //eyeTextures[i].DepthBufferDescription = new Texture2DDescription { // Width = idealSize.Width, // Height = idealSize.Height, // ArraySize = 1, // MipLevels = 1, // Format = Format.D32_Float, // CpuAccessFlags = CpuAccessFlags.None, // Usage = ResourceUsage.Default, // BindFlags = BindFlags.DepthStencil, // OptionFlags = ResourceOptionFlags.None, // SampleDescription = new SampleDescription(1, 0) //}; } hmd.CreateMirrorTexture(d3dDevice.NativePointer, new OVR.MirrorTextureDesc { Format = OVR.TextureFormat.OVR_FORMAT_R8G8B8A8_UNORM_SRGB, Width = backbufferColor.Width, Height = backbufferColor.Height, MiscFlags = OVR.TextureMiscFlags.None }, out mirrorTexture); layers = new Layers(); layerEyeFov = layers.AddLayerEyeFov(); hmd.SetTrackingOriginType(OVR.TrackingOrigin.EyeLevel); frameIndex = 0; Game.RenderSystem.Width = eyeTextures[0].Viewport.Width; Game.RenderSystem.Height = eyeTextures[0].Viewport.Height; }
protected void InitializeRift() { // Initialize OVR Library OVR.Initialize(); if (OVR.HmdDetect() < 1) { throw new IndexOutOfRangeException("No Rfft detected"); } // Create our HMD hmd = OVR.HmdCreate(0); if (hmd == null) { throw new IndexOutOfRangeException("Can't create Rift"); } SharpDX.Size2 left = hmd.GetFovTextureSize(EyeType.Left, hmd.DefaultEyeFov[0]); SharpDX.Size2 right = hmd.GetFovTextureSize(EyeType.Right, hmd.DefaultEyeFov[1]); leftEyeWidth = left.Width; leftEyeHeight = left.Height; rightEyeWidth = right.Width; rightEyeHeight = right.Height; // Create our render target eyeTexture[0] = hmd.CreateSwapTexture(RenderContext11.Device, riftFormat, left, false); eyeTexture[1] = hmd.CreateSwapTexture(RenderContext11.Device, riftFormat, right, false); swapTextures[0] = new SwapTextureSetD3D(eyeTexture[0].TextureSet); swapTextures[1] = new SwapTextureSetD3D(eyeTexture[1].TextureSet); // Create our layer layerEyeFov = new LayerEyeFov { Header = new LayerHeader(LayerType.EyeFov, LayerFlags.HighQuality), ColorTextureLeft = eyeTexture[0].TextureSet, ColorTextureRight = eyeTexture[1].TextureSet, ViewportLeft = new Rect(0, 0, eyeTexture[0].Size.Width, eyeTexture[0].Size.Height), ViewportRight = new Rect(0, 0, eyeTexture[1].Size.Width, eyeTexture[1].Size.Height), FovLeft = hmd.DefaultEyeFov[0], FovRight = hmd.DefaultEyeFov[1], }; // Keep eye view offsets eyeRenderDesc[0] = hmd.GetRenderDesc(EyeType.Left, hmd.DefaultEyeFov[0]); eyeRenderDesc[1] = hmd.GetRenderDesc(EyeType.Right, hmd.DefaultEyeFov[1]); hmdToEyeViewOffset[0] = eyeRenderDesc[0].HmdToEyeViewOffset; hmdToEyeViewOffset[1] = eyeRenderDesc[1].HmdToEyeViewOffset; // Create a mirror texture mirrorTexture = hmd.CreateMirrorTexture(RenderContext11.Device, RenderContext11.BackBuffer.Description); mirror = new Texture11(mirrorTexture); // Configure tracking hmd.ConfigureTracking(TrackingCapabilities.Orientation | TrackingCapabilities.Position | TrackingCapabilities.MagYawCorrection, TrackingCapabilities.None); // Set enabled capabilities hmd.EnabledCaps = HMDCapabilities.LowPersistence | HMDCapabilities.DynamicPrediction; riftInit = true; }
private static void Main() { RenderForm form = new RenderForm("OculusWrap SharpDX demo"); IntPtr sessionPtr; InputLayout inputLayout = null; Buffer contantBuffer = null; Buffer vertexBuffer = null; ShaderSignature shaderSignature = null; PixelShader pixelShader = null; ShaderBytecode pixelShaderByteCode = null; VertexShader vertexShader = null; ShaderBytecode vertexShaderByteCode = null; Texture2D mirrorTextureD3D = null; EyeTexture[] eyeTextures = null; DeviceContext immediateContext = null; DepthStencilState depthStencilState = null; DepthStencilView depthStencilView = null; Texture2D depthBuffer = null; RenderTargetView backBufferRenderTargetView = null; Texture2D backBuffer = null; SharpDX.DXGI.SwapChain swapChain = null; Factory factory = null; MirrorTexture mirrorTexture = null; Guid textureInterfaceId = new Guid("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); // Interface ID of the Direct3D Texture2D interface. Result result; OvrWrap OVR = OvrWrap.Create(); // Define initialization parameters with debug flag. InitParams initializationParameters = new InitParams(); initializationParameters.Flags = InitFlags.Debug | InitFlags.RequestVersion; initializationParameters.RequestedMinorVersion = 17; // Initialize the Oculus runtime. string errorReason = null; try { result = OVR.Initialize(initializationParameters); if (result < Result.Success) { errorReason = result.ToString(); } } catch (Exception ex) { errorReason = ex.Message; } if (errorReason != null) { MessageBox.Show("Failed to initialize the Oculus runtime library:\r\n" + errorReason, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Use the head mounted display. sessionPtr = IntPtr.Zero; var graphicsLuid = new GraphicsLuid(); result = OVR.Create(ref sessionPtr, ref graphicsLuid); if (result < Result.Success) { MessageBox.Show("The HMD is not enabled: " + result.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var hmdDesc = OVR.GetHmdDesc(sessionPtr); try { // Create a set of layers to submit. eyeTextures = new EyeTexture[2]; // Create DirectX drawing device. SharpDX.Direct3D11.Device device = new Device(SharpDX.Direct3D.DriverType.Hardware, DeviceCreationFlags.Debug); // Create DirectX Graphics Interface factory, used to create the swap chain. factory = new SharpDX.DXGI.Factory4(); immediateContext = device.ImmediateContext; // Define the properties of the swap chain. SwapChainDescription swapChainDescription = new SwapChainDescription(); swapChainDescription.BufferCount = 1; swapChainDescription.IsWindowed = true; swapChainDescription.OutputHandle = form.Handle; swapChainDescription.SampleDescription = new SampleDescription(1, 0); swapChainDescription.Usage = Usage.RenderTargetOutput | Usage.ShaderInput; swapChainDescription.SwapEffect = SwapEffect.Sequential; swapChainDescription.Flags = SwapChainFlags.AllowModeSwitch; swapChainDescription.ModeDescription.Width = form.Width; swapChainDescription.ModeDescription.Height = form.Height; swapChainDescription.ModeDescription.Format = Format.R8G8B8A8_UNorm; swapChainDescription.ModeDescription.RefreshRate.Numerator = 0; swapChainDescription.ModeDescription.RefreshRate.Denominator = 1; // Create the swap chain. swapChain = new SwapChain(factory, device, swapChainDescription); // Retrieve the back buffer of the swap chain. backBuffer = swapChain.GetBackBuffer <Texture2D>(0); backBufferRenderTargetView = new RenderTargetView(device, backBuffer); // Create a depth buffer, using the same width and height as the back buffer. Texture2DDescription depthBufferDescription = new Texture2DDescription(); depthBufferDescription.Format = Format.D32_Float; depthBufferDescription.ArraySize = 1; depthBufferDescription.MipLevels = 1; depthBufferDescription.Width = form.Width; depthBufferDescription.Height = form.Height; depthBufferDescription.SampleDescription = new SampleDescription(1, 0); depthBufferDescription.Usage = ResourceUsage.Default; depthBufferDescription.BindFlags = BindFlags.DepthStencil; depthBufferDescription.CpuAccessFlags = CpuAccessFlags.None; depthBufferDescription.OptionFlags = ResourceOptionFlags.None; // Define how the depth buffer will be used to filter out objects, based on their distance from the viewer. DepthStencilStateDescription depthStencilStateDescription = new DepthStencilStateDescription(); depthStencilStateDescription.IsDepthEnabled = true; depthStencilStateDescription.DepthComparison = Comparison.Less; depthStencilStateDescription.DepthWriteMask = DepthWriteMask.Zero; // Create the depth buffer. depthBuffer = new Texture2D(device, depthBufferDescription); depthStencilView = new DepthStencilView(device, depthBuffer); depthStencilState = new DepthStencilState(device, depthStencilStateDescription); var viewport = new Viewport(0, 0, hmdDesc.Resolution.Width, hmdDesc.Resolution.Height, 0.0f, 1.0f); immediateContext.OutputMerger.SetDepthStencilState(depthStencilState); immediateContext.OutputMerger.SetRenderTargets(depthStencilView, backBufferRenderTargetView); immediateContext.Rasterizer.SetViewport(viewport); // 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; } var layerEyeFov = new LayerEyeFov(); layerEyeFov.Header.Type = LayerType.EyeFov; layerEyeFov.Header.Flags = LayerFlags.None; for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { EyeType eye = (EyeType)eyeIndex; var eyeTexture = new EyeTexture(); eyeTextures[eyeIndex] = eyeTexture; // Retrieve size and position of the texture for the current eye. eyeTexture.FieldOfView = hmdDesc.DefaultEyeFov[eyeIndex]; eyeTexture.TextureSize = OVR.GetFovTextureSize(sessionPtr, eye, hmdDesc.DefaultEyeFov[eyeIndex], 1.0f); eyeTexture.RenderDescription = OVR.GetRenderDesc(sessionPtr, eye, hmdDesc.DefaultEyeFov[eyeIndex]); eyeTexture.HmdToEyeViewOffset = eyeTexture.RenderDescription.HmdToEyePose.Position; eyeTexture.ViewportSize.Position = new Vector2i(0, 0); eyeTexture.ViewportSize.Size = eyeTexture.TextureSize; eyeTexture.Viewport = new Viewport(0, 0, eyeTexture.TextureSize.Width, eyeTexture.TextureSize.Height, 0.0f, 1.0f); // Define a texture at the size recommended for the eye texture. eyeTexture.Texture2DDescription = new Texture2DDescription(); eyeTexture.Texture2DDescription.Width = eyeTexture.TextureSize.Width; eyeTexture.Texture2DDescription.Height = eyeTexture.TextureSize.Height; eyeTexture.Texture2DDescription.ArraySize = 1; eyeTexture.Texture2DDescription.MipLevels = 1; eyeTexture.Texture2DDescription.Format = Format.R8G8B8A8_UNorm; eyeTexture.Texture2DDescription.SampleDescription = new SampleDescription(1, 0); eyeTexture.Texture2DDescription.Usage = ResourceUsage.Default; eyeTexture.Texture2DDescription.CpuAccessFlags = CpuAccessFlags.None; eyeTexture.Texture2DDescription.BindFlags = BindFlags.ShaderResource | BindFlags.RenderTarget; // Convert the SharpDX texture description to the Oculus texture swap chain description. TextureSwapChainDesc textureSwapChainDesc = SharpDXHelpers.CreateTextureSwapChainDescription(eyeTexture.Texture2DDescription); // Create a texture swap chain, which will contain the textures to render to, for the current eye. IntPtr textureSwapChainPtr; result = OVR.CreateTextureSwapChainDX(sessionPtr, device.NativePointer, ref textureSwapChainDesc, out textureSwapChainPtr); WriteErrorDetails(OVR, result, "Failed to create swap chain."); eyeTexture.SwapTextureSet = new TextureSwapChain(OVR, sessionPtr, textureSwapChainPtr); // Retrieve the number of buffers of the created swap chain. int textureSwapChainBufferCount; result = eyeTexture.SwapTextureSet.GetLength(out textureSwapChainBufferCount); WriteErrorDetails(OVR, result, "Failed to retrieve the number of buffers of the created swap chain."); // Create room for each DirectX texture in the SwapTextureSet. eyeTexture.Textures = new Texture2D[textureSwapChainBufferCount]; eyeTexture.RenderTargetViews = new RenderTargetView[textureSwapChainBufferCount]; // Create a texture 2D and a render target view, for each unmanaged texture contained in the SwapTextureSet. for (int textureIndex = 0; textureIndex < textureSwapChainBufferCount; textureIndex++) { // Retrieve the Direct3D texture contained in the Oculus TextureSwapChainBuffer. IntPtr swapChainTextureComPtr = IntPtr.Zero; result = eyeTexture.SwapTextureSet.GetBufferDX(textureIndex, textureInterfaceId, out swapChainTextureComPtr); WriteErrorDetails(OVR, result, "Failed to retrieve a texture from the created swap chain."); // Create a managed Texture2D, based on the unmanaged texture pointer. eyeTexture.Textures[textureIndex] = new Texture2D(swapChainTextureComPtr); // Create a render target view for the current Texture2D. eyeTexture.RenderTargetViews[textureIndex] = new RenderTargetView(device, eyeTexture.Textures[textureIndex]); } // Define the depth buffer, at the size recommended for the eye texture. eyeTexture.DepthBufferDescription = new Texture2DDescription(); eyeTexture.DepthBufferDescription.Format = Format.D32_Float; eyeTexture.DepthBufferDescription.Width = eyeTexture.TextureSize.Width; eyeTexture.DepthBufferDescription.Height = eyeTexture.TextureSize.Height; eyeTexture.DepthBufferDescription.ArraySize = 1; eyeTexture.DepthBufferDescription.MipLevels = 1; eyeTexture.DepthBufferDescription.SampleDescription = new SampleDescription(1, 0); eyeTexture.DepthBufferDescription.Usage = ResourceUsage.Default; eyeTexture.DepthBufferDescription.BindFlags = BindFlags.DepthStencil; eyeTexture.DepthBufferDescription.CpuAccessFlags = CpuAccessFlags.None; eyeTexture.DepthBufferDescription.OptionFlags = ResourceOptionFlags.None; // Create the depth buffer. eyeTexture.DepthBuffer = new Texture2D(device, eyeTexture.DepthBufferDescription); eyeTexture.DepthStencilView = new DepthStencilView(device, eyeTexture.DepthBuffer); // Specify the texture to show on the HMD. if (eyeIndex == 0) { layerEyeFov.ColorTextureLeft = eyeTexture.SwapTextureSet.TextureSwapChainPtr; layerEyeFov.ViewportLeft.Position = new Vector2i(0, 0); layerEyeFov.ViewportLeft.Size = eyeTexture.TextureSize; layerEyeFov.FovLeft = eyeTexture.FieldOfView; } else { layerEyeFov.ColorTextureRight = eyeTexture.SwapTextureSet.TextureSwapChainPtr; layerEyeFov.ViewportRight.Position = new Vector2i(0, 0); layerEyeFov.ViewportRight.Size = eyeTexture.TextureSize; layerEyeFov.FovRight = eyeTexture.FieldOfView; } } MirrorTextureDesc mirrorTextureDescription = new MirrorTextureDesc(); mirrorTextureDescription.Format = TextureFormat.R8G8B8A8_UNorm_SRgb; mirrorTextureDescription.Width = form.Width; mirrorTextureDescription.Height = form.Height; mirrorTextureDescription.MiscFlags = TextureMiscFlags.None; // Create the texture used to display the rendered result on the computer monitor. IntPtr mirrorTexturePtr; result = OVR.CreateMirrorTextureDX(sessionPtr, device.NativePointer, ref mirrorTextureDescription, out mirrorTexturePtr); WriteErrorDetails(OVR, result, "Failed to create mirror texture."); mirrorTexture = new MirrorTexture(OVR, sessionPtr, mirrorTexturePtr); // Retrieve the Direct3D texture contained in the Oculus MirrorTexture. IntPtr mirrorTextureComPtr = IntPtr.Zero; result = mirrorTexture.GetBufferDX(textureInterfaceId, out mirrorTextureComPtr); WriteErrorDetails(OVR, result, "Failed to retrieve the texture from the created mirror texture buffer."); // Create a managed Texture2D, based on the unmanaged texture pointer. mirrorTextureD3D = new Texture2D(mirrorTextureComPtr); #region Vertex and pixel shader // Create vertex shader. vertexShaderByteCode = ShaderBytecode.CompileFromFile("Shaders.fx", "VertexShaderPositionColor", "vs_4_0"); vertexShader = new VertexShader(device, vertexShaderByteCode); // Create pixel shader. pixelShaderByteCode = ShaderBytecode.CompileFromFile("Shaders.fx", "PixelShaderPositionColor", "ps_4_0"); pixelShader = new PixelShader(device, pixelShaderByteCode); shaderSignature = ShaderSignature.GetInputSignature(vertexShaderByteCode); // Specify that each vertex consists of a single vertex position and color. InputElement[] inputElements = new InputElement[] { new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0), new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0) }; // Define an input layout to be passed to the vertex shader. inputLayout = new InputLayout(device, shaderSignature, inputElements); // Create a vertex buffer, containing our 3D model. vertexBuffer = Buffer.Create(device, BindFlags.VertexBuffer, m_vertices); // Create a constant buffer, to contain our WorldViewProjection matrix, that will be passed to the vertex shader. contantBuffer = new Buffer(device, Utilities.SizeOf <Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0); // Setup the immediate context to use the shaders and model we defined. immediateContext.InputAssembler.InputLayout = inputLayout; immediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList; immediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, sizeof(float) * 4 * 2, 0)); immediateContext.VertexShader.SetConstantBuffer(0, contantBuffer); immediateContext.VertexShader.Set(vertexShader); immediateContext.PixelShader.Set(pixelShader); #endregion DateTime startTime = DateTime.Now; Vector3 position = new Vector3(0, 0, -1); #region Render loop RenderLoop.Run(form, () => { Vector3f[] hmdToEyeViewOffsets = { eyeTextures[0].HmdToEyeViewOffset, eyeTextures[1].HmdToEyeViewOffset }; double displayMidpoint = OVR.GetPredictedDisplayTime(sessionPtr, 0); TrackingState trackingState = OVR.GetTrackingState(sessionPtr, displayMidpoint, true); Posef[] eyePoses = new Posef[2]; // Calculate the position and orientation of each eye. OVR.CalcEyePoses(trackingState.HeadPose.ThePose, hmdToEyeViewOffsets, ref eyePoses); float timeSinceStart = (float)(DateTime.Now - startTime).TotalSeconds; for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++) { EyeType eye = (EyeType)eyeIndex; EyeTexture eyeTexture = eyeTextures[eyeIndex]; if (eyeIndex == 0) { layerEyeFov.RenderPoseLeft = eyePoses[0]; } else { layerEyeFov.RenderPoseRight = eyePoses[1]; } // Update the render description at each frame, as the HmdToEyeOffset can change at runtime. eyeTexture.RenderDescription = OVR.GetRenderDesc(sessionPtr, eye, hmdDesc.DefaultEyeFov[eyeIndex]); // Retrieve the index of the active texture int textureIndex; result = eyeTexture.SwapTextureSet.GetCurrentIndex(out textureIndex); WriteErrorDetails(OVR, result, "Failed to retrieve texture swap chain current index."); immediateContext.OutputMerger.SetRenderTargets(eyeTexture.DepthStencilView, eyeTexture.RenderTargetViews[textureIndex]); immediateContext.ClearRenderTargetView(eyeTexture.RenderTargetViews[textureIndex], Color.Black); immediateContext.ClearDepthStencilView(eyeTexture.DepthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0); immediateContext.Rasterizer.SetViewport(eyeTexture.Viewport); // Retrieve the eye rotation quaternion and use it to calculate the LookAt direction and the LookUp direction. Quaternion rotationQuaternion = SharpDXHelpers.ToQuaternion(eyePoses[eyeIndex].Orientation); Matrix rotationMatrix = Matrix.RotationQuaternion(rotationQuaternion); Vector3 lookUp = Vector3.Transform(new Vector3(0, -1, 0), rotationMatrix).ToVector3(); Vector3 lookAt = Vector3.Transform(new Vector3(0, 0, 1), rotationMatrix).ToVector3(); Vector3 viewPosition = position - eyePoses[eyeIndex].Position.ToVector3(); Matrix world = Matrix.Scaling(0.1f) * Matrix.RotationX(timeSinceStart / 10f) * Matrix.RotationY(timeSinceStart * 2 / 10f) * Matrix.RotationZ(timeSinceStart * 3 / 10f); Matrix viewMatrix = Matrix.LookAtLH(viewPosition, viewPosition + lookAt, lookUp); Matrix projectionMatrix = OVR.Matrix4f_Projection(eyeTexture.FieldOfView, 0.1f, 100.0f, ProjectionModifier.LeftHanded).ToMatrix(); projectionMatrix.Transpose(); Matrix worldViewProjection = world * viewMatrix * projectionMatrix; worldViewProjection.Transpose(); // Update the transformation matrix. immediateContext.UpdateSubresource(ref worldViewProjection, contantBuffer); // Draw the cube immediateContext.Draw(m_vertices.Length / 2, 0); // Commits any pending changes to the TextureSwapChain, and advances its current index result = eyeTexture.SwapTextureSet.Commit(); WriteErrorDetails(OVR, result, "Failed to commit the swap chain texture."); } result = OVR.SubmitFrame(sessionPtr, 0L, IntPtr.Zero, ref layerEyeFov); WriteErrorDetails(OVR, result, "Failed to submit the frame of the current layers."); immediateContext.CopyResource(mirrorTextureD3D, backBuffer); swapChain.Present(0, PresentFlags.None); }); #endregion } finally { if (immediateContext != null) { immediateContext.ClearState(); immediateContext.Flush(); } // Release all resources Dispose(inputLayout); Dispose(contantBuffer); Dispose(vertexBuffer); Dispose(shaderSignature); Dispose(pixelShader); Dispose(pixelShaderByteCode); Dispose(vertexShader); Dispose(vertexShaderByteCode); Dispose(mirrorTextureD3D); Dispose(mirrorTexture); Dispose(eyeTextures[0]); Dispose(eyeTextures[1]); Dispose(immediateContext); Dispose(depthStencilState); Dispose(depthStencilView); Dispose(depthBuffer); Dispose(backBufferRenderTargetView); Dispose(backBuffer); Dispose(swapChain); Dispose(factory); // Disposing the device, before the hmd, will cause the hmd to fail when disposing. // Disposing the device, after the hmd, will cause the dispose of the device to fail. // It looks as if the hmd steals ownership of the device and destroys it, when it's shutting down. // device.Dispose(); OVR.Destroy(sessionPtr); } }
public void Session_SubmitFrame() { IntPtr sessionPtr = CreateSession(); Assert.AreNotEqual(IntPtr.Zero, sessionPtr); // Define field of view (This is used for both left and right eye). FovPort fieldOfView = new FovPort(); fieldOfView.DownTan = (float)Math.Tan(0.523598776); // 0.523598776 radians = 30 degrees. fieldOfView.UpTan = (float)Math.Tan(0.523598776); // 0.523598776 radians = 30 degrees. fieldOfView.LeftTan = (float)Math.Tan(0.785398163); // 0.785398163 radians = 45 degrees. fieldOfView.RightTan = (float)Math.Tan(0.785398163); // 0.785398163 radians = 45 degrees. EyeRenderDesc renderDescLeft = OVR.GetRenderDesc(sessionPtr, EyeType.Left, fieldOfView); EyeRenderDesc renderDescRight = OVR.GetRenderDesc(sessionPtr, EyeType.Left, fieldOfView); var viewScaleDesc = new ViewScaleDesc(); viewScaleDesc.HmdToEyePose0 = renderDescLeft.HmdToEyePose; viewScaleDesc.HmdToEyePose1 = renderDescRight.HmdToEyePose; viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1; // Determine texture size matching the field of view. Sizei sizeLeft = OVR.GetFovTextureSize(sessionPtr, EyeType.Left, fieldOfView, 1.0f); Sizei sizeRight = OVR.GetFovTextureSize(sessionPtr, EyeType.Right, fieldOfView, 1.0f); var hmdToEyeViewOffset = new Vector3f[2]; var poses = new Posef[2]; double sensorSampleTime; hmdToEyeViewOffset[0].X = -0.1f; hmdToEyeViewOffset[1].X = 0.1f; OVR.GetEyePoses(sessionPtr, 0, true, hmdToEyeViewOffset, ref poses, out sensorSampleTime); // Create a set of layers to submit. LayerEyeFov layer = new LayerEyeFov(); layer.Header.Type = LayerType.EyeFov; Result result; using (TestEngine testEngine = CreateTestEngine(sessionPtr)) { try { // Create a texture for the left eye. layer.ColorTextureLeft = CreateTextureSwapChain(sessionPtr, testEngine); layer.ViewportLeft.Position = new Vector2i(0, 0); layer.ViewportLeft.Size = sizeLeft; layer.FovLeft = fieldOfView; layer.RenderPoseLeft = poses[0]; // Create a texture for the right eye. layer.ColorTextureRight = CreateTextureSwapChain(sessionPtr, testEngine); layer.ViewportRight.Position = new Vector2i(0, 0); layer.ViewportRight.Size = sizeLeft; layer.FovRight = fieldOfView; layer.RenderPoseRight = poses[1]; // The created texture swap chain must be committed to the Oculus SDK, before using it in the // call to ovr_SubmitFrame, otherwise ovr_SubmitFrame will fail. result = OVR.CommitTextureSwapChain(sessionPtr, layer.ColorTextureLeft); Assert.IsTrue(result >= Result.Success); result = OVR.CommitTextureSwapChain(sessionPtr, layer.ColorTextureRight); Assert.IsTrue(result >= Result.Success); // SubmitFrame requires pointer to an array of pointers to Layer objects var layerPointers = new IntPtr[1]; GCHandle layerHandle = GCHandle.Alloc(layer, GCHandleType.Pinned); GCHandle layerPointersHandle = GCHandle.Alloc(layerPointers, GCHandleType.Pinned); layerPointers[0] = layerHandle.AddrOfPinnedObject(); result = OVR.SubmitFrame(sessionPtr, 0L, IntPtr.Zero, layerPointersHandle.AddrOfPinnedObject(), 1); Assert.IsTrue(result >= Result.Success); layerPointersHandle.Free(); layerHandle.Free(); } finally { if (layer.ColorTextureLeft != IntPtr.Zero) { OVR.DestroyTextureSwapChain(sessionPtr, layer.ColorTextureLeft); } if (layer.ColorTextureRight != IntPtr.Zero) { OVR.DestroyTextureSwapChain(sessionPtr, layer.ColorTextureRight); } } } }
/// <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); } }