OpenGL打包顶点属性

时间:2018-03-24 02:41:50

标签: opengl glsl

在OpenGL中,最好保持顶点属性分离:

layout(location = 0) in vec4 v_Position;
layout(location = 1) in vec3 v_Normal;
layout(location = 2) in vec3 v_Tanget;
layout(location = 3) in vec3 v_Bitanget;
layout(location = 4) in vec2 v_UV;

或者像这样包装它们:

layout(location = 0) in vec4 v_Position;
layout(location = 1) in vec3 v_Normal;
layout(location = 2) in vec4 v_TangetAndU;
layout(location = 3) in vec4 v_BitangetAndV;

..常用作性能优化?我的印象是,如果你受到几何体数量的限制,你可以从"打包"中获得额外的20%顶点。版。这是对的吗?

1 个答案:

答案 0 :(得分:0)

顶点提取的主要成本是读取内存的成本。数据越大,读取的时间就越长。因此,这种包装不是特别有用。最好使用normalized integers使用vertex formats正确打包数据。

对于纹理坐标,通常可以使用16位无符号归一化整数。这使得纹理坐标每个顶点占用4个字节:

glVertexAttribFormat(4, 2, GL_UNSIGNED_SHORT​, GL_TRUE, ...);

你的法线/切线/比特数应使用GL_INT_2_10_10_10_REV,它将整个法线打包成32位。 XYZ各得10位,最后2位转到你不会使用的W分量。因此,法线/切线/比特数总共将占用每个顶点12个字节:

glVertexAttribFormat(1, 4, GL_INT_2_10_10_10_REV, GL_TRUE, ...);
glVertexAttribFormat(2, 4, GL_INT_2_10_10_10_REV, GL_TRUE, ...);
glVertexAttribFormat(3, 4, GL_INT_2_10_10_10_REV, GL_TRUE, ...);

即使你将你的位置保留为3个浮点数(不需要传递第四个),每个顶点的顶点总大小为12 + 12 + 4 = 28个字节。比原始代码的任何版本都有实质性的改进。如果对位置使用16位浮点数,则每个顶点可以使用24位字节(属性应始终以4字节边界开始)。

请注意,尝试将UV打包到tangent / bitangent中时不适用于10/10/10/2格式,因为2个咬合对于纹理坐标来说是不够的。

打包这样的数据,特别是10/10/10/2格式,需要一些关注,但总的来说,从长远来看,这比使用着色器属性玩游戏要好得多。