使用 OpenGL 进行像素完美的 2D 渲染

Posted

技术标签:

【中文标题】使用 OpenGL 进行像素完美的 2D 渲染【英文标题】:Pixel-Perfect 2D Rendering with OpenGL 【发布时间】:2013-01-30 16:05:32 【问题描述】:

是否可以设置 OpenGL 场景以实现像素完美的渲染和像素位块传输?我注意到通过以下方式设置场景:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, width, height, 0.0, 0.0, 1.0);

然后使用以下方法绘制一个像素:

glBegin(GL_POINTS);
glVertex2i(0, 0);
glEnd();

是否始终在每个硬件配置的左上角像素上绘制它(有时它在左侧一个像素,或左上角下方一个像素)。我意识到这可能是由于图形驱动程序对 OpenGL 的不同实现,但是有没有办法让它左上角的像素是(0,0),右下角是(width-1,height-1 ) 始终如一?这似乎很奇怪,这不是标准化的东西......

我看到了一些使用 (0.375, 0.375) 或 (0.5, 0.5) 的翻译的“黑客”,但这似乎也解决了某些配置而不是其他配置的问题。

【问题讨论】:

【参考方案1】:

edit:该死,这是翻译。已更新。

您还必须考虑像素也有大小。这就是“翻译黑客”的目的。如果最左边的像素应该有一个center 坐标0.0,那么它的左边界在-0.5——这就是剪切平面应该在的位置。同样,如果最右边的像素应该有一个center 坐标width - 1,那么它的右边界在(width - 1) + 0.5——这就是剪切平面应该在的位置。

那就试试吧:

glOrtho(-0.5, (width - 1) + 0.5, (height - 1) + 0.5, -0.5, 0.0, 1.0);

这就是翻译的来源。

【讨论】:

你说得对:左上角像素的中心实际上在窗口坐标中的 (0.5, 0.5) 处,其范围从 (0,0) - (1, 1)。要在正确的像素上画一个点,他需要将其偏移半个像素。【参考方案2】:

在第一次检查时,它似乎应该可以工作,并且如果实现偏移了一个像素,我怀疑它们可能不符合规范。然而,这也可能是由于视图被颠倒了,并且一些不准确性逐渐出现并导致舍入问题。我不相信是这样,但如果我想做像素完美的渲染,我不会从引入不必要的变换开始。

无论如何,我很可能会完全避免使用固定功能管道,只需确保使用我自己的变换计算顶点着色器中的正确坐标即可。所以这是我的第一个建议 - 现代可编程管道让您可以更好地控制正在发生的事情。

如果做不到这一点,至少尝试以正确的方式渲染事物,看看这是否会使您所针对的各种平台更加一致。

另外,我认为这有点 hack,但有时这些东西是必要的 - 你可以检查它,并使用变换相应地偏移你的坐标(即绘制一个像素并读回它以查看它是否结束在正确的地方,如果没有,它确实去了哪里)。当然,您可能只是让问题更加复杂。

我不会在这里过多地摆弄子像素偏移,您更有可能只是介绍更多像素不再按您想要的 1:1 映射的情况。

【讨论】:

我尝试在 glOrtho 调用中交换顶部和底部以尝试正面朝上,但在 AMD 图形驱动程序上运行时它似乎可以正常工作,禁用驱动程序并再次运行它会在更接近(宽度,高度)的像素上引入一些偏移。对我来说,使用整数坐标值绘制点应该会产生关于哪个像素应该被 blitted 的任何歧义,这对我来说似乎很奇怪。 有可能它们被转换为浮点数并通过整个变换/着色器管道。

以上是关于使用 OpenGL 进行像素完美的 2D 渲染的主要内容,如果未能解决你的问题,请参考以下文章

使用 opencl 将软件渲染到 opengl 2d 视图 [关闭]

OpenGL-渲染流程

OpenGL工作流程

OpenGL:如何渲染完美的矩形渐变?

OpenGL 中的 2D 绘图:在原始尺寸下具有像素精度的线性过滤

使用 VAO/VBO 进行 OpenGL 模型/纹理渲染