在我的宠物项目中,视频内存开始成为一个问题,因此我研究了各种技术来减少内存占用.我尝试过使用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
Run Code Online (Sandbox Code Playgroud)
如果我正确地阅读规范(第10.3.8节"打包顶点数据格式"和2.1和2.2中的转换规则),这应该可行,但事实并非如此.
我还应该注意,上面的代码是在多个操作系统上测试的(尽管int仍然是64位,但仍然应该是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
Run Code Online (Sandbox Code Playgroud)
希望我提供了足够的信息,有人可以阐明如何正常包装法线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
Run Code Online (Sandbox Code Playgroud)
经过一些搜索后,看起来比特字段中的位顺序不是由C标准定义的.例如,参见位字段的哪一端是最重要的位?
我见过的编译器通常使用从最低到最高的位顺序.例如,Microsoft为其编译器定义了这个:
位字段在从最低有效位到最高有效位的整数内分配.
如果您依赖于使用此订单的编译器,您的声明应如下所示:
union Vec3IntPacked {
int i32;
struct {
int x:10;
int y:10;
int z:10;
int w:2;
} i32f3;
};
Run Code Online (Sandbox Code Playgroud)
为保证完全可移植性,您可以使用移位运算符来构建值,而不是使用位域.
根据您在顶点着色器中声明和使用属性的方式,您可能还需要确保将w组件设置为1.当然,如果不在w顶点着色器中使用该组件,则不需要.