OpenGL浮点精度

Posted

技术标签:

【中文标题】OpenGL浮点精度【英文标题】:OpenGL floating point precision 【发布时间】:2020-01-14 19:01:35 【问题描述】:

我正在开展一个从旧版/即时 OpenGL 迁移到现代 OpenGL(核心配置文件)的项目。在传统的 OpenGL 实现中,我们使用了双精度,即我们在 glVertexPointer 中使用了 GL_DOUBLE,我们使用了 glLoadMatrixd 等。但是,在现代 OpenGL 中,只有 OpenGL/GLSL 4.0+ 支持双精度。

旧的 OpenGL 如何支持双精度,而新的 OpenGL 不支持? 传统 OpenGL 如何处理双精度,而大多数显卡甚至不支持双精度?

我在互联网上找不到任何信息,或者某些答案太旧了。

目前的显卡支持双精度吗?我应该使用 OpenGL 4.0 吗?

【问题讨论】:

如果 GL_DOUBLE 在几乎所有情况下实际上都没有等同于 C++ double,我会感到非常惊讶。 我不确定,但我希望旧显卡默认使用半浮动。并且 GL_DOUBLE 意味着常规浮动。但我只是推测。显卡支持double,但它们往往拥有更少的内核来执行双重计算,这使得它几乎毫无用处,因为性能会受到巨大影响。 @JesperJuhl GL_DOUBLE 应该等于 c++ double,因为旧版 OpenGL 与 C++ double 一起使用。但是,现代 OpenGL(不是 OpenGL 4.0+)没有用于双精度的 API,即 glUniform 不接受双精度,并且您无法在着色器中定义双精度。 【参考方案1】:

旧的 OpenGL 如何支持双精度,而新的 OpenGL 不支持?传统 OpenGL 如何处理双精度,而大多数显卡甚至不支持双精度?

它不是你想的那样。您可以使用双精度作为顶点属性并不意味着(并且从未这样做过)GL 实现将以该精度进行计算——GPU 从未这样做过。在任何情况下,数据都会转换为单精度。矩阵也是如此——在旧版 GL 中,发送到 GPU 的矩阵永远不会是双精度的,无论您在指定 CPU 端数据时使用的是 d 还是 f 后缀。

在更新的 GPU 中,着色器内核提供了双精度,而现代 GL 4.x 允许您第一次使用它

另外请注意,许多实际消费级 GPU 的双精度比都非常低,例如 FP32 性能的 1/32,因此您最好在使用之前三思而后行。对于图形,您很少需要它。而且您之前的代码与旧版 GL 一起使用的事实证明您不需要精度。

【讨论】:

感谢您的回答!所以即使我用glm::dvec3 顶点调用glVertexPointer,显卡内部也使用单精度? 是的!为此,您需要 GL4.something 和 glVertexAttirbLPointer(注意函数名称中的 L,“L”代表“double”) @TaoChen:“所以即使我用 glm::dvec3 顶点调用 glVertexPointer,显卡内部也使用单精度?” 不仅如此。如果您尝试这样做,系统基本上必须在 CPU 上 读取您的顶点数据并将双精度数转换为浮点数,因为硬件实际上无法读取它们。这样做会影响你的表现。 "对于图形,您很少需要它。" 实际上,您将使用它的最明显的地方(VS 中的位置)实际上并没有帮助,因为 @987654327 @ 是单精度向量。即使不是,使用它的硬件肯定也无法处理双精度值。深度缓冲区也不能。

以上是关于OpenGL浮点精度的主要内容,如果未能解决你的问题,请参考以下文章

通过表面写入 CUDA 中的浮点 OpenGL 纹理

OpenGL ES 2.0 符点精度

转换浮点数组中的 blend 或 obj 文件以在 OpenGL 中绘图

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

是否可以将 Mat4 作为 rust 'glam' crate 中的浮点指针传递给 Opengl 调用 gl::UniformMatrix4fv?

如何将变量(不统一)浮点值从 C++ 传递到顶点着色器 OpenGL ES 2.0