D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践

D3DImage - 它能做啥、解决了什么问题、有哪些瓶颈、怎么最佳实践

D3dImage,.Net Framework 3.5 之后,微软提供的一个全新的ImageSource对象,可以在WPF中很好的呈现DirectX内容;在此之前,你只能将DirectX内容直接渲染在Windows窗口之上,这必然引起令人头疼的AirSpace问题,为了在这些内容上面添加我们习以为常的WPF UI 元素,你只能使用Popup来承载这些内容,完全丧失WPF UI开发的灵活性,且有经验的WPF程序员都知道一个事实:WPF Popup就是一个深坑 - 你需要手动处理各种显示隐藏问题、因为其导致的焦点问题,显示层级问题以及最令人头疼的性能问题,特别是在4K屏幕下,因为我们都知道,Popup就是一个Window,为了解决Airspace问题而使用Popup来承载UI必定需要使其AllowTransparency=True,这就引起了另外一个问题,透明窗口占用内存与其面积成正相关,在4K屏幕下,你可能将整个程序大部分的内存占用贡献给了这些Popup UI。说了这么多,好像在诉控Popup有多么的垃圾(它的确如此,如果在做大量的UI容器时)。

年轻人,如果你觉得Airspace问题真的没有办法解决了,只能用Popup这种技术手段来规避了,那么听老人一句话,不要浪费时间在Popup上了,因为你在前期投入的时间来规避种种Popup UI导致的问题以及各种你意想不到的Bug,到最后总会碰到解决不了,完全不能规避的情况,从而导致整个Popup UI替换方案完全失败的情形。

阅读更多
D3DImage in WPF

D3DImage in WPF

在.Net Framework 3.5 SP1中,微软在WPF中提供了D3DImage对象,D3DImage是一个ImageSource,这可以让我们在WPF原生的D3D Surface上渲染Direct3D Surface,大大提高了WPF和DirectX内容的交互性。
在此之前,要想在WPF上渲染DirectX的内容,只能让DirectX直接渲染到窗口上,这样会造成不可避免的Airspace问题,因为DirectX内容要时刻刷新重绘,导致WPF窗口上的其他内容被覆盖,表现就是DirectX内容始终在窗口最顶层。
正如前面所说,D3DImage是一个ImageSource,在WPF中,这意味着,我们可以将一个3D场景变成一个Image对象的Source,或者构建一个ImageBrush,这意味这D3D Surface可以渲染到WPF中任意一个以Brush进行渲染的元素上,例如图片,文本前景色,元素背景色等等。
如下,就是一个典型的应用D3DImage的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if (d3dimg.IsFrontBufferAvailable)
{
IntPtr pSurface = IntPtr.Zero;
pSurface = _view.GetBackBuffer();

if (pSurface != IntPtr.Zero)
{
d3dimg.Lock();
d3dimg.SetBackBuffer(D3DResourceType.IDirect3DSurface9,pSurface);
_view.Draw();
d3dimg.AddDirtyRect(new Int32Rect(0, 0, d3dimg.PixelWidth, d3dimg.PixelHeight));
d3dimg.Unlock();
}
}

只需要Direct3D内容渲染的Surface接口指针即可,如上面的pSurface。