如何使用Direct2D处理像素

7

有人能提供一个使用Direct2D处理像素的高效方法的示例吗?

例如,如何在渲染目标上将所有绿色像素(RGB = 0x00FF00)与红色像素(RGB = 0xFF0000)交换?这里假设使用某种硬件加速。我应该为直接像素操作创建不同的对象吗?是否可以使用ID2D1HwndRenderTarget实现?标准方法是什么?

使用DirectDraw,我会在IDirectDrawSurface7上使用BltFast方法进行逻辑操作。Direct2D中是否有类似的方法?

另一个任务是动态生成复杂图像,其中每个点的位置和颜色都是数学函数的结果。为了简化示例,让我们绘制Y = X ^ 2。如何使用Direct2D实现呢?最终我需要绘制复杂函数,但如果有人能给我一个关于Y = X ^ 2的简单示例就好了。

3个回答

12

首先,将ID2D1Bitmap视为“设备位图”会有所帮助。它可能存在于本地的CPU可寻址内存中,也可能不存在,并且并不提供任何方便(或至少快速)的方法从CPU侧读取/写入像素。因此,从这个角度接近可能是错误的方法。

我认为您想要的是一个常规的WIC位图,即IWICBitmap,可以使用IWICImagingFactory::CreateBitmap()创建。然后,您可以调用Lock()来获取缓冲区,然后使用指针读写并进行任何操作。然后,当您需要在Direct2D屏幕上绘制时,请使用ID2D1RenderTarget::CreateBitmap()创建新的设备位图,或者使用ID2D1Bitmap::CopyFromMemory()更新现有的设备位图。您还可以利用ID2D1Factory::CreateWicBitmapRenderTarget()(未经硬件加速)将其渲染到IWICBitmap中。

您将无法获得这些类型操作的硬件加速。Win8中更新的Direct2D(最终应该也可用于Win7)有一些很棒的东西处理这个问题,但看起来相对复杂。


10

Rick的回答提到了一些在不关心硬件加速时可以使用的方法。我着重介绍如何通过大量使用GPU加速来实现这一点。

为了保持您的渲染硬件加速并获得最佳性能,您需要从ID2DHwndRenderTarget切换到使用较新的ID2DDevice和ID2DDeviceContext接口。它其实并不需要在您的代码中增加太多逻辑,而且性能提升非常显著。它还可以在带有平台更新的Windows 7上使用。总结一下过程:

  1. 创建DXGI工厂时创建您的D2D工厂。
  2. 创建一个D3D11设备和一个匹配的D2D设备。
  3. 使用您的DXGI工厂和D3D设备创建一个交换链。
  4. 向交换链请求其后备缓冲区并将其包装在D2D位图中。
  5. 像以前一样进行渲染,在调用BeginDraw()和EndDraw()之间。记得取消绑定后备缓冲区并销毁包裹它的D2D位图!
  6. 在交换链上调用Present()以查看结果。
  7. 从第4步开始重复执行。
一旦完成这一步骤,您就可以解锁许多可能的解决方案。也许解决您确切问题(交换颜色通道)最简单且最高效的方法是使用颜色矩阵效果,正如其他答案中提到的那样。然而,重要的是要认识到,您需要使用较新的ID2DDeviceContext接口而不是ID2DHwndRenderTarget才能实现这一点。如果您愿意,还有许多其他可以执行更复杂操作的效果。以下是一些用于简单像素处理的最有用的效果: 一般而言,如果要直接操作像素而不降低硬件加速或进行大量复制,有两个选项。第一个是编写像素着色器并将其包装在完全自定义的D2D效果中。这比仅仅在CPU上获取像素缓冲区并进行传统的位操作更费力,但在GPU上完成所有操作的速度要快得多。D2D效果框架还使得重用您的效果以及与其他效果组合等变得非常简单。
对于那些必须进行CPU像素操作但仍希望获得相当程度的加速的情况,可以管理自己可映射的D3D11纹理。例如,如果你想异步地从CPU操作你的纹理资源,你可以使用暂存纹理。有another answer提供了更详细的信息。请参见ID3D11Texture2D以获取更多信息。

2
值得注意的是,您可以在任何类型的ID2D1RenderTarget上使用QueryInterface来获取ID2D1DeviceContext。这使您可以使用更简单的ID2D1Factory :: CreateHwndRenderTarget方法,但仍然可以获得更新的API并避免处理DXGI / Direct3D文件。据我所知,这是未记录的,但似乎是有意为之的。 - Rick Brewster
@zhuman,为什么你会说“记得解绑后备缓冲区并销毁包装它的D2D位图!”在调用Present()之前为什么要这样做? - deLock

0

交换所有绿色像素和红色像素的特定问题可以通过 Windows 8 和 Windows 7 平台更新中的 ID2D1Effect 来解决。

更具体地说,使用 颜色矩阵效果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接