在OpenGL中传递大型/更改/复杂顶点集?

时间:2014-03-03 18:17:08

标签: qt opengl

我有一个非常基本的场景渲染,有一个顶点和颜色数组(下面的代码)。我看到如何将顶点和颜色绑定到顶点着色器属性。目前,此顶点和颜色信息位于我的渲染函数中的局部数组变量中,如下所示,然后调用glDrawArrays(GL_TRIANGLES, 0, n)为每个帧绘制它们。

我正在尝试描绘一个更大的移动场景的架构,其中有许多模型需要加载和卸载许多顶点。

我想要扩展它的天真方式是将所有顶点/颜色数据放在主存储器中的一个大数组中,然后为每个帧调用一次glDrawArrays。这似乎对我来说效率低下。在每一帧上,顶点和颜色信息仅在部分中变化,因此为每个帧排列和重新加载整个单片顶点数组似乎是错误的。

3D游戏等对此有何影响?它们是否为每个帧将所有顶点放在主内存中的一个大数组中,然后调用glDrawArrays一次?如果没有,他们通常使用什么架构和OpenGL调用来将场景的所有顶点传递给GPU?是否可以将顶点加载到GPU内存中,然后将它们重用于几个帧?是否可以从主存储器中的多个位置绘制多个顶点数组?

static const char *vertexShaderSource =
R"(

    attribute highp vec4 posAttr;
    attribute lowp vec4 colAttr;
    varying lowp vec4 col;
    uniform highp mat4 matrix;

    void main()
    {
       col = colAttr;
       gl_Position = matrix * posAttr;
    }

)";

static const char *fragmentShaderSource =
R"(

    varying lowp vec4 col;

    void main()
    {
       gl_FragColor = col;
    }

)";

void Window::render()
{
    glViewport(0, 0, width(), height());

    glClear(GL_COLOR_BUFFER_BIT);

    m_program->bind();

    constexpr float delta = 0.001;
    if (forward)
        eyepos += QVector3D{0,0,+delta};
    if (backward)
        eyepos += QVector3D{0,0,-delta};
    if (left)
        eyepos += QVector3D{-delta,0,0};
    if (right)
        eyepos += QVector3D{delta,0,0};

    QMatrix4x4 matrix;
    matrix.perspective(60, 4.0/3.0, 0.1, 10000.0);
    matrix.lookAt(eyepos, eyepos+direction, {0, 1, 0});
    matrix.rotate(timer.elapsed() / 100.0f, 0, 1, 0);

    m_program->setUniformValue("matrix", matrix);

    QVector3D vertices[] =
    {
        {0.0f, 0.0f, 0.0f},
        {1.0f, 0.0f, 0.0f},
        {1.0f, 1.0f, 0.0f},
    };

    QVector3D colors[] =
    {
        {1.0f, 0.0f, 0.0f},
        {1.0f, 1.0f, 0.0f},
        {1.0f, 0.0f, 1.0f},
    };

    m_program->setAttributeArray("posAttr", vertices);
    m_program->setAttributeArray("colAttr", colors);

    m_program->enableAttributeArray("posAttr");
    m_program->enableAttributeArray("colAttr");

    glDrawArrays(GL_TRIANGLES, 0, 3);

    m_program->disableAttributeArray("posAttr");
    m_program->disableAttributeArray("colAttr");

    m_program->release();

    ++m_frame;
}

1 个答案:

答案 0 :(得分:0)

取决于你想要如何构建事物。

如果您有一个需要移动和旋转并转换但不改变其形状的详细模型,那么一个非常明确的方法是将该模型加载到例如一个VBO(我不确定你的setAttributeArray做了什么),这只能在第一帧之前发生,后续的帧可以通过简单地设置模型视图矩阵统一来渲染你想要的任何变换的模型通过总线传输的数据量要小得多。

顶点着色器可以而且应该用于让GPU完全帮助或卸载这些类型的操作的计算和/或应用。