如何使用Direct2D处理像素



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

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

使用DirectDraw,我将在具有逻辑运算的IDirectDrawSurface7上使用BltFast方法。Direct2D有类似的东西吗?

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

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

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

对于这些类型的操作,您将无法获得硬件加速。Win8中更新的Direct2D(最终也应该适用于Win7)对此有一些不错的东西,但看起来相当复杂。

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

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

  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。

从Windows 8起,可以通过ID2D1Effect和Windows 7平台更新来解决用红色像素替换所有绿色像素的具体问题。

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

最新更新