如何使用 Direct2D 处理像素

发布于 2024-12-29 06:54:03 字数 495 浏览 0 评论 0原文

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

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

使用 DirectDraw,我将在 IDirectDrawSurface7 上使用 BltFast 方法进行逻辑操作。有没有和Direct2D类似的东西?

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

Could somebody provide an example of an efficient way to work with pixels using Direct2D?

For example, how can I swap all green pixels (RGB = 0x00FF00) with red pixels (RGB = 0xFF0000) on a render target? What is the standard approach? Is it possible to use ID2D1HwndRenderTarget for that? Here I assume using some kind of hardware acceleration. Should I create a different object for direct pixels manipulations?

Using DirectDraw I would use BltFast method on the IDirectDrawSurface7 with logical operation. Is there something similar with Direct2D?

Another task is to generate complex images dynamically where each point location and color is a result of a mathematical function. For the sake of an example let's simplify everything and draw Y = X ^ 2. How to do that with Direct2D? Ultimately I'm going to need to draw complex functions but if somebody could give me a simple example for Y = X ^ 2.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青春有你 2025-01-05 06:54:03

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

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

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

First, it helps to think of ID2D1Bitmap as a "device bitmap". It may or may not live in local, CPU-addressable memory, and it doesn't give you any convenient (or at least fast) way to read/write the pixels from the CPU side of the bus. So approaching from that angle is probably the wrong approach.

What I think you want is a regular WIC bitmap, IWICBitmap, which you can create with IWICImagingFactory::CreateBitmap(). From there you can call Lock() to get at the buffer, and then read/write using pointers and do whatever you want. Then, when you need to draw it on-screen with Direct2D, use ID2D1RenderTarget::CreateBitmap() to create a new device bitmap, or ID2D1Bitmap::CopyFromMemory() to update an existing device bitmap. You can also render into an IWICBitmap by making use of ID2D1Factory::CreateWicBitmapRenderTarget() (not hardware accelerated).

You will not get hardware acceleration for these types of operations. The updated Direct2D in Win8 (should also be available for Win7 eventually) has some spiffy stuff for this but it's rather complex looking.

淡水深流 2025-01-05 06:54:03

里克的回答谈到了如果您不关心失去硬件加速的话可以使用的方法。我关注的是如何使用大量 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了解更多信息。

Rick's answer talks about the methods you can use if you don't care about losing hardware acceleration. I'm focusing on how to accomplish this using a substantial amount of GPU acceleration.

In order to keep your rendering hardware accelerated and to get the best performance, you are going to want to switch from ID2DHwndRenderTarget to using the newer ID2DDevice and ID2DDeviceContext interfaces. It honestly doesn't add that much more logic to your code and the performance benefits are substantial. It also works on Windows 7 with the Platform Update. To summarize the process:

  1. Create a DXGI factory when you create your D2D factory.
  2. Create a D3D11 device and a D2D device to match.
  3. Create a swap chain using your DXGI factory and the D3D device.
  4. Ask the swap chain for its back buffer and wrap it in a D2D bitmap.
  5. Render like before, between calls to BeginDraw() and EndDraw(). Remember to unbind the back buffer and destroy the D2D bitmap wrapping it!
  6. Call Present() on the swap chain to see the results.
  7. Repeat from 4.

Once you've done that, you have unlocked a number of possible solutions. Probably the simplest and most performant way to solve your exact problem (swapping color channels) is to use the color matrix effect as one of the other answers mentioned. It's important to recognize that you need to use the newer ID2DDeviceContext interface rather than the ID2DHwndRenderTarget to get this however. There are lots of other effects that can do more complicated operations if you so choose. Here are some of the most useful ones for simple pixel manipulation:

For generally solving the problem of manipulating the pixels directly without dropping hardware acceleration or doing tons of copying, there are two options. The first is to write a pixel shader and wrap it in a completely custom D2D effect. It's more work than just getting the pixel buffer on the CPU and doing old-fashioned bit mashing, but doing it all on the GPU is substantially faster. The D2D effects framework also makes it super simple to reuse your effect for other purposes, combine it with other effects, etc.

For those times when you absolutely have to do CPU pixel manipulation but still want a substantial degree of acceleration, you can manage your own mappable D3D11 textures. For example, you can use staging textures if you want to asynchronously manipulate your texture resources from the CPU. There is another answer that goes into more detail. See ID3D11Texture2D for more information.

熊抱啵儿 2025-01-05 06:54:03

将所有绿色像素替换为红色像素的具体问题可以通过 ID2D1Effect 自 Windows 8 和 Windows 7 平台更新开始。

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

The specific issue of swapping all green pixels with red pixels can be addressed via ID2D1Effect as of Windows 8 and Platform Update for Windows 7.

More specifically, Color matrix effect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文