当前位置: 首页 > 知识库问答 >
问题:

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

戚正业
2023-03-14
    null
unsigned int vboId;
glGenBuffers(1, &vboId);
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
    null
glBindBuffer(GL_ARRAY_BUFFER, vboId);
    null
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。我想知道是否可以使用不同的模板来做这样的事情

共有1个答案

慕容劲
2023-03-14

您可以很好地制作不同的模板参数,而不必从函数参数中扣除它们。但是,不能声明所希望的类型和值参数的交替类型( )。

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

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

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

...它将分派到辅助模板,这些模板可以通过模板专门化匹配数组类型,也可以使用std::exted检索大小。

示例实现:

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重载,每个重载都在刚刚注册的属性之后返回偏移量。

在Wandbox上看现场直播

 类似资料:
  • 我目前正在使用LWJGL / OpenGL创建一个2D,自上而下的游戏,但是在绘制实体之后,在使用顶点缓冲区对象渲染实体后,在让它们四处移动的过程中,我遇到了一些问题。这是渲染线程的 run() 方法,以及设置方法: 实体从抽象超类继承这些方法来设置 VBO 并绘制实体(呈现线程中的 drawEntities 方法仅调用该方法,实体更新方法(见下文),而 setUpEntities 调用 setU

  • 我正在努力理解这两个,如何使用它们,以及它们是如何联系的。假设我想创建一个简单的地形和一个有纹理的立方体。对于这两个对象,我有三角形、顶点的数组,对于立方体,我有一个包含纹理数据的数组。我的问题是:我如何使用VAOs和VBOs来创建和呈现这两个? null

  • 我正在尝试从ArrayList读取并创建VBO,然后对其进行渲染。问题是我只是渲染了一个空白屏幕。当我立即渲染时,一切都很好;只有现在VBO的才不起作用。 游戏循环如下所示,相机调用glTranslate和glRotate函数。 渲染方法: 阵列列表具有顶点和链接的颜色。每个体素将其顶点添加到ArrayList(而不是立即渲染)。

  • 我正在努力学习LWJGL (OpenGL)不得不说我很艰难。 我试着在窗户上画一个三角形和一个四边形,最后我设法做到了。 但我还有一个问题 如果您觉得这个问题很愚蠢,请提前表示歉意,但我在网上找不到非常详细的教程,所以很难理解,因为这是我第一次使用OpenGL。 话虽如此,这是代码的相关部分: 假设程序以60 fps的速度运行。< br >这意味着渲染方法每秒钟被游戏循环调用60次。 该渲染方法的

  • 下面的lwjgl3代码设置缓冲区等,用于呈现三角形。我能看到三角形。现在我正努力弄明白到底是怎么回事。 下面是我对代码的理解。我们首先创建一个顶点缓冲区对象,它只是一个数组的容器。glBindBuffer()和glBufferData()使用顶点数组填充顶点缓冲区对象。我们再次对第二个顶点数组执行此操作。然后我们编译顶点和片段着色器,并将它们添加到着色器程序中。不知怎么的,这个程序访问第二个顶点缓

  • 我想知道什么等效的和帧缓冲区对象(FBO)。是否存在等价物,或者我需要自己实现一些东西?