Search code examples
c#direct3dsharpdxdirect3d11

SharpDx direct3d11 how to start rendering


I want to use directx on C# and I am using SharpDX wrapper. I got a book called Direct3D rendering cookbook and I got the basic code from it. I want to create a 3d world view. For that I will need a camera view and a grid that helps to recognize world position just like in Autodesk Maya but I do not know how to do that. My mind is rally mixed what should I do to start ?

Here I have code that is ready to render something I think:

using System;
using SharpDX.Windows;
using SharpDX.DXGI;
using SharpDX.Direct3D11;

using Device = SharpDX.Direct3D11.Device;
using Device1 = SharpDX.Direct3D11.Device1;

namespace CurrencyConverter
{
    static class Program
    {[STAThread]
            static void Main()
            {
                // Enable object tracking
                SharpDX.Configuration.EnableObjectTracking = true;
                SharpDX.Animation.Timer timer = new SharpDX.Animation.Timer();

                #region Direct3D Initialization
                // Create the window to render to
                Form1 form = new Form1();
                form.Text = "D3DRendering - EmptyProject";
                form.Width = 640;
                form.Height = 480;
                // Declare the device and swapChain vars
                Device device;
                SwapChain swapChain;
                // Create the device and swapchain
                // First create a regular D3D11 device
                using (var device11 = new Device(
                 SharpDX.Direct3D.DriverType.Hardware,
                 DeviceCreationFlags.None,
                 new[] {
     SharpDX.Direct3D.FeatureLevel.Level_11_1,
     SharpDX.Direct3D.FeatureLevel.Level_11_0,
                 }))
                {
                    // Query device for the Device1 interface (ID3D11Device1)
                    device = device11.QueryInterfaceOrNull<Device1>();
                    if (device == null)
                        throw new NotSupportedException(
                        "SharpDX.Direct3D11.Device1 is not supported");
                }// Rather than create a new DXGI Factory we reuse the
                 // one that has been used internally to create the device
                using (var dxgi = device.QueryInterface<SharpDX.DXGI.Device2>())
                using (var adapter = dxgi.Adapter)
                using (var factory = adapter.GetParent<Factory2>())
                {
                    var desc1 = new SwapChainDescription1()
                    {
                        Width = form.ClientSize.Width,
                        Height = form.ClientSize.Height,
                        Format = Format.R8G8B8A8_UNorm,
                        Stereo = false,
                        SampleDescription = new SampleDescription(1, 0),
                        Usage = Usage.BackBuffer | Usage.RenderTargetOutput,
                        BufferCount = 1,
                        Scaling = Scaling.Stretch,
                        SwapEffect = SwapEffect.Discard,
                    };
                    swapChain = new SwapChain1(factory,
                    device,
                    form.Handle,
                    ref desc1,
                    new SwapChainFullScreenDescription()
                    {
                        RefreshRate = new Rational(60, 1),
                        Scaling = DisplayModeScaling.Centered,
                        Windowed = true
                    },
                    // Restrict output to specific Output (monitor)
                    adapter.Outputs[0]);
                }

                // Create references for backBuffer and renderTargetView
                var backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain,
               0);
                var renderTargetView = new RenderTargetView(device,
               backBuffer);
                #endregion

                // Setup object debug names
                device.DebugName = "The Device";
                swapChain.DebugName = "The SwapChain";
                backBuffer.DebugName = "The Backbuffer";
                renderTargetView.DebugName = "The RenderTargetView";

                #region Render loop
                // Create and run the render loop
                RenderLoop.Run(form, () =>
                {
                    // Clear the render target with...
                    var lerpColor = SharpDX.Color.Lerp(SharpDX.Color.White,
     SharpDX.Color.DarkBlue,
     (float)((timer.Time) / 10.0 % 1.0));
                    device.ImmediateContext.ClearRenderTargetView(
                     renderTargetView,
                     lerpColor);

                    // Execute rendering commands here...
                    //...
                    //I DO NOT HAVE ANY IDEA
                    //...
                    // Present the frame
                    swapChain.Present(0, PresentFlags.RestrictToOutput); 
                });
                #endregion

                #region Direct3D Cleanup
                // Release the device and any other resources created
                renderTargetView.Dispose();
                backBuffer.Dispose();
                device.Dispose();
                swapChain.Dispose();
                #endregion
            }
}
}

Solution

  • Generally speaking, with Direct3D you need a substantial amount of code before to have anything happening on the screen.

    In the SharpDX repository you have the MiniCube sample which contains enough to really get you started, as it has all the elements required to draw a 3d scene.

    I recommend to particularily look for:

    • Depth buffer creation (DepthStencilView)
    • fx file, as you need shaders to have anything on the screen (no more fixed funtion)
    • How the Vertex Buffer is created, you need to split geometry in triangles (in common cases, there are other possibilities).
    • Don't forget the SetViewport (it's really common to have it omitted)
    • The calls referring to Input Assembler are assigning the geometry to be drawn
    • Constant buffer creation : this is to pass matrices and changing data (like diffuse)
    • Also make sure to have DeviceCreationFlags.None with the Device.CreateWithSwapChain call, and in visual studio debug options, use "Enable Native Code Debugging". This will give you errors and warnings if something is not set properly, plus a meaningful reason in case any for the resource creation fails (instead of "Invalid Args", which is quite pointless).
    • As another recommendation, all the Direct3D11 resource creation parameters are incredibly error prone and tedious (many options are non compatible between each other), so it quite important to wrap those into some easier to use helper functions (and make a small amount of unit tests to validate them once and for all). The old Toolkit has quite some of those examples
    • SharpDX wrapper is relatively close to the c++ counterpart, so anything in the c++ documentation applies to it too.