我需要轴对齐法线,所以我想安全记忆并将其作为字节而不是带位置的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}但接近于此。好吧,我不认为这段代码应该引入任何精度错误,为什么会发生这种情况呢?
更新
在从顶点着色器到片段着色器的过渡中引入了精度误差,可以通过添加flat
关键字来解决。 (感谢Chris Dodd)
答案 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的补码表示。