Skip to main content
Up and Coming
May 11, 2014

SharpOVR 0.4.2 NuGet Update

I've released a NuGet package called SharpOVR, it's a .NET API for the Oculus Rift. It is based on SDK 0.4.x and wraps most of the functionality provided by the SDK. It only supports SDK Rendering at the moment (no Client Distortion Rendering). It has a dependency on SharpDX for the Matrix, ViewportF, Vector and Point classes.
https://www.nuget.org/packages/SharpOVR/

Here's how to use it:

OVR.Initialize();
using (HMD hmd = OVR.HmdCreate(0))
{
// Configure rendering, configure tracking, BeginFrame, EndFrame, etc
}
OVR.Shutdown();

It targets the "Any CPU" platform as the assembly embeds both Win32/x64 unmanaged dlls and loads the appropriate one at runtime. In other words, just add the NuGet package to your project and you're good to go.

I've created a sample SharpDX game project (shown below) that can help you get started.
SharpOVR Sample



Let me know if you have any questions/suggestions.

Guy

    51 replies

    guygodinAuthor
    Up and Coming
    September 6, 2014
    "vizual54" wrote:
    This is maybe a dumb question but would it be possible to use sharpovr and render to the rift without the sharpdx game class?

    Absolutely, you don't have to use the SharpDX Toolkit, the only dependency is with the base SharpDX library. In Virtual Desktop for example I'm using my own game class.
    Virtual Desktop Developer
    New Participant
    September 6, 2014
    "guygodin" wrote:
    "vizual54" wrote:
    This is maybe a dumb question but would it be possible to use sharpovr and render to the rift without the sharpdx game class?

    Absolutely, you don't have to use the SharpDX Toolkit, the only dependency is with the base SharpDX library. In Virtual Desktop for example I'm using my own game class.


    Might need some help with this. I just started trying to learn DirectX so please bare with me.
    The HMD initializes ok and I can get tracking data. Though I only get a black screen, not the beautiful CornflowerBlue.
    Here is my code:
    static class Program
    {
    [STAThread]
    static void Main()
    {
    Form1 form = new Form1();
    form.Text = "SharpOVR";

    // Initialize OVR Library
    OVR.Initialize();
    HMD hmd;
    // Create our HMD
    hmd = OVR.HmdCreate(0) ?? OVR.HmdCreateDebug(HMDType.DK1);
    // Attach HMD to window
    var control = (System.Windows.Forms.Control)form;
    hmd.AttachToWindow(control.Handle);
    var renderTargetSize = hmd.GetDefaultRenderTargetSize(1.5f);

    form.ClientSize = new System.Drawing.Size(hmd.Resolution.Width, hmd.Resolution.Height);
    form.Show();

    // Create the device and swapchain
    Device device;
    SwapChain swapChain;

    Device.CreateWithSwapChain(
    SharpDX.Direct3D.DriverType.Hardware,
    DeviceCreationFlags.None,
    new[] {
    SharpDX.Direct3D.FeatureLevel.Level_11_0,
    SharpDX.Direct3D.FeatureLevel.Level_10_1,
    SharpDX.Direct3D.FeatureLevel.Level_10_0,
    },
    new SwapChainDescription()
    {
    ModeDescription =
    new ModeDescription(
    renderTargetSize.Width,
    renderTargetSize.Height,
    new Rational(60, 1),
    Format.R8G8B8A8_UNorm
    ),
    SampleDescription = new SampleDescription(1, 0),
    Usage = SharpDX.DXGI.Usage.BackBuffer | Usage.RenderTargetOutput | Usage.ShaderInput,
    BufferCount = 1,
    Flags = SwapChainFlags.None,
    IsWindowed = true,
    OutputHandle = form.Handle,
    SwapEffect = SwapEffect.Discard,
    },
    out device, out swapChain
    );

    var renderTarget = SharpDX.Direct3D11.Texture2D.FromSwapChain<SharpDX.Direct3D11.Texture2D>(swapChain, 0);
    var renderTargetView = new RenderTargetView(device, renderTarget);
    var renderTargetSRView = new ShaderResourceView(device, renderTarget);
    renderTarget.Dispose();

    // Depth buffer
    var zbufferTexture = new SharpDX.Direct3D11.Texture2D(device, new Texture2DDescription()
    {
    Format = Format.D16_UNorm,
    ArraySize = 1,
    MipLevels = 1,
    Width = renderTargetSize.Width,
    Height = renderTargetSize.Height,
    SampleDescription = new SampleDescription(1, 0),
    Usage = ResourceUsage.Default,
    BindFlags = BindFlags.DepthStencil,
    CpuAccessFlags = CpuAccessFlags.None,
    OptionFlags = ResourceOptionFlags.None
    });

    var zbufferView = new DepthStencilView(device, zbufferTexture);
    zbufferTexture.Dispose();

    // The viewport sizes are re-computed in case renderTargetSize changed
    var eyeRenderViewport = new Rect[2];
    eyeRenderViewport[0] = new Rect(0, 0, renderTargetSize.Width / 2, renderTargetSize.Height);
    eyeRenderViewport[1] = new Rect((renderTargetSize.Width + 1) / 2, 0, eyeRenderViewport[0].Width, eyeRenderViewport[0].Height);

    // Create our eye texture data
    D3D11TextureData[] eyeTexture = new D3D11TextureData[2];
    eyeTexture[0].Header.API = RenderAPIType.D3D11;
    eyeTexture[0].Header.TextureSize = renderTargetSize;
    eyeTexture[0].Header.RenderViewport = eyeRenderViewport[0];
    //eyeTexture[0].pTexture = ((SharpDX.Direct3D11.Texture2D)renderTarget).NativePointer;
    eyeTexture[0].pTexture = SharpDX.Direct3D11.Texture2D.FromSwapChain<SharpDX.Direct3D11.Texture2D>(swapChain, 0).NativePointer;
    eyeTexture[0].pSRView = renderTargetSRView.NativePointer;

    // Right eye uses the same texture, but different rendering viewport
    eyeTexture[1] = eyeTexture[0];
    eyeTexture[1].Header.RenderViewport = eyeRenderViewport[1];

    D3D11ConfigData d3d11cfg = new D3D11ConfigData();
    d3d11cfg.Header.API = RenderAPIType.D3D11;
    d3d11cfg.Header.RTSize = hmd.Resolution;
    d3d11cfg.Header.Multisample = 1;
    d3d11cfg.pDevice = device.NativePointer;
    d3d11cfg.pDeviceContext = device.ImmediateContext.NativePointer;
    //d3d11cfg.pBackBufferRT = ((RenderTargetView)graphicsDevice.BackBuffer).NativePointer;
    d3d11cfg.pBackBufferRT = renderTargetView.NativePointer;
    d3d11cfg.pSwapChain = swapChain.NativePointer;
    //d3d11cfg.pSwapChain = ((SharpDX.DXGI.SwapChain)graphicsDevice.Presenter.NativePresenter).NativePointer;

    // Configure rendering
    var eyeRenderDesc = new EyeRenderDesc[2];
    if (!hmd.ConfigureRendering(d3d11cfg, DistortionCapabilities.Chromatic | DistortionCapabilities.TimeWarp, hmd.DefaultEyeFov, eyeRenderDesc))
    {
    throw new Exception("Failed to configure rendering");
    }

    // Set enabled capabilities
    hmd.EnabledCaps = HMDCapabilities.LowPersistence | HMDCapabilities.DynamicPrediction;

    // Configure tracking
    hmd.ConfigureTracking(TrackingCapabilities.Orientation | TrackingCapabilities.Position | TrackingCapabilities.MagYawCorrection, TrackingCapabilities.None);

    // Dismiss the Heatlh and Safety Window
    //hmd.DismissHSWDisplay();

    // Get HMD output
    var adapter = (Adapter)(GraphicsDevice.New(device)).Adapter;
    var hmdOutput = adapter.Outputs.FirstOrDefault(o => hmd.DeviceName.StartsWith(o.Description.DeviceName, StringComparison.OrdinalIgnoreCase));
    if (hmdOutput != null)
    {
    // Set game to fullscreen on rift
    //var swapChain = (SwapChain)graphicsDevice.Presenter.NativePresenter;
    var description = swapChain.Description.ModeDescription;
    swapChain.ResizeTarget(ref description);
    swapChain.SetFullscreenState(true, hmdOutput);
    }

    // Create Clock and FPS counters
    var clock = new System.Diagnostics.Stopwatch();
    var clockFrequency = (double)System.Diagnostics.Stopwatch.Frequency;
    clock.Start();
    var deltaTime = 0.0;
    var fpsTimer = new System.Diagnostics.Stopwatch();
    fpsTimer.Start();
    var fps = 0.0;
    int fpsFrames = 0;

    PoseF[] renderPose = new PoseF[2];

    device.ImmediateContext.Rasterizer.SetViewport(0, 0, renderTargetSize.Width, renderTargetSize.Height);
    device.ImmediateContext.OutputMerger.SetTargets(zbufferView, renderTargetView);

    // Create and run the render loop
    RenderLoop.Run(form, () =>
    {
    #region fps
    // Time in seconds
    var totalSeconds = clock.ElapsedTicks / clockFrequency;
    fpsFrames++;
    if (fpsTimer.ElapsedMilliseconds > 1000)
    {
    fps = 1000.0 * fpsFrames / fpsTimer.ElapsedMilliseconds;

    // Update window title with FPS once every second
    form.Text = string.Format("SharpOVR - FPS: {0:F2} ({1:F2}ms/frame)", fps, (float)fpsTimer.ElapsedMilliseconds / fpsFrames);

    // Restart the FPS counter
    fpsTimer.Reset();
    fpsTimer.Start();
    fpsFrames = 0;
    }
    #endregion

    device.ImmediateContext.ClearRenderTargetView(renderTargetView, Color.CornflowerBlue);


    hmd.BeginFrame(0);

    for (int eyeIndex = 0; eyeIndex < 2; eyeIndex++)
    {
    var eye = hmd.EyeRenderOrder[eyeIndex];
    var renderDesc = eyeRenderDesc[(int)eye];
    var renderViewport = eyeRenderViewport[(int)eye];
    var pose = renderPose[(int)eye] = hmd.GetEyePose(eye);

    device.ImmediateContext.Rasterizer.SetViewport(renderViewport.ToViewportF());
    }

    hmd.EndFrame(renderPose, eyeTexture);

    // Determine the time it took to render the frame
    deltaTime = (clock.ElapsedTicks / clockFrequency) - totalSeconds;
    });
    }
    }
    guygodinAuthor
    Up and Coming
    September 7, 2014
    Can't tell what's wrong from the code above. Is there a reason why you're not using the toolkit?
    Virtual Desktop Developer
    New Participant
    September 8, 2014
    "guygodin" wrote:
    Can't tell what's wrong from the code above. Is there a reason why you're not using the toolkit?


    I'm actually using the toolkit right now and are starting to get the basic stuff for my app together.
    Since im new to directX, and not much of a coder in general, I thought I should learn the basics to have a better understanding of how things work. Also most tutorials I have found and the book I bought doesn't use the toolkit.
    Thanks for having a look at the code!
    New Participant
    October 10, 2014
    Hi Guy, I grabbed your sample code from the link you have in the first post of this thread. It seems to reference an older version of SharpOVR, and I don't know if it's related, but head movements are not brought into the rendering loop correctly. Yaw/Pitch/Roll work fine, however.

    I modify the packages.config file to change the version of SharpOVR to 0.4.2 but this doesn't seem to have any effect, although I'm not a NuGet expert by any stretch.

    Any ideas? I'm really hoping your project will be the best route for getting our custom c# game engine to gain Rift support!

    Thanks,
    Nick

    EDIT: I figured out my problem was related to the camera not being correctly reinitialized when my PC comes out of sleep. SharpOVR is working fine!
    New Participant
    December 19, 2014
    Dear Mr. Guy Godin .

    I'm using SharpOVR with OVRVision which is a dual-camera for OVR.
    I use a SpriteBatch to render on background left/right camera data stream.
    The problem is that I don't want that the sprite draw call pass through Distortion Shader as the camera has already a distortion lens.

    How can do that with SharpOVR?

    THank you

    Denis
    New Participant
    December 23, 2014
    Hello guygodin,

    I want to develop a 3D game which can both use normal DirectX Fullscreen Output and also Oculus Rift DK2 Output. I found your package, thanks a lot for that!

    Is it possible to make a new NuGet package or download Version that supports the new SharpDX 2.6.3. please?

    When I start my prgram with latest SharpDX 2.6.3 now I always get an error because SharpOVR wants to load a SharpDX.dll with 2.6.2 ....

    Thanks a lot for that and have nice Holidays!

    Firlefanz73
    New Participant
    April 10, 2015
    "Firlefanz73" wrote:
    Hello guygodin,

    I want to develop a 3D game which can both use normal DirectX Fullscreen Output and also Oculus Rift DK2 Output. I found your package, thanks a lot for that!

    Is it possible to make a new NuGet package or download Version that supports the new SharpDX 2.6.3. please?

    When I start my prgram with latest SharpDX 2.6.3 now I always get an error because SharpOVR wants to load a SharpDX.dll with 2.6.2 ....

    Thanks a lot for that and have nice Holidays!

    Firlefanz73


    I got the same problem :|
    guygodinAuthor
    Up and Coming
    July 20, 2015
    Just updated SharpOVR to the 0.6 SDK. I've also updated the sample and fixed the dependencies. I've created a new thread in the appropriate forum section.
    Virtual Desktop Developer
    New Participant
    June 23, 2016
    Hi guygodin (or anyone else who could possibly help me)

    A few months ago, I added support for the Oculus DK2 using the SharpOVR library, and it all worked great. We recently got our hands on the Oculus CV1 model and really need to implement support for it.

    Will the SharpOVR library ever be updated to work with the CV1?
    Also I tried to download the SharpOVR sample project (to try and get that to work with CV1), but the link provided is broken.

    Thanks a lot for any help that you are able to give me.