在我的宠物项目视频内存开始成为一个问题,因此,我看了各种技术,以尽量减少内存占用。我试着使用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如果我正确地阅读了等级库 (第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中。
发布于 2016-03-12 18:19:04
位字段声明中的顺序看起来不正确。基于规范文档( 3.3规范第32页中的"2.8.2打包顶点数据格式“部分),每个组件的位范围是:
x: bits 0-9
y: bits 10-19
z: bits 20-29
w: bits 30-31经过一些搜索后,它看起来像位字段中的位顺序不是由C标准定义的。参见例如位字段的哪一端是最重要的位?
我看到的编译器通常使用最低到最高的位序。例如,Microsoft为它们的编译器定义了以下内容:
位字段在整数内分配,从最小有效位到最重要位.
如果您依赖于使用带有此顺序的编译器,则声明应该如下所示:
union Vec3IntPacked {
int i32;
struct {
int x:10;
int y:10;
int z:10;
int w:2;
} i32f3;
};为了保证完全可移植性,您可以使用shift运算符来构建值,而根本不使用位字段。
根据您在顶点着色器中声明和使用属性的方式,您还可能希望确保将w组件设置为1。当然,如果在顶点着色器中不使用w组件,这是不必要的。
发布于 2018-11-26 09:35:09
我只是把这个放在这里,因为我很难让它起作用,而且在StackOverflow上也没有全面的答案。Reto关于字节/位排序( OpenGL维基也显示了布局)和使用移位是正确的,但是您仍然需要正确地到达.示例代码(以及其他问题在StackOverflow上)似乎与依赖未定义的行为有关,但对我来说却不起作用。为我工作的( OpenGL <= 4.1)是
inline uint32_t Pack_INT_2_10_10_10_REV(float x, float y, float z, float w)
{
const uint32_t xs = x < 0;
const uint32_t ys = y < 0;
const uint32_t zs = z < 0;
const uint32_t ws = w < 0;
uint32_t vi =
ws << 31 | ((uint32_t)(w + (ws << 1)) & 1) << 30 |
zs << 29 | ((uint32_t)(z * 511 + (zs << 9)) & 511) << 20 |
ys << 19 | ((uint32_t)(y * 511 + (ys << 9)) & 511) << 10 |
xs << 9 | ((uint32_t)(x * 511 + (xs << 9)) & 511);
return vi;
}我找到了这里。对于法线,只需省略"w“部分。如果你有一个更快/更简单的方法,我很想知道。要设置属性指针,请确保使用
glVertexAttribPointer(1, 4, GL_INT_2_10_10_10_REV, GL_TRUE, stride, dataPointer);你的正常数据以vec4的形式到达你的着色器,映射为-1,1。如果你不需要w组件,你也可以方便地使用vec3,OpenGL只会给你xyz,所以你可能根本不需要改变任何着色代码。有些答案说你必须使用"glVertexAttribIPointer",但这是错误的。
请注意,从4.2到OpenGL 4.2的映射是从浮点到打包格式变了的映射,因此转换是不同的,但更容易。这是顶点格式,也是OpenGL es3.0支持及以上。
https://stackoverflow.com/questions/35961057
复制相似问题