可变参数模板和顶点缓冲区属性

问题描述 投票:0回答:1

在OpenGL中,创建VBO时,必须完成所有这三件事:

  • 创建缓冲区
unsigned int vboId;
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
  • 确保缓冲区已绑定
glBindBuffer(GL_ARRAY_BUFFER, vboId);
  • 启用并定义属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

在原始OpenGL中执行此操作虽然简单,但是如果要为单个缓冲区设置许多属性,则可能会失控。我当时以为我可以简化使用带有API的可变参数模板调用属性函数的过程:

// 3 float position, 2 float uv texture coord.
float data[] {
    0.f, 0.f, 0.f,   0.f, 0.f,
    0.f, 1.f, 0.f,   0.f, 1.f,
    1.f, 0.f, 0.f,   1.f, 0.f,
    1.f, 1.f, 0.f,   1.f, 1.f,
};
auto vboId = createVbo(data, sizeof(data));
bindVbo(vboId);
setVboLayout<float, 3, float, 2>(vboId);

但是,这是不可行的,因为模板参数(AFAIK)实际上不能可变,而只能使可变参数。我不想使用函数参数的原因是因为我希望能够输入不能用作参数的C ++关键字floatint。我当前的解决方案是使用带有枚举的参数,该枚举可以复制基本类型,例如Float32Int32。我想知道是否可以使用可变参数模板执行类似的操作]

c++ templates opengl variadic-templates vbo
1个回答
0
投票

您可以很好地制作可变参数模板参数,而无需从函数参数中扣除它们。但是,您无法声明想要的交替类型和值参数的种类(<float, 3, float, 2>)。

解决方案是使用复合类型来存储这两个信息,而IMO则非常适合使用数组类型。因此,您可以声明并调用为:

template <class... Attributes>
void setVboLayout(VboId vboId);

setVboLayout<float[3], float[2]>(vboId);

...将分派给可以通过模板专门化匹配数组类型,或使用std::extent检索大小的辅助模板。

示例实现:

namespace detail {
    template <class Attribute>
    struct attributeTag { };

    std::size_t bindAttribute(VboId, attributeTag<float>, std::size_t offset) {
        // glVertexAttribPointer for a float
        return offset + sizeof(float);
    }

    template <std::size_t ArraySize>
    std::size_t bindAttribute(VboId, attributeTag<float[ArraySize]>, std::size_t offset) {
        // glVertexAttribPointer for a float array
        return offset + sizeof(float[ArraySize]);
    }

    // More overloads for variouts attribute types...
}

template <class... Attributes>
void setVboLayout(VboId vboId) {
    std::size_t offset = 0;
    ((offset = detail::bindAttribute(vboId, detail::attributeTag<Attributes>{}, offset)), ...);
}

这里bindAttribute重载每个都在刚注册的属性之后立即返回偏移量。

See it live on Wandbox

© www.soinside.com 2019 - 2024. All rights reserved.