7

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

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

使用 DirectDraw 我会在with 逻辑操作上使用BltFast方法。IDirectDrawSurface7Direct2D有类似的东西吗?

另一项任务是动态生成复杂图像,其中每个点的位置和颜色都是数学函数的结果。举个例子,让我们简化一切并绘制Y = X ^ 2。如何用 Direct2D 做到这一点?最终我将需要绘制复杂的函数,但如果有人能给我一个简单的例子Y = X ^ 2

4

3 回答 3

12

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

我认为您想要的是一个常规的 WIC 位图 IWICBitmap,您可以使用 IWICImagingFactory::CreateBitmap() 创建它。从那里你可以调用 Lock() 来获取缓冲区,然后使用指针读/写并做任何你想做的事情。然后,当您需要使用 Direct2D 在屏幕上绘制它时,使用 ID2D1RenderTarget::CreateBitmap() 创建新的设备位图,或使用 ID2D1Bitmap::CopyFromMemory() 更新现有设备位图。您还可以通过使用 ID2D1Factory::CreateWicBitmapRenderTarget()(非硬件加速)渲染到 IWICBitmap。

对于这些类型的操作,您不会获得硬件加速。Win8 中更新的 Direct2D(最终也应该可用于 Win7)为此提供了一些漂亮的东西,但看起来相当复杂。

于 2012-02-21T21:47:41.263 回答
10

Rick 的回答谈到了如果您不关心失去硬件加速可以使用的方法。我专注于如何使用大量的 GPU 加速来实现这一点。

为了保持渲染硬件加速并获得最佳性能,您将希望从 ID2DHwndRenderTarget 切换到使用更新的 ID2DDevice 和 ID2DDeviceContext 接口。老实说,它不会为您的代码添加更多逻辑,并且性能优势是巨大的。它也适用于带有平台更新的 Windows 7。总结一下过程:

  1. 在创建 D2D 工厂时创建 DXGI 工厂。
  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 异步操作纹理资源,则可以使用暂存纹理。还有另一个更详细的答案。有关详细信息,请参阅ID3D11Texture2D

于 2014-03-06T06:59:54.183 回答
0

将所有绿色像素与红色像素交换的具体问题可以通过ID2D1EffectWindows 8 和 Windows 7 的平台更新来解决。

更具体地说,颜色矩阵效应。

于 2013-08-28T14:59:03.813 回答