【问题标题】:SharpDX 3.0.2 D3D11 - How to load texture from file and make it to work in shader?SharpDX 3.0.2 D3D11 - 如何从文件加载纹理并使其在着色器中工作?
【发布时间】:2017-08-04 15:31:16
【问题描述】:

我在 D3D 方面的经验为 0。我目前正在阅读 Frank Luna 的关于 D3D11 的书,并尝试使用 SharpDX 制作使用 C# 的示例,尽管没有效果框架。我现在坚持使用纹理。我不明白如何从文件加载纹理以及如何将其发送到着色器。

官方 wiki 已死。或者至少它不会为我加载。 我在这里进行了搜索,但只发现了一些使用 SharpDX.WIC 的方法,它与 D2D 一起使用,所以在 D3D 应用程序中使用一些 D2D 组件对我来说看起来有点奇怪。

【问题讨论】:

  • 同样的问题。我只是在开发一个 Direct3D11 程序,但现在我最终得到了 D3DCompiler、Desktop、Direct2D1、DXGI、Mathematics。有这么多分离的依赖项总是一起使用的目的是什么?真烦人。

标签: c# directx directx-11 sharpdx


【解决方案1】:

很抱歉在旧线程上发帖,但是使用 .NET 框架中提供的功能来实现这一点不是更好吗?

    if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
    {
        bitmap = bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), PixelFormat.Format32bppArgb);
    }
    var data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    var ret = new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription()
    {
        Width = bitmap.Width,
        Height = bitmap.Height,
        ArraySize = 1,
        BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource,
        Usage = SharpDX.Direct3D11.ResourceUsage.Immutable,
        CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
        Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
        MipLevels = 1,
        OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
        SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
    }, new SharpDX.DataRectangle(data.Scan0, data.Stride));
    bitmap.UnlockBits(data);
    return ret;

【讨论】:

  • 上面的例子很好,但没有处理位图。另外,要获取位图,您应该using (var image = Image.FromFile(path)) { var bitmap = new Bitmap(image); ... }
【解决方案2】:

在此处查找纹理加载器:How to load a texture from a file?

用法:

var device = this.DeviceManager.Direct3DDevice;
var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), "Texture2.png"));
ShaderResourceView textureView = new ShaderResourceView(device, texture);

【讨论】:

  • 在 Direct3D 中使用 Direct2D 包中的 WIC 进行纹理加载不是很奇怪吗?
【解决方案3】:

WIC 不是 direct2d 的一部分,wic 是加载图像的最佳方式,我知道即使在 c++ 中也可以在 directX 中使用,您必须使用 wic,因此只需点击第一个答案中的链接即可。

或者

 public class TextureLoader
{
    /// <summary>
    /// Loads a bitmap using WIC.
    /// </summary>
    /// <param name="deviceManager"></param>
    /// <param name="filename"></param>
    /// <returns></returns>
    public static SharpDX.WIC.BitmapSource LoadBitmap(SharpDX.WIC.ImagingFactory2 factory, string filename)
    {
        var bitmapDecoder = new SharpDX.WIC.BitmapDecoder(
            factory,
            filename,
            SharpDX.WIC.DecodeOptions.CacheOnDemand
            );

        var formatConverter = new SharpDX.WIC.FormatConverter(factory);

        formatConverter.Initialize(
            bitmapDecoder.GetFrame(0),
            SharpDX.WIC.PixelFormat.Format32bppPRGBA,
            SharpDX.WIC.BitmapDitherType.None, 
            null,
            0.0, 
            SharpDX.WIC.BitmapPaletteType.Custom);

        return formatConverter;
    }

