SharpDx direct3d11如何开始渲染

SharpDx direct3d11 how to start rendering

我想在 C# 上使用 directx,我正在使用 SharpDX 包装器。我有一本名为 Direct3D 渲染指南的书,我从中获得了基本代码。我想创建一个 3d 世界视图。为此,我将需要一个相机视图和一个网格来帮助识别世界位置,就像在 Autodesk Maya 中一样,但我不知道该怎么做。我的想法很复杂,我应该怎么做才能开始?

这里我有代码可以渲染我认为的东西:

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
            }
}
}

一般来说,对于 Direct3D,您需要大量代码才能在屏幕上显示任何内容。

在 SharpDX 存储库中,您有 MiniCube 示例,其中包含足以让您真正入门的示例,因为它包含绘制 3d 场景所需的所有元素。

我建议特别寻找:

  • 深度缓冲区创建(DepthStencilView)
  • fx 文件,因为你需要着色器在屏幕上显示任何内容(不再是固定功能)
  • Vertex Buffer的创建方式,需要将几何图形分割成三角形(一般情况下还有其他可能)。
  • 不要忘记 SetViewport(省略它很常见)
  • 引用输入汇编器的调用正在分配要绘制的几何图形
  • 常量缓冲区创建:这是为了传递矩阵和更改数据(如漫反射)
  • 同时确保在 Device.CreateWithSwapChain 调用中使用 DeviceCreationFlags.None,并在 visual studio 调试选项中使用 "Enable Native Code Debugging"。如果某些设置不正确,这会给你错误和警告,加上一个有意义的原因,以防任何资源创建失败(而不是 "Invalid Args",这是毫无意义的)。
  • 作为另一项建议,所有 Direct3D11 资源创建参数都非常容易出错且乏味(许多选项彼此之间不兼容),因此将它们包装到一些更易于使用的辅助函数中非常重要(并制作一个少量的单元测试来一劳永逸地验证它们)。旧的 Toolkit 有很多这样的例子
  • SharpDX 包装器与 c++ 包装器相对接近,因此 c++ 文档中的任何内容也适用于它。