有符号8字节整数转归一化float方法及GLSL SNORM规则问询
8位有符号整数存储法线的解包转换方案
你要的转换逻辑不需要区分正负除数,直接除以127.0f后钳位到[-1.0, 1.0]区间即可,该逻辑完全符合GLSL SNORM纹理格式的标准解码规则。
映射规则验证
- 当输入整数为127时:
127 / 127.0f = 1.0f,完全匹配127对应+1.f的要求 - 当输入整数为-128时:
-128 / 127.0f ≈ -1.00787,经过clamp钳位到-1.0f,完全匹配-128对应-1.f的要求
该方案没有分支逻辑,在GPU中执行效率远高于分正负判断的实现,是工业界通用的SNORM解码标准。
GLSL 解码实现代码
单分量解码函数
float decodeSnorm8(int value) { return clamp(float(value) / 127.0, -1.0, 1.0); }
三维法线/切线解码示例
// 输入的packedNormal是三个int8值组成的ivec3 vec3 normal = vec3( decodeSnorm8(packedNormal.x), decodeSnorm8(packedNormal.y), decodeSnorm8(packedNormal.z) ); // 存储时如果已经做过量化优化,可省略归一化步骤 normal = normalize(normal);
CPU侧打包对应逻辑(可选参考)
如果需要在CPU侧把浮点数法线打包为int8,对应的转换逻辑为:
int8_t encodeSnorm8(float value) { // 先钳位到[-1, 1]区间 float clamped = std::clamp(value, -1.0f, 1.0f); // 乘以127后取整 int rounded = static_cast<int>(std::round(clamped * 127.0f)); // 截断到int8范围 return static_cast<int8_t>(std::clamp(rounded, -128, 127)); }
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

