使用统一缓冲区对象进行批量渲染

时间:2016-05-24 12:18:05

标签: c++ opengl

我正在更改我的基本渲染器,使其成为批量渲染器以提高性能。 我已成功更改顶点数据以在一个批次中绘制所有网格,但是当我想处理多个材质时会出现问题。

显然我不能使用普通的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

那我怎么能这样做?我是否必须单独计算每个元素的偏移量?

另外,我应该如何索引网格使用的材质?我应该将材质索引作为顶点属性传递吗?

1 个答案:

答案 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上使用相应的数据结构。