使用OpenGL渲染和GLSL的GL_HALF_FLOAT

3

我正在用C++编写一个OpenGL渲染器。我希望它尽可能高效,每个顶点/法线/UV纹理坐标/切线等占用的内存尽量少。我使用索引、线条和扇形。我认为32位浮点数并不是必需的,16位浮点数应该足够了,至少对于一些像法线和UV这样的属性来说。但我似乎找不到任何关于这方面的例子。我可以找到有关"GL_HALF_FLOAT"的讨论,但没有实际的示例。我走在正确的道路上吗?或者这不值得深入研究?如果有人知道这方面的示例,请发送源代码链接。


1
你可以使用uint数据类型来打包和解包两个半精度浮点数。但在GLSL中,你能得到的最小数据类型是32位。请参阅uint packHalf2x16( vec2 v)以获取更多详细信息。 - Andon M. Coleman
@AndonM.Coleman,您可以在顶点缓冲区中使用HALF_FLOAT数据。当它到达着色器时,它当然会被扩展为32位精度,但如果半浮点足够精确,则仍然可以节省内存空间和带宽。 - Reto Koradi
@RetoKoradi:我完全读错了问题,因为我的思维在其他地方:-\ 我有点看到了标签,并认为他想要在GLSL中更改“float”的精度。是的,你是绝对正确的,尽管由于半浮点数不是大多数语言的一部分,所以像glm(假设这是C++)将不得不扮演那个角色。 - Andon M. Coleman
1个回答

5
在完整的OpenGL中(与OpenGL ES不同),着色器代码始终使用32位浮点数。从OpenGL 3.0开始,支持将顶点数据指定为半精度浮点数。如果精度足够满足您的需求,则可以减少顶点数据的内存使用量,并减少顶点提取所需的带宽。
请记住,半精度浮点数的精度仅约为3-4个小数位。因此,精度真正受到严重限制。
至于如何使用它们,这非常简单。如果您有半精度浮点值的指针,您可以使用glBufferData()glBufferSubData()将它们存储在VBO中,就像对任何其他类型一样。然后,glVertexAttribPointer()调用将如下所示,以一个具有3个组件的属性为例:
glVertexAttribPointer(loc, 3, GL_HALF_FLOAT, GL_FALSE, 0);

数据本身的格式是在ARB_texture_float扩展中定义的。尽管它没有官方名称,但它看起来至少非常类似于IEEE 754-2008格式。我以前根据维基百科的格式描述编写了转换代码,并且对于OpenGL使用工作正常。

大多数语言都没有内置的半浮点类型。因此,您要么需要编写几行代码将float转换为half-float,要么使用其他人编写的代码。

以下关于半浮点转换的资源是通过快速搜索得到的。我个人没有任何经验,您应该自行搜索找到最适合您需求的资源:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接