在单个浮点值中编码轴对齐的单位向量

Encode axis aligned unit vector in a single float value

我想在单个浮点值中编码轴对齐的单位向量。像这样:

0: vec3(0, 0 ,0)

1: vec3(1, 0, 0)

2: vec3(0, 1, 0)

3: vec3(0, 0, 1)

根据table将float转换为vector我可以写一个简单的代码

in float axisIndex
...
vec3 axis = vec3(0.0, 0.0, 0.0);
if (axisIndex > 0.5) {
  axis = vec3(1.0, 0.0, 0.0);
}
if (axisIndex > 1.5) {
  axis = vec3(0.0, 1.0, 0.0);
}
if (axisIndex > 2.5) {
  axis = vec3(0.0, 0.0, 1.0);
}

但是如果分支很慢。是否有 快速 方法将浮点数转换为向量而不使用 if 分支和外部缓冲区,仅使用数学?

一个快速的方法是

axis = vec3(float(axisIndex == 1.0), float(axisIndex == 2.0), float(axisIndex == 3.0))

请注意,axisIndex 可以是 uint 而不是 float,在这种情况下,如果将其作为 GL_UNSIGNED_BYTE 传递,则每个顶点只需传递 1 个字节到 GPU .

如果你必须这样做,那么最好的方法是使用一个简单的数组索引:

in uint axisIndex;

const vec3[4] table = {
  vec3(0, 0 ,0), 
  vec3(1, 0, 0),
  vec3(0, 1, 0),
  vec3(0, 0, 1)
};

然后只需使用table[axisIndex] 来获取值。您可以使用 glVertexAttribIPointer 向着色器提供整数值。虽然您可以为您提供的类型使用无符号字节,但最好只使用无符号整数; OpenGL 实现不喜欢不是 4 字节对齐的顶点属性。

话虽如此,这确实是不必要的。您可以只传递 3 normalized, signed bytes 作为属性,而不是单个索引。它不会再占用您的顶点数据 space(再一次,实现不喜欢未对齐的属性),并且处理速度可能不会变慢。