SharpDX 3.0.2 D3D11 - 如何从文件加载纹理并使其在着色器中工作?
SharpDX 3.0.2 D3D11 - How to load texture from file and make it to work in shader?
我有 0 次 D3D 经验。我目前正在阅读 Frank Luna 关于 D3D11 的书,并尝试使用 SharpDX 通过 w/o 效果框架制作在 C# 中工作的示例。我现在坚持使用纹理。我不明白如何从文件加载纹理以及如何将其发送到着色器。
官方维基已死。或者至少它不会为我加载。
我在这里进行了搜索,但只找到了一些使用 SharpDX.WIC 的方法,它与 D2D 一起使用,所以在 D3D 应用程序中使用一些 D2D 组件对我来说看起来有点奇怪。
在此处查找纹理加载器:
用法:
var device = this.DeviceManager.Direct3DDevice;
var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), "Texture2.png"));
ShaderResourceView textureView = new ShaderResourceView(device, texture);
WIC 不是 direct2d 的一部分,wic 是我所知道的在 directX 中加载图像的最佳方式,即使在 c++ 中你也必须使用 wic,所以只要按照第一个答案中的 link 就可以了.
或
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));
}
}
}
我刚从 link 中提取它,因此它可能需要一些更改才能与 SharpDX 3 一起使用,我使用几乎相同的代码路径,但在加载阶段我有更多选项,例如。非法线预乘,转换为 Srgb 之类的东西。
很抱歉在旧线程上发帖,但是使用 .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;
我个人喜欢在资源里(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 在绘图管道中使用它。
我有 0 次 D3D 经验。我目前正在阅读 Frank Luna 关于 D3D11 的书,并尝试使用 SharpDX 通过 w/o 效果框架制作在 C# 中工作的示例。我现在坚持使用纹理。我不明白如何从文件加载纹理以及如何将其发送到着色器。
官方维基已死。或者至少它不会为我加载。 我在这里进行了搜索,但只找到了一些使用 SharpDX.WIC 的方法,它与 D2D 一起使用,所以在 D3D 应用程序中使用一些 D2D 组件对我来说看起来有点奇怪。
在此处查找纹理加载器:
用法:
var device = this.DeviceManager.Direct3DDevice;
var texture = TextureLoader.CreateTexture2DFromBitmap(device, TextureLoader.LoadBitmap(new SharpDX.WIC.ImagingFactory2(), "Texture2.png"));
ShaderResourceView textureView = new ShaderResourceView(device, texture);
WIC 不是 direct2d 的一部分,wic 是我所知道的在 directX 中加载图像的最佳方式,即使在 c++ 中你也必须使用 wic,所以只要按照第一个答案中的 link 就可以了.
或
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));
}
}
}
我刚从 link 中提取它,因此它可能需要一些更改才能与 SharpDX 3 一起使用,我使用几乎相同的代码路径,但在加载阶段我有更多选项,例如。非法线预乘,转换为 Srgb 之类的东西。
很抱歉在旧线程上发帖,但是使用 .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;
我个人喜欢在资源里(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 在绘图管道中使用它。