在我的宠物项目中,视频内存开始成为一个问题,因此,我研究了各种技术以最大程度地减少内存占用。我尝试使用GL_INT_2_10_10_10_REV
,但是我使用打包方法得到了照明伪像。这些工件似乎不是错误的结果,因为使用规范化的char[3]
或short[3]
可以完美地工作。由于其他方面无用的填充,我宁愿使用空间效率更高的GL_INT_2_10_10_10_REV
。
这是包装代码:
union Vec3IntPacked {
int i32;
struct {
int a:2;
int z:10;
int y:10;
int x:10;
} i32f3;
};
int vec3_to_i32f3(const Vec3* v) {
Vec3IntPacked packed;
packed.i32f3.x = to_int(clamp(v->x, -1.0f, 1.0f) * 511);
packed.i32f3.y = to_int(clamp(v->y, -1.0f, 1.0f) * 511);
packed.i32f3.z = to_int(clamp(v->z, -1.0f, 1.0f) * 511);
return packed.i32;
} // NOTE: to_int is a static_cast
如果我正确地读取了spec(第10.3.8节“打包的顶点数据格式”以及2.1和2.2中的转换规则),则应该可以,但是不能。
我还要注意,以上代码已在多个操作系统(虽然全为64位,但
int
仍应为32位)和图形卡供应商上进行过测试,以检查是否与驱动程序有关。此外,使用了OpenGL 3.3核心配置文件。
顶点结构如下所示:
struct BasicVertex {
float position[3];
unsigned short uv[2];
int normal;
int tangent;
int bitangent;
} // resulting in a 4-byte aligned 28 byte structure
希望我提供了足够的信息,并且有人可以阐明如何将法线正确打包到
GL_INT_2_10_10_10_REV
中。
最佳答案
您的位域声明中的顺序看起来不正确。根据规范文档(3.3规范的第32页的“2.8.2压缩的顶点数据格式”部分),每个组件的位范围是:
x: bits 0-9
y: bits 10-19
z: bits 20-29
w: bits 30-31
经过一些搜索后,看起来好像位域中的位顺序不是由C标准定义的。参见例如Which end of a bit field is the most significant bit?
我见过的编译器通常使用最低到最高位的顺序。例如,Microsoft为他们的编译器定义了这一点:
Bit fields are allocated within an integer from least-significant to most-significant bit.
如果您依赖于按此顺序使用编译器,则声明应如下所示:
union Vec3IntPacked {
int i32;
struct {
int x:10;
int y:10;
int z:10;
int w:2;
} i32f3;
};
为了保证完全的可移植性,您将使用移位运算符来构建值,而根本不使用位域。
根据您在顶点着色器中声明和使用属性的方式,您可能还需要确保将
w
组件设置为1。当然,如果不在顶点着色器中使用w
组件,则不会必要的。
关于opengl - 如何将法线打包到GL_INT_2_10_10_10_REV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35961057/