我正在尝试基于WPF创建地图编辑器。目前我正在使用黑客来呈现DirectX内容。我创建了一个WinFormsHost并在WinForms-Panel上呈现。
这一切都是因为DirectX(我使用DirectX 11和Featurelevel 10)想要一个Handle(别名IntPtr)来渲染。我不知道如何在没有句柄的情况下初始化和使用DX设备。
但WPF控件无法处理。所以我发现,有一个名为“D3DImage”的互操作类。但我不明白如何使用它。
我目前的系统是这样的:
内部循环遍历“IGameloopElement”列表。对于每个,它呈现其内容调用“Draw()”。之后,它调用交换链的“Present()”来显示更改。然后它重置设备以将句柄切换到下一个元素(大多数只有一个元素)。
现在,因为D3DImage没有句柄,我该如何渲染它?我只知道我必须使用“Lock()”然后“SetBackBuffer()”,“AddDirtyRect()”然后“Unlock()”。
但是如何在不指定设备句柄的情况下渲染到DirectX11.Texture2D对象上?
我真的输了......我刚刚在codeplex上找到了“DirectX 4 WPF”示例,但这实现了DirectX的所有版本,管理设备本身并且有如此巨大的开销。 我想留在我目前的系统。我自己管理设备。我不希望WPF控件处理它。
循环应调用“Render()”,然后将后备缓冲区纹理传递给WPF控件。
有人能告诉我怎么做吗?我完全陷入困境......
非常感谢:)
[R
答案 0 :(得分:4)
WPF的D3DImage仅支持Direct3D9 / Direct3D9Ex,它不支持Direct3D 11.您需要使用DXGI Surface Sharing才能使其正常工作。
答案 1 :(得分:2)
另一个答案写道,“D3DImage
仅支持 Direct3D9/Direct3D9Ex”……无论如何,这在过去几年中可能并不完全正确。正如我在评论 here 中总结的那样,关键似乎是带有 DXGI 的 Direct3D11 具有非常特定的互操作兼容模式(D3D11_SHARED_WITHOUT_MUTEX
标志),这使得 {{1} } 可直接用作 ID3D11Texture2D1
,无需复制任何位,这恰好(且仅)是 WPF D3DResourceType.IDirect3DSurface9
愿意接受的。
这是对我有用的粗略草图,用于创建一个 D3D11 SampleAllocator,它生成与 WPF 的 Direct3D9 直接兼容的 D3DImage
。因为这里显示的所有 .NET 互操作都是我自己设计的,所以这不会是完全准备好运行的代码,可以放入您的项目中,但方法、意图和过程应该很清楚,以便于适应。
1.初级帮手
ID3D11Texture2D1
2. D3D11 设备和上下文实例去某处
static D3D_FEATURE_LEVEL[] levels =
{
D3D_FEATURE_LEVEL._11_1,
D3D_FEATURE_LEVEL._11_0,
};
static IMFAttributes GetSampleAllocatorAttribs()
{
MF.CreateAttributes(out IMFAttributes attr, 6);
attr.SetUINT32(in MF_SA_D3D11_AWARE, 1U);
attr.SetUINT32(in MF_SA_D3D11_BINDFLAGS, (uint)D3D11_BIND.RENDER_TARGET);
attr.SetUINT32(in MF_SA_D3D11_USAGE, (uint)D3D11_USAGE.DEFAULT);
attr.SetUINT32(in MF_SA_D3D11_SHARED_WITHOUT_MUTEX, (uint)BOOL.TRUE);
attr.SetUINT32(in MF_SA_BUFFERS_PER_SAMPLE, 1U);
return attr;
}
static IMFMediaType GetMediaType()
{
MF.CreateMediaType(out IMFMediaType mt);
mt.SetUINT64(in MF_MT_FRAME_SIZE, new SIZEU(1920, 1080).ToSwap64());
mt.SetGUID(in MF_MT_MAJOR_TYPE, in WMMEDIATYPE.Video);
mt.SetUINT32(in MF_MT_INTERLACE_MODE, (uint)MFVideoInterlaceMode.Progressive);
mt.SetGUID(in MF_MT_SUBTYPE, in MF_VideoFormat.RGB32);
return mt;
}
3.接下来是初始化代码
ID3D11Device4 m_d3D11_device;
ID3D11DeviceContext2 m_d3D11_context;
4.根据需要使用样本分配器重复生成纹理
void InitialSetup()
{
D3D11.CreateDevice(
null,
D3D_DRIVER_TYPE.HARDWARE,
IntPtr.Zero,
D3D11_CREATE_DEVICE.BGRA_SUPPORT,
levels,
levels.Length,
D3D11.SDK_VERSION,
out m_d3D11_device,
out D3D_FEATURE_LEVEL _,
out m_d3D11_context);
MF.CreateDXGIDeviceManager(out uint tok, out IMFDXGIDeviceManager m_dxgi);
m_dxgi.ResetDevice(m_d3D11_device, tok);
MF.CreateVideoSampleAllocatorEx(
ref REFGUID<IMFVideoSampleAllocatorEx>.GUID,
out IMFVideoSampleAllocatorEx sa);
sa.SetDirectXManager(m_dxgi);
sa.InitializeSampleAllocatorEx(
PrerollSampleSink.QueueMax,
PrerollSampleSink.QueueMax * 2,
GetSampleAllocatorAttribs(),
GetMediaType());
}