如何使用Direct2D处理像素

时间:2012-01-26 16:14:54

标签: direct2d directdraw

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

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

使用DirectDraw我会在BltFast上使用IDirectDrawSurface7方法进行逻辑运算。与Direct2D有类似的东西吗?

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

3 个答案:

答案 0 :(得分:12)

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

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

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

答案 1 :(得分:8)

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开始重复。
  8. 完成后,您已解锁了许多可能的解决方案。解决您的确切问题(交换颜色通道)可能是最简单,最高效的方法是使用color matrix effect作为提到的其他答案之一。重要的是要认识到你需要使用较新的ID2DDeviceContext接口而不是ID2DHwndRenderTarget来获得它。如果您愿意,还有许多其他效果可以执行更复杂的操作。以下是一些用于简单像素操作的最有用的方法:

    一般来说,为了解决直接操作像素而不降低硬件加速或进行大量复制的问题,有两种选择。第一种是编写像素着色器并将其包装在完全自定义的D2D效果中。除了在CPU上获得像素缓冲区并进行老式的位混搭之外,还有更多的工作,但在GPU上完成所有这些工作要快得多。 D2D效果框架还可以非常简单地将效果重用于其他目的,将其与其他效果结合使用等。

    对于那些绝对需要进行CPU像素操作但仍需要大幅度加速的时候,您可以管理自己的可映射D3D11纹理。例如,如果要从CPU异步操作纹理资源,则可以使用分段纹理。有another answer更详细的内容。有关详细信息,请参阅ID3D11Texture2D

答案 2 :(得分:0)

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

更具体地说,Color matrix effect.