OpenGL包装规范

OpenGL包装规范,opengl,Opengl,我正在试图理解使用GL_INT_2_10_10_REV作为我的数据V.S.GLbyte的正常值之间的区别。目前,我正在将法线加载到glm::vec4中,并将其打包如下: int32_t floatToSignedNormalizedByte(float x, float y, float z, float w) { int32_t result = 0; const int16_t maxValue = static_cast<int16_t>(std::numeri

我正在试图理解使用
GL_INT_2_10_10_REV
作为我的数据V.S.
GLbyte
的正常值之间的区别。目前,我正在将法线加载到
glm::vec4
中,并将其打包如下:

int32_t floatToSignedNormalizedByte(float x, float y, float z, float w)
{
    int32_t result = 0;
    const int16_t maxValue = static_cast<int16_t>(std::numeric_limits<int8_t>::max());
    const int16_t negativeValueScale = maxValue + 1;

    result |= static_cast<int8_t>(x < 0 ? x * negativeValueScale : x * maxValue);
    result |= static_cast<int8_t>(y < 0 ? y * negativeValueScale : y * maxValue) << 8;
    result |= static_cast<int8_t>(z < 0 ? z * negativeValueScale : z * maxValue) << 16;
    result |= static_cast<int8_t>(w < 0 ? w * negativeValueScale : w * maxValue) << 24;

    return result;
}
我的问题是,考虑到我打包的方式,我是否应该使用
GL_INT_2_10_10_REV
作为我的类型(替换GL_字节)?我理解使用
GL_INT_2_10_10_10_REV
意味着每个组件获得10位而不是8位,这很好,因为实际上我只需要xyz组件。哪一个更好,为什么?如果我使用
GL_INT_2_10_10_10_REV
,我猜组件计数仍然是4?

为什么 正如您所说,使用10_10_10_2将为每个有意义的分量(xyz)提供10位,同时为w分量保留2位,而w分量对法向量没有用处。对于10位,您有x、y和z的
2^10
可能的离散值,而不是8位提供的
2^8
值。因此,这将为法线和更平滑的渐变提供更精确的值。您也可以使用浮点值,但这些值需要更多内存,而且速度可能较慢。这回答了“我为什么要这样做”部分

怎么 至于“how”,您当前的packing函数将每个
float
转换为8位整数。您需要对此进行更改,以将x、y和z分量转换为10位整数,并将这些位与
01
一起打包为最后2位(w分量)。
REV
版本只允许您以相反的顺序(wzyx)指定组件

有关
GL_INT_2_10_10_10_REV
顶点格式的更多信息 OpenGL规范的表10.3和表10.4描述了这些组件如何在32位字中布局:

31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             z               |              y              |         x         |

Table 10.3: Packed component layout for non-BGRA formats. Bit numbers are indicated for each component.

UNSIGNED_INT_2_10_10_10_REV:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             x               |              y              |         z         |

Table 10.4: Packed component layout for BGRA format. Bit numbers are indicated for each component.
如您所见,此顶点格式中有4个组件

如果您想了解更多背景信息,还可能会找到有趣的阅读说明:

两种新的顶点属性数据格式:有符号的2.10.10.10和无符号的2.10.10.10顶点数据格式。这些顶点数据格式描述了一个4分量流,可用于以量化形式存储法线或其他属性。法线、切线、副法线和其他顶点属性通常可以以较低的精度指定,而不会引入明显的瑕疵,从而减少它们所消耗的内存量和内存带宽

“降低精度”指的是使用10位整数,而不是法线的半浮点数(16位)或浮点数(32位)。每个顶点具有更少的位可以提供更好的性能,因为顶点组装阶段需要更少的内存带宽


这个问题还有相关信息:

@Nicolas,法线不应该签名吗?阅读规范,对于有符号规范化整数,我可以选择8位的范围[-128127],或者[-127127]。有人说第一个更适合顶点,而第二个更适合纹理。我知道第二个可以精确地表示0,而第一个不能。我认为这不是一个大问题。我做错了什么?请帮帮我:)好的,我只是在自言自语:(我删除了旧评论,因为它是错误的。但是,我发现了另一个潜在的问题:。但除此之外,我不确定你的问题到底是什么。你是在问如何使用2_10_10_10作为一种格式,还是你应该还是什么?@NicolBolas,我是在问如何使用2_10_10_10,如果我应该将其用于正常值,以及如何正确打包。)我发现如果没有
REV
标志,很难知道包装的顺序。对于我包装的方式,顺序应该是什么?
REV
清楚地表明xyzw应该包装为->wzyx,从高位到低位(从左到右).所以类型应该是GL_INT_2_10_10_10_REV,组件计数仍然是4?如果我想继续使用
2^8
packing怎么办?它们的顺序应该相同,w是最高位,x是最低位吗?
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             z               |              y              |         x         |

Table 10.3: Packed component layout for non-BGRA formats. Bit numbers are indicated for each component.

UNSIGNED_INT_2_10_10_10_REV:
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|  w |             x               |              y              |         z         |

Table 10.4: Packed component layout for BGRA format. Bit numbers are indicated for each component.