OpenGL打包顶点属性
Posted
技术标签:
【中文标题】OpenGL打包顶点属性【英文标题】:OpenGL packing vertex attributes 【发布时间】:2018-03-24 02:41:49 【问题描述】:在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】:顶点获取的主要成本将是读取内存的成本。您的数据越大,读取所需的时间就越多。因此,这种包装并不是特别有用。使用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 打包到切线/副切线中不适用于 10/10/10/2 格式,因为 2 位对于纹理坐标来说是不够的。
打包此类数据,尤其是 10/10/10/2 格式,需要小心谨慎,但总体而言,从长远来看,这将比玩具有 in-shader 属性的游戏好得多。
【讨论】:
【参考方案2】:为了添加一些真实世界的数据,我更改了以下用于绘制线条的代码:
attribute vec4 a_points;
void main()
vec2 point1 = a_points.xy;
vec2 point2 = a_points.zw;
// ...
到
attribute vec2 a_point1;
attribute vec2 a_point2;
void main()
// ...
它还提高了我在 iPad (PowerVR Series7XT Plus GPU) 上游戏的 FPS 从
因此,如果有疑问,我的建议是保持顶点属性分开。
【讨论】:
以上是关于OpenGL打包顶点属性的主要内容,如果未能解决你的问题,请参考以下文章