是否可以在现代 GPU 上进行老式 2d 位图?

Posted

技术标签:

【中文标题】是否可以在现代 GPU 上进行老式 2d 位图?【英文标题】:Is it possible to do old school 2d blitting on modern GPU? 【发布时间】:2011-01-21 23:33:14 【问题描述】:

看起来 GL 已成为所有游戏平台的主流(甚至是手持设备!) 这将现代 GPU 芯片组的部署推向大量消费者。

这太棒了。

现在有了现代 GPU 系统,是否可以制作通用的老式图形 编程(又名 - 使用 VRAM 从 X rect 到 Y rect 的 blit)? (想想Amiga)还是以运营为中心 围绕顶点和像素着色器?

这可以从 GL 访问吗? OpenGL ES?

渲染一个带纹理的四边形是可以的,但它需要双缓冲并重新渲染整个场景。正在看我是否可以避免这种情况。

【问题讨论】:

我在这方面的经验几乎为零,所以这可能是一个愚蠢的建议,但是如果3D图形很快,并且你需要2D图形,你不能只使用3D能力而保持Z = 0 只让 X 和 Y 变化? 您将永远无法在自己的代码中更快地完成可以在 3D 硬件中完成的任何事情,您将时间浪费在过早的优化上。 @Earwicker,这就是一些答案所暗示的...... @Earlz - 啊,我只是不懂行话。 @fuzzy lollipop - 两个答案显示了通过 api 暴露的硬件角度。 glBlitFrameBuffer 和旧的 glCopyPixels 由 GPU 执行全 VRAM 速度 blits。 【参考方案1】:

检查glBlitFramebuffer 例程 (Framebuffer Object)。您需要更新的驱动程序。

请记住,您仍然可以使用默认帧缓冲区,但我认为使用帧缓冲区对象会更有趣。

将您的精灵保存在单独的帧缓冲区中(可能使用 OpenGL 渲染),并将它们设置为已读(使用 glReadBuffers)并在绘制帧缓冲区上对它们进行 blit(使用 glDrawBuffers)。它非常简单快捷。

【讨论】:

【参考方案2】:

好吧,您可以使用libSDL 并获取指向屏幕帧缓冲区的指针,然后对像素做任何您想做的事情。 或者您可以将所有绘图都写入内存缓冲区,加载到 GL 纹理并绘制带纹理的四边形,这可能会因为硬件加速而更快。

【讨论】:

我不想要帧缓冲区、指针,我想使用 GPU 上的代码来完成这一切。 @drudru,你听说过 OpenCL。我认为这与在某些 Nvidia GPU 上执行任意代码有关 @Earls - 是的,这可能是票。我希望那个阵营的人能插话。【参考方案3】:

在某些嵌入式系统上可能会获得一个帧缓冲区指针并直接写入它,但现在最好使用 OpenGL|ES 并渲染纹理。它会更便携,而且可能更快。

你可以在主内存中创建一个缓冲区,做所有你想做的事情,然后将它渲染为一个纹理。您可以将纹理数据 DMA 到 VRAM 以提高速度,然后以四边形渲染它,这相当于 blit,但不使用任何 CPU 周期并且运行速度与 GPU 可以处理的速度一样快。

如今,您可以使用着色器和可编程管道做的事情令人惊叹。

【讨论】:

我不想要帧缓冲区、指针,我想使用 GPU 上的代码来完成这一切。 好的,看看render-to-texture technique。您使用着色器将您喜欢的任何内容渲染到纹理上,然后使用四边形绘制该纹理,这会将其传送到屏幕上。您也可以根据纹理参数和混合模式从各种 ROP 中进行选择。【参考方案4】:

如果您正在绘制带纹理的四边形,您可以使用它轻松模拟“老式”blitting,那么实际上这些像素是由 GPU 从视频内存中复制的。另请注意,虽然位图操作在 OpenGL 中是可能的,但由于 3D 路径在消费级视频卡上进行了优化,而 2D 路径可能不是,因此它们可能会非常缓慢。

【讨论】:

渲染四边形与双缓冲关系不大。如果目标设备上应该这样做,您可以使用单个缓冲区。但是,如果整个框架发生了变化,那么无论如何您都必须更新所有内容。 true,但是对于我的应用程序,90% 的操作都是滚动。在老式硬件上,这只是将硬件 VRAM 指针移动到具有预设模数的新位置的问题。快速 blit 也可以解决问题。在我的应用程序中,我可以避免整个重绘。谢谢你的回答。 @drudru:在过去,您需要像那样滚动,因为您没有处理器时间来重绘框架。现在有了硬件,你可以多次重绘屏幕,仍然有时间消磨。特别是如果你只做'2d' blits【参考方案5】:

此外,如果您正确设置了环境,glCopyPixels 似乎可以解决问题。

【讨论】:

【参考方案6】:

在Windows上可以使用低级位图复制功能,准确匹配旧描述,无需任何OpenGL等。

BOOL BitBlt(
  _In_ HDC   hdcDest,
  _In_ int   nXDest,
  _In_ int   nYDest,
  _In_ int   nWidth,
  _In_ int   nHeight,
  _In_ HDC   hdcSrc,
  _In_ int   nXSrc,
  _In_ int   nYSrc,
  _In_ DWORD dwRop
);

https://msdn.microsoft.com/en-us/library/dd183370%28v=vs.85%29.aspx

【讨论】:

以上是关于是否可以在现代 GPU 上进行老式 2d 位图?的主要内容,如果未能解决你的问题,请参考以下文章

Direct2D教程渲染位图

将位图(RGB_565)转换为灰度(8位)Android

在现代 amd64 CPU 上进行 memset 的最快方法

如何对 INTEL GPU 进行编程

关于OpenGL纹理 装载位图的问题

WebGL - 发送数组缓冲区 VS 将图像/画布/位图从 CPU 发送到 GPU