SharpDX 3.0.2 D3D11 — Как загрузить текстуру из файла и заставить ее работать в шейдере?

У меня 0 опыта работы с D3D. В настоящее время я читаю книгу Фрэнка Луны о D3D11 и пытаюсь сделать примеры, работающие на С#, с использованием SharpDX, хотя и без фреймворка эффектов. Я застрял с текстурированием сейчас. Я не понимаю, как загрузить текстуру из файла и как отправить ее в шейдер.

Официальная вики мертва. По крайней мере у меня не загружается. Я искал здесь, но нашел только какой-то способ сделать это с помощью SharpDX.WIC, который работает с D2D, поэтому мне кажется немного странным использовать некоторые компоненты D2D в приложении D3D.


person Vasja Filippov    schedule 17.03.2016    source источник
comment
Та же проблема. Я только разрабатываю программу Direct3D11, но теперь у меня есть D3DCompiler, Desktop, Direct2D1, DXGI, Mathematics. Какова цель наличия такого количества отдельных зависимостей, которые всегда будут использоваться вместе? Действительно раздражает.   -  person Wu Zhenwei    schedule 20.11.2016


Ответы (4)


Посмотрите здесь загрузчик текстур: Как загрузить текстуру из файла?

Использование:

var device = this.DeviceManager.Direct3DDevice;
var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), "Texture2.png"));
ShaderResourceView textureView = new ShaderResourceView(device, texture);
person hitzi    schedule 18.03.2016
comment
Не странно ли использовать WIC, который является частью пакета Direct2D, для загрузки текстур в Direct3D? - person Vasja Filippov; 18.03.2016

Извините за публикацию в старой ветке, но не лучше ли для этого использовать то, что предусмотрено в .NET framework?

    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;
person Wu Zhenwei    schedule 05.03.2017
comment
Пример выше хорош, но растровое изображение не удаляется. Кроме того, для получения растрового изображения необходимо using (var image = Image.FromFile(path)) { var bitmap = new Bitmap(image); ... } - person Krzysztof Bociurko; 25.09.2018

WIC не является частью Direct2D, wic — лучший известный мне способ загрузки изображений в DirectX, даже в C++ вы должны использовать wic, поэтому просто перейдите по ссылке в первом ответе, и все будет в порядке.

Or

 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 и тому подобное.

person Justin William Stanley Bryant    schedule 18.05.2016

Мне лично нравится хранить некоторые текстуры в ресурсах (внутри exe). Чтобы получить растровое изображение из ресурсов, вы можете использовать YOURPROJECT.Properties.Resources.BITMAPNAME в C#.

Затем я сделал небольшую функцию преобразования растровых изображений 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, чтобы использовать его в конвейере рисования.

person Michal Pokluda    schedule 04.08.2017