我正在更改我的基本渲染器,使其成为批量渲染器以提高性能。 我已成功更改顶点数据以在一个批次中绘制所有网格,但是当我想处理多个材质时会出现问题。
显然我不能使用普通的uniforms
,因为我正在批量处理很多网格,所以我想到使用统一缓冲区对象存储所有材料数据。
问题是,如何更新此缓冲区?
如果我像这样设置我的UBO:
layout(std140) uniform MATERIAL
{
vec4 Color[20];
float Specular[20];
float Roughness[20];
float Metallic[20];
float ReflectionIntensity[20];
};
我不认为那时,当我提交单一材料的数据时,我可以使用基于材料索引计算的起始偏移并提交如下数据:
struct Material {
float color[4];
float specular;
float roughness;
float metallic;
float reflectionIntensity;
};
int bufferStride = 32; // 16 (vec4) + 4 (float) + 4 (float) + 4 (float) + 4 (float)
int offset = bufferStride * updatingMaterialIndex;
Material m;
m.color...
glBufferSubData(GL_UNIFORM_BUFFER, offset, &m, sizeof(Material));
因为我认为OpenGL在内存中会有20 vec4
后跟80 float
。
那我怎么能这样做?我是否必须单独计算每个元素的偏移量?
另外,我应该如何索引网格使用的材质?我应该将材质索引作为顶点属性传递吗?
答案 0 :(得分:0)
您的初步建议是包含数组的结构。那么为什么不反过来呢:一个包含结构的数组?
struct Material
{
vec4 Color;
float Specular;
float Roughness;
float Metallic;
float ReflectionIntensity;
}
layout(std140) uniform Materials
{
Material mtls[20];
};
然后,您将在CPU上构建一个类似的数组。
现在要执行此操作,必须确保遵循std140
的对齐规则。特别重要的是结构和阵列的对齐。由于Material
中有vec4
,因此其基本对齐为16.并且数组元素之间的步幅必须是数组元素的基本对齐的倍数。
因此,mtls[20]
的大小为32 * 20字节。即使你从Material
删除了一个浮点数,它仍然是那个大小。
如果你真的想保留数组结构方法,你只需要在CPU上使用相应的数据结构。