c++ - 如何在 C++ 和 GLSL 之间打包(4 字节)和解包(vec4)

标签 c++ opengl glsl

我想节省内存,因为输入数据在 [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);

结果应该提供提示,但它太乱了。 result

编辑:

即使我的解决方案毫无意义,也有两个错误。首先如下所述,我必须使用 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/

相关文章:

c++ - GLSL - 何时何地调用顶点和片段?

c++ - Visual Studio 2013 专业版 - "An item with the same key has already been added."

c++ - 对一组数字进行排序最快的数据结构(和排序算法)是什么?

c++ - XCode 项目无法识别某些 GLUT 命令

c++ - 在 OpenGL 中将纹理映射到球体时出现接缝问题

c++ - 制作shader将vertexArray作为canvas而不是window

C++ QuickSort 枢轴优化

c++ - 为什么 VS 2008 编译时没有带有错误模板逻辑的警告?

python - Azure是否允许应用程序需要OpenGL,有什么办法可以解决吗?

OpenGL,为什么这段代码不能按我的预期工作?