【问题标题】:Displaying/implementing a System.Graphics.DrawEllipse as a DirectX 3D Surface?! c#将 System.Graphics.DrawEllipse 显示/实现为 DirectX 3D 表面?! C#
【发布时间】:2024-01-17 11:42:01
【问题描述】:

我目前开发了一个使用 System.Graphics.DrawEllipse 绘制多个椭圆的应用程序,该应用程序在 c# 中运行良好。

现在我想集成它,以便通过为每只眼睛提供不同的图像来使用立体成像 (3D) 向不同的眼睛显示某些椭圆。我安装了 DirectX SDK 和 SharpDX,我想使用生成的椭圆 (2D)并使用 NVIDIA 3D 和快门眼镜以立体/3D 方式显示它..

This question 给出了如何在 c# 中使用 3D 显示立体图像的答案,但它利用了 Surface 类。我在互联网上搜索了很多,但找不到绘制形状或使用已经绘制的形状而不是图像(位图)的方法。

感谢任何帮助。 谢谢。

【问题讨论】:

  • System.Drawing 是 GDI。它不是 DirectX,也不兼容。您将无法使用 System.Drawing 类来做任何与 DirectX 相关的事情。
  • 您最好的选择——如果你想保持简单——是使用 DirectX11.1 和 Direct2D。使用 DX11.1,设置stereo swapchain 非常简单。 Direct2D 还为您提供了类似 GDI 的方法,例如 Draw/Fill-Ellipse。这两个 API 均由 SharpDX 提供。

标签: c# drawing directx rendering graphics2d


【解决方案1】:

directx 和 GDI 之间没有直接的交互方式。当我遇到同样的问题时,我求助于准备好从 GDI 到内存的字节,然后返回到 direct3D。我在下面添加了我的代码,它应该可以工作,因为我认为它正在我的项目中使用:)

注意这是针对directx11(应该很容易转换)。此外,*B*GRA 纹理格式的使用是有意的,否则颜色会反转。

如果您需要更高的性能,我建议您研究 DirectDraw。

    private byte[] getBitmapRawBytes(Bitmap bmp)
{
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData =
        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

    // Get the address of the first line.
    IntPtr ptr = bmpData.Scan0;

    // Declare an array to hold the bytes of the bitmap.
    int bytes = Math.Abs(bmpData.Stride) * bmp.Height;
    byte[] rgbValues = new byte[bytes];

    // Copy the RGB values into the array.
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

    // Unlock the bits.
    bmp.UnlockBits(bmpData);
    return rgbValues;
}


/// <summary>
/// The bitmap and the texture should be same size.
/// The Texture format should be B8G8R8A8_UNorm
/// Bitmap pixelformat is read as PixelFormat.Format32bppArgb, so if this is the native format maybe speed is higher?
/// </summary>
/// <param name="bmp"></param>
/// <param name="tex"></param>
public void WriteBitmapToTexture(Bitmap bmp, GPUTexture tex)
{
    System.Diagnostics.Debug.Assert(tex.Resource.Description.Format == Format.B8G8R8A8_UNorm);

    var bytes = getBitmapRawBytes(bmp);
    tex.SetTextureRawData(bytes);

}

【讨论】:

    【解决方案2】:

    我使它工作的方式是将每个创建的椭圆(通过图形)保存在位图中,将每个位图添加到位图列表中,然后将这些位图加载到 Direct3D 表面列表中,然后通过索引访问我想要的任何表面。

    我希望它也能帮助其他人。

    【讨论】: