我想节省内存,因为输入数据在 [0,..,255] 范围内,所以我不需要 4xFloat,但 4xByte 就足够了。 GLSL 和 gpu 不喜欢字节,所以需要打包和解包。也不应发生精度损失。
C++和打包代码:
最快和最简单的解决方案应该是使用 uint 进行传输。 GLM 已经准备好 vector ,所以将 glm::u8vec4(1, 1, 1, 1) 放入顶点数组应该没问题。我用 gDEBugger 检查了顶点数组,所以我确信它们包含正确的数据。 VAP 看起来像这样:
glVertexAttribPointer(
0,
1, // one element
GL_UNSIGNED_INT, //transfer data type
GL_FALSE, //dont normalize
1 * sizeof(GLuint), // size of one element
(void*)0 // offset
);
GLSL 和解包:
layout(location = 0) in uint data;
vec4 unpack;
unpack.x = float((data & uint(0xff000000)) >> 24);
unpack.y = float((data & uint(0x00ff0000)) >> 16);
unpack.z = float((data & uint(0x0000ff00)) >> 8);
unpack.w = float((data & uint(0x000000ff)) >> 0);
结果应该提供提示,但它太乱了。
编辑:
即使我的解决方案毫无意义,也有两个错误。首先如下所述,我必须使用 glVertexAttribIPointer。其次,在我的例子中,移位是镜像的(X 应该移动 0,Y 移动 8,..)。
正确的解决方案是这样的:
glVertexAttribPointer(
0,
4,
GL_UNSIGNED_BYTE,
GL_FALSE,
4 * sizeof(GLubyte),
(void*)0
);
shader:
layout(location = 0) in vec4 data;
最佳答案
GLSL and gpu don't like bytes so pack and unpack is required. Also no precision loss should occur.
为什么这么说?使用 GL_UNSIGNED_BYTE
属性数据得到了很好的支持并且非常普遍(例如颜色)。这没有性能问题(只要遵守基本对齐规则)。
GL 会自动将整数属性数据转换为 float 。 normalized
参数定义数据是否应规范化为 [0,1](或 [-1,1] 有符号 int 类型)范围,或者是否应直接转换为 float,因此(GLubyte)255 在着色器中将显示为 255.0f。
您的代码失败,因为您需要使用 glVertexAttribIPointer()
(注意那里的 I)来设置整数属性。但就您而言,这确实是毫无意义的练习。
关于c++ - 如何在 C++ 和 GLSL 之间打包(4 字节)和解包(vec4),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28159591/