为什么存在 glVertexAttribPointer 的不同变体?
Why do different variations of glVertexAttribPointer exist?
有
glVertexAttribPointer()
glVertexAttribIPointer()
glVertexAttribLPointer()
据我所知,glVertexAttribPointer
可以代替其他两个
如果是,为什么存在 I
和 L
变体?
我在 OpenGL Insights 中看到了这个
使用 glVertexAttribPointer()
时,所有内容都会转换为浮点数。虽然 glVertexAttribIPointer()
只能公开存储整数的顶点数组,而 glVertexAttribLPointer()
仅适用于双精度数。
正如对此 OpenGL.org page 的引述所证实:
For glVertexAttribPointer, if normalized is set to GL_TRUE, it
indicates that values stored in an integer format are to be mapped to
the range [-1,1] (for signed values) or [0,1] (for unsigned values)
when they are accessed and converted to floating point. Otherwise,
values will be converted to floats directly without normalization.
For glVertexAttribIPointer, only the integer types GL_BYTE,
GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT,
GL_UNSIGNED_INT are accepted. Values are always left as integer
values.
glVertexAttribLPointer specifies state for a generic vertex attribute
array associated with a shader attribute variable declared with 64-bit
double precision components. type must be GL_DOUBLE. index, size,
and stride behave as described for glVertexAttribPointer and
glVertexAttribIPointer.
不可以,它们不能相互代替使用。
传统上,GL的所有顶点属性都是浮点数。您可以输入整数数据这一事实并没有改变这一点——数据会即时转换为浮点数。 normalized
参数控制转换的完成方式,如果启用,输入类型的范围将映射到规范化的 [0,1](对于无符号类型,也称为 GL 的 UNORM)或 [- 1,1](对于有符号类型,也称为SNORM),如果禁用,则将值直接转换为输入整数最接近的浮点值。
由于这是原始的 API,因此在引入不同的属性数据类型(整数和双精度)时必须对其进行扩展。另请注意,属性指针独立于着色器,因此目标值不能由当前绑定的着色器(如果有)确定,因为稍后可能会与不同的着色器一起使用。因此,L
变体 ID 用于 double/dvec
属性,而 I
变体用于 int/uint/ivec/uvec
属性。
测试一下,你就会明白其中的区别。
假设您正在使用以下顶点着色器进行变换反馈:
#version 450 core
layout(location = 0) in int input;
layout(xfb_offset = 0) out float output;
void main()
{
output = sqrt(input);
}
这是你的 "vertex data":
GLint data[] = { 1, 2, 3, 4, 5 };
那么如果你像这样设置顶点属性:
glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, nullptr);
你会得到错误和奇怪的结果。
如果在顶点着色器中更改此行
output = sqrt(input);
至
output = sqrt(intBitsToFloat(input));
或
在 C++ 代码中更改此行:
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
^^^^^^^^
does not match the real input type
but stops glVertexAttribPointer() converting them
它会起作用的。但这不是自然的方式。
现在glVertexAttribIPointer()
来帮忙:
--- glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, nullptr);
+++ glVertexAttribIPointer(0, 1, GL_INT, 0, nullptr);
那么你会得到正确的结果。
(为此折腾了一下午,才找到glVertexAttribIPointer()
。)
有
glVertexAttribPointer()
glVertexAttribIPointer()
glVertexAttribLPointer()
据我所知,glVertexAttribPointer
可以代替其他两个
如果是,为什么存在 I
和 L
变体?
我在 OpenGL Insights 中看到了这个
使用 glVertexAttribPointer()
时,所有内容都会转换为浮点数。虽然 glVertexAttribIPointer()
只能公开存储整数的顶点数组,而 glVertexAttribLPointer()
仅适用于双精度数。
正如对此 OpenGL.org page 的引述所证实:
For glVertexAttribPointer, if normalized is set to GL_TRUE, it indicates that values stored in an integer format are to be mapped to the range [-1,1] (for signed values) or [0,1] (for unsigned values) when they are accessed and converted to floating point. Otherwise, values will be converted to floats directly without normalization.
For glVertexAttribIPointer, only the integer types GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT are accepted. Values are always left as integer values.
glVertexAttribLPointer specifies state for a generic vertex attribute array associated with a shader attribute variable declared with 64-bit double precision components. type must be GL_DOUBLE. index, size, and stride behave as described for glVertexAttribPointer and glVertexAttribIPointer.
不可以,它们不能相互代替使用。
传统上,GL的所有顶点属性都是浮点数。您可以输入整数数据这一事实并没有改变这一点——数据会即时转换为浮点数。 normalized
参数控制转换的完成方式,如果启用,输入类型的范围将映射到规范化的 [0,1](对于无符号类型,也称为 GL 的 UNORM)或 [- 1,1](对于有符号类型,也称为SNORM),如果禁用,则将值直接转换为输入整数最接近的浮点值。
由于这是原始的 API,因此在引入不同的属性数据类型(整数和双精度)时必须对其进行扩展。另请注意,属性指针独立于着色器,因此目标值不能由当前绑定的着色器(如果有)确定,因为稍后可能会与不同的着色器一起使用。因此,L
变体 ID 用于 double/dvec
属性,而 I
变体用于 int/uint/ivec/uvec
属性。
测试一下,你就会明白其中的区别。
假设您正在使用以下顶点着色器进行变换反馈:
#version 450 core
layout(location = 0) in int input;
layout(xfb_offset = 0) out float output;
void main()
{
output = sqrt(input);
}
这是你的 "vertex data":
GLint data[] = { 1, 2, 3, 4, 5 };
那么如果你像这样设置顶点属性:
glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, nullptr);
你会得到错误和奇怪的结果。
如果在顶点着色器中更改此行
output = sqrt(input);
至
output = sqrt(intBitsToFloat(input));
或
在 C++ 代码中更改此行:
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
^^^^^^^^
does not match the real input type
but stops glVertexAttribPointer() converting them
它会起作用的。但这不是自然的方式。
现在glVertexAttribIPointer()
来帮忙:
--- glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, nullptr);
+++ glVertexAttribIPointer(0, 1, GL_INT, 0, nullptr);
那么你会得到正确的结果。
(为此折腾了一下午,才找到glVertexAttribIPointer()
。)