【问题标题】:How to work with pixels using Direct2D如何使用 Direct2D 处理像素
【发布时间】:2012-02-19 17:32:32
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: direct2d directdraw


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      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 开始重复。

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

      对于一般解决直接操作像素而不降低硬件加速或进行大量复制的问题,有两种选择。首先是编写一个像素着色器并将其包装在一个完全自定义的 D2D 效果中。这不仅仅是在 CPU 上获取像素缓冲区并进行老式的位混搭,而是在 GPU 上完成所有这些工作要快得多。 D2D 效果框架还使得将效果重用于其他目的、将其与其他效果组合等变得超级简单。

      当您绝对需要处理 CPU 像素但仍需要大幅加速时,您可以管理自己的可映射 D3D11 纹理。例如,如果您想从 CPU 异步操作纹理资源,则可以使用暂存纹理。 another answer 更详细。请参阅ID3D11Texture2D 了解更多信息。

      【讨论】:

      • 值得注意的是,您可以在ID2D1RenderTarget(任何类型)上使用QueryInterface 来获取ID2D1DeviceContext。这使您可以使用更简单的ID2D1Factory::CreateHwndRenderTarget 方法,但仍可以获得更新的 API 并避免处理 DXGI / Direct3D 文书工作。据我所知,这是无证的,但似乎是故意的。
      【解决方案3】:

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

      更具体地说,Color matrix effect.

      【讨论】:

        猜你喜欢
        • 2014-07-04
        • 2012-06-01
        • 1970-01-01
        • 2012-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-26
        相关资源
        最近更新 更多