如何将字节解压缩到vec3?

时间:2015-02-08 23:07:34

标签: opengl glsl

我需要轴对齐法线,所以我想安全记忆并将其作为字节而不是带位置的alpha通道发送。缓冲区对象由4个字节组成:glVertexAttribPointer(0, 4, GL_UNSIGNED_BYTE, GL_FALSE, 4 * sizeof(GLubyte), (void*)0);编码应如下所示。

//byte in buffer object | unpacked vector
x+ 0010 1011 == vec3( 1,  0,  0)
x- 0010 1001 == vec3(-1,  0,  0)
y+ 0010 1110
y- 0010 0110
z+ 0011 1010
z- 0001 1010

//Lets take vec3(-1, 0, 1) encoded velue looks like 0011 1001
//               ,(operation) -> (result),
//Z = >>4 -> 0000 0011, &mask -> 0000 0011, -2 -> 0000 0001
//Y = >>2 -> 0000 1110, &mask -> 0000 0010, -2 -> 0000 0000
//X = >>0 -> 0011 1001, &mask -> 0000 0001, -2 -> 1111 1111

我在gDEBuggerGL中检查了编码,这是正确的。问题出现在顶点着色器中,因为解包非常笨拙。

layout(location = 0) in vec4 vertex_position;
//...
int byte = int(vertex_position.w);

const int mask = 0x00000003; 
vec3 v_normal;
v_normal.x = float(((byte >> 0) & mask) - 2);
v_normal.y = float(((byte >> 2) & mask) - 2);
v_normal.z = float(((byte >> 4) & mask) - 2);

首先:有更好的方法来实现这个目标吗?

其次:我将这个法线向量渲染成浮点纹理,发现有些值是错误的。其中许多不是{1,0,-1}但接近于此。好吧,我不认为这段代码应该引入任何精度错误,为什么会发生这种情况呢?

Normals in float texture

更新 在从顶点着色器到片段着色器的过渡中引入了精度误差,可以通过添加flat关键字来解决。 (感谢Chris Dodd)

1 个答案:

答案 0 :(得分:0)

//Lets take vec3(-1, 0, 1) encoded velue looks like 0011 1001    
//X = >> 0 -> 0011 1001, &mask -> 0000 0001, -2 -> ffff ffff

0xFFFFFF不是-1,因为您使用的是GL_UNSIGNED_BYTE,因此这不是2的补码表示。