【问题标题】:OpenGL 1 pixel high texture rendering difference Windows/Linux vs OS XOpenGL 1 像素高纹理渲染差异 Windows/Linux vs OS X
【发布时间】:2021-06-04 01:08:31
【问题描述】:

我需要帮助了解为什么我需要进行特定更改以使我的 OpenGL 项目在 OS X(2019 Macbook)上运行,而无需更改它在 Windows 和 Linux 上完美运行,在 ATI 和 NVIDIA 硬件上。

在某些时候,我正在渲染到一个 1024 像素宽和 1 像素高的帧缓冲区。我需要直接的正交投影,所以对于我的投影矩阵,我使用:

glm::ortho(0.f, (float)LookupMapSize, 1.f, 0.f)

在 Windows 和 Linux 上使用这个投影矩阵,我渲染了我的线条几何图形,它按预期工作,所有像素都被写入。

然而,在 OS X 上,我最初在我的帧缓冲区中没有看到任何内容,只是我用 glClearColor 和 glClear 清除它的颜色。怀疑着色器问题,我将片段输出设置为vec4(1),期望得到全白的结果,但我仍然只看到帧缓冲区中的清晰颜色。深度测试、混合、剔除和模板都不是问题,所以一定是我的矩阵错了。经过一番折腾,我终于想通了,我只需要将投影矩阵更改为:

glm::ortho(0.f, (float)LookupMapSize, 0.f, 1.f)

但是为什么呢?这种差异从何而来?因此,在 Windows/Linux 中,底部位于 1.f,顶部位于 0.f,而在 OS X 中则正好相反。如果我在 Windows/Linux 上使用“OS X”矩阵,我会得到与最初在 OS X 上完全相同的错误。

我不只是在我的代码中保留这个特定于平台的更改,而是想了解发生了什么。

edit:我会自动检查我所有的 OpenGL 调用 (glGetError),没有任何地方返回任何错误。不幸的是,OpenGL 调试功能 (glDebugMessageCallback) 在 OS X 上不可用...

edit:我验证了在 OSX 和 Linux/Windows 上 glm::ortho 的结果是相同的。所以我对 OpenGL 的输入在所有平台上都是相同的。

【问题讨论】:

  • GLSL 日志在说什么?我在过去 2 年的经验是高级或非标准着色器使用在 gfx 供应商、驱动程序版本、操作系统中不可靠,标准功能通常在任何地方都能很好地工作......所以你必须在许多不同的硬件上进行测试以确保你有足够的 bug免费...我敢打赌,您的 OS X gfx 驱动程序的着色器代码存在一些语法问题(通常是一些微不足道的问题,例如不支持的字符或文字,适用于不同的实现)...还有什么 gfx 在您的 MAC 上使用?英特尔通常在渲染到纹理时遇到问题
  • @Spektre 正如所说,除了正交投影外,我不需要更改任何其他内容即可使其完美运行,所以我认为这里的着色器代码没有问题(它没有做任何特别的事情反正)。我可能应该在我的问题中补充一点,我会自动检查所有 OpenGL 调用,并且在任何地方都没有报告任何错误,谢谢
  • macOS 的 OpenGL 驱动程序非常糟糕,所以谁知道呢。您可以仔细检查您是否符合 OpenGL 规范,但即使您是 Apple,也不会修复驱动程序。
  • @Spektre 它是 Intel 硬件 btw,Intel UHD Graphics 630 1536 MB
  • @foddex 嗯我讨厌英特尔高清显卡......他们有最糟糕的 OpenGL 驱动程序,英特尔从不为旧卡修复它们......

标签: c++ macos opengl projection glm-math


【解决方案1】:

OpenGL 没有被指定为像素精确的渲染 API,GPU 和不同的驱动程序(即使在同一个 GPU 上)不会产生具有相同输入的相同输出。然而,OpenGL 规范实际上对实现者提出了硬性要求,而您作为 API 的用户可以依赖。

在您的情况下,如果您使用正交矩阵设置 1 像素高的视口,y 范围从 0 到 1 意味着 y=0 将是底部 edge您的像素行,1 将是顶部edge。如果您在两个像素之间的边缘上精确地画一条线,OpenGL 规范并没有指定在这种情况下实现必须“舍入”到哪个方向,它们只是必须始终以相同的方式进行舍入。

所以这意味着如果您拥有的两个选项是 y=0 和 y=1,则两个选项中的 一个 *不会画线(因为它在技术上位于您的帧缓冲区之外),但哪一个是完全特定于实现的。

但是,故意在像素之间的边缘上画线是个坏主意,尤其是当你有一些非常特定的像素要填充时。将顶点设置在要填充的像素的 center 最有意义,这是y=0.5。

但是,对于只生成 widthx1 LUT 的通道,我认为不需要设置任何类型的转换矩阵,您可以在未转换的剪辑中工作,只需从 (-1,0,0,1) 绘制到 (1,0,0,1) . y=0 很好,因为那正是您视口的中心。

【讨论】:

  • 使用您最后的建议,在剪辑空间中绘图,是迄今为止最好的解决方案,并且对我来说非常有效。感谢其他解释,这也很清楚!
猜你喜欢
  • 1970-01-01
  • 2015-03-15
  • 2013-12-27
  • 2014-08-09
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2019-04-02
相关资源
最近更新 更多