    /// <summary>
    /// Creates a <see cref="SharpDX.Direct3D11.Texture2D"/> from a WIC <see cref="SharpDX.WIC.BitmapSource"/>
    /// </summary>
    /// <param name="device">The Direct3D11 device</param>
    /// <param name="bitmapSource">The WIC bitmap source</param>
    /// <returns>A Texture2D</returns>
    public static SharpDX.Direct3D11.Texture2D CreateTexture2DFromBitmap(SharpDX.Direct3D11.Device device, SharpDX.WIC.BitmapSource bitmapSource)
    {
        // Allocate DataStream to receive the WIC image pixels
        int stride = bitmapSource.Size.Width * 4;
        using (var buffer = new SharpDX.DataStream(bitmapSource.Size.Height * stride, true, true))
        {
            // Copy the content of the WIC to the buffer
            bitmapSource.CopyPixels(stride, buffer);
            return new SharpDX.Direct3D11.Texture2D(device, new SharpDX.Direct3D11.Texture2DDescription()
            {
                Width = bitmapSource.Size.Width,
                Height = bitmapSource.Size.Height,
                ArraySize = 1,
                BindFlags = SharpDX.Direct3D11.BindFlags.ShaderResource,
                Usage = SharpDX.Direct3D11.ResourceUsage.Immutable,
                CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None,
                Format = SharpDX.DXGI.Format.R8G8B8A8_UNorm,
                MipLevels = 1,
                OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None,
                SampleDescription = new SharpDX.DXGI.SampleDescription(1, 0),
            }, new SharpDX.DataRectangle(buffer.DataPointer, stride));
        }
    }
}

我刚刚从链接中提取它,因此它可能需要一些更改才能与 SharpDX 3 一起使用,我使用几乎相同的代码路径,但在加载阶段我有更多选项,例如。非预乘法线,转换为 Srgb 和类似的东西。

【讨论】:

    【解决方案4】:

    我个人喜欢在资源中保留一些纹理(在 exe 中)。要从资源中获取位图,您可以在 C# 中使用 YOURPROJECT.Properties.Resources.BITMAPNAME。

    然后我做了一个小转换功能,将 GDI+ 位图转换为 WIC 位图:

        public static unsafe SharpDX.WIC.Bitmap CreateWICBitmapFromGDI(
            System.Drawing.Bitmap gdiBitmap)
        {
            var wicFactory = new ImagingFactory();
            var wicBitmap = new SharpDX.WIC.Bitmap(
                wicFactory, gdiBitmap.Width, gdiBitmap.Height,
                SharpDX.WIC.PixelFormat.Format32bppBGRA, 
                BitmapCreateCacheOption.CacheOnLoad);
    
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(
                0, 0, gdiBitmap.Width, gdiBitmap.Height);
            var btmpData = gdiBitmap.LockBits(rect,
                System.Drawing.Imaging.ImageLockMode.WriteOnly,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);
    
            byte* pGDIData = (byte*)btmpData.Scan0;
            using (BitmapLock bl = wicBitmap.Lock(BitmapLockFlags.Write))
            {
                byte* pWICData = (byte*)bl.Data.DataPointer;
                for (int y = 0; y < gdiBitmap.Height; y++)
                {
                    int offsetWIC = y * bl.Stride;
                    int offsetGDI = y * btmpData.Stride;
                    for (int x = 0; x < gdiBitmap.Width; x++)
                    {
                        pWICData[offsetWIC + 0] = pGDIData[offsetGDI + 0];  //R
                        pWICData[offsetWIC + 1] = pGDIData[offsetGDI + 1];  //G
                        pWICData[offsetWIC + 2] = pGDIData[offsetGDI + 2];  //B
                        pWICData[offsetWIC + 3] = pGDIData[offsetGDI + 3];      //A
                        offsetWIC += 4;
                        offsetGDI += 4;
                    }
                }
            }
    
            gdiBitmap.UnlockBits(btmpData);
    
            return wicBitmap;
        }
    

    这将为您创建 WIC 位图,然后您可以使用 CreateTexture2DFromBitmap 在绘图管道中使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      相关资源
      最近更新 更多