如何使用Direct2D处理像素

Ale*_*lex 6 directdraw direct2d

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

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

使用DirectDraw我会BltFastIDirectDrawSurface7with逻辑操作上使用方法.Direct2D有类似的东西吗?

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

Ric*_*ter 12

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

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

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


zhu*_*SFT 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.

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

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

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

  • 值得注意的是,您可以在`ID2D1RenderTarget`(任何类型)上使用`QueryInterface`来获取`ID2D1DeviceContext`.这允许您使用更简单的`ID2D1Factory :: CreateHwndRenderTarget`方法,但仍然可以获得更新的API并避免处理DXGI/Direct3D文书工作.这是没有记载的,但从我能说的来看似乎是故意的. (2认同)