예제 #1
0
        /// <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();
        }
        public OculusTextureSwapChain(OvrWrap ovr,
                                      IntPtr sessionPtr,
                                      SharpDX.Direct3D11.Device device,
                                      EyeType eye,
                                      Format format,
                                      Sizei size,
                                      bool createDepthStencilView = false,
                                      bool isDebugDevice          = false)
        {
            _ovr          = ovr;
            _sessionPtr   = sessionPtr;
            _size         = size;
            _viewportSize = size;
            _viewport     = new ViewportF(0.0f, 0.0f, (float)size.Width, (float)size.Height);

            Format srgbFormat = GetSRgbFormat(format);

            TextureFormat        textureFormat = SharpDXHelpers.GetTextureFormat(srgbFormat);
            TextureSwapChainDesc swapChainDesc = new TextureSwapChainDesc()
            {
                ArraySize   = 1,
                BindFlags   = TextureBindFlags.DX_RenderTarget,
                Format      = textureFormat,
                Height      = _size.Height,
                MipLevels   = 1,
                MiscFlags   = TextureMiscFlags.DX_Typeless,
                SampleCount = 1,
                Width       = _size.Width
            };

            Texture2DDescription description1 = new Texture2DDescription()
            {
                ArraySize         = 1,
                BindFlags         = BindFlags.DepthStencil,
                CpuAccessFlags    = CpuAccessFlags.None,
                Format            = Format.R24G8_Typeless,
                Height            = _size.Height,
                MipLevels         = 1,
                OptionFlags       = ResourceOptionFlags.None,
                SampleDescription = new SampleDescription(1, 0),
                Usage             = ResourceUsage.Default,
                Width             = _size.Width
            };

            ShaderResourceViewDescription description2 = new ShaderResourceViewDescription()
            {
                Format    = srgbFormat,
                Dimension = ShaderResourceViewDimension.Texture2D
            };

            description2.Texture2D.MipLevels = 1;

            // Create a texture swap chain, which will contain the textures to render to, for the current eye.
            var result = _ovr.CreateTextureSwapChainDX(_sessionPtr, device.NativePointer, ref swapChainDesc, out _textureSwapChainPtr);

            if (result < Ab3d.OculusWrap.Result.Success)
            {
                var lastError = _ovr.GetLastErrorInfo();
                throw new OvrException("Error creating Oculus TextureSwapChain: " + lastError.ErrorString, lastError.Result);
            }


            int length;

            result = _ovr.GetTextureSwapChainLength(_sessionPtr, _textureSwapChainPtr, out length);

            if (result < Ab3d.OculusWrap.Result.Success)
            {
                var lastError = _ovr.GetLastErrorInfo();
                throw new OvrException("Failed to retrieve the number of buffers of the created swap chain: " + lastError.ErrorString, lastError.Result);
            }


            _textures = new TextureItem[length];

            for (int index = 0; index < length; ++index)
            {
                IntPtr bufferPtr;
                result = _ovr.GetTextureSwapChainBufferDX(_sessionPtr, _textureSwapChainPtr, index, typeof(Texture2D).GUID, out bufferPtr);

                if (result < Ab3d.OculusWrap.Result.Success)
                {
                    var lastError = _ovr.GetLastErrorInfo();
                    throw new OvrException("Failed to retrieve a texture from the created swap chain: " + lastError.ErrorString, lastError.Result);
                }

                Texture2D        texture2D1       = new Texture2D(bufferPtr);
                Texture2D        texture2D2       = null;
                DepthStencilView depthStencilView = null;

                if (createDepthStencilView)
                {
                    texture2D2       = new Texture2D(device, description1);
                    depthStencilView = new DepthStencilView(device, texture2D2, new DepthStencilViewDescription()
                    {
                        Flags     = DepthStencilViewFlags.None,
                        Dimension = DepthStencilViewDimension.Texture2D,
                        Format    = Format.D24_UNorm_S8_UInt
                    });
                }

                _textures[index] = new TextureItem()
                {
                    Texture            = texture2D1,
                    TextureDescription = texture2D1.Description,
                    DepthBuffer        = texture2D2,
                    DepthStencilView   = depthStencilView,
                    RTView             = new RenderTargetView(device, texture2D1, new RenderTargetViewDescription()
                    {
                        Format    = format,
                        Dimension = RenderTargetViewDimension.Texture2D
                    }),
                    SRView = new ShaderResourceView(device, texture2D1, description2)
                };


                if (isDebugDevice)
                {
                    var eyeTextAndIndex = eye.ToString() + index.ToString();

                    _textures[index].Texture.DebugName          = "OculusBackBuffer" + eyeTextAndIndex;
                    _textures[index].RTView.DebugName           = "OculusRT" + eyeTextAndIndex;
                    _textures[index].SRView.DebugName           = "OculusSR" + eyeTextAndIndex;
                    _textures[index].DepthBuffer.DebugName      = "OculusDepthBuffer" + eyeTextAndIndex;
                    _textures[index].DepthStencilView.DebugName = "OculusDepthStencilView" + eyeTextAndIndex;
                }
            }
        }