c++ - OpenGL——多个 glDrawArrays() 调用只显示第一次的结果?

标签 c++ c windows opengl

所以我遍历了几个网格,每个网格都存储在自己的 GL_ARRAY_BUFFER 中,但它们共享相同的 glVertexAttribPointer 结构。我在 for 循环中遍历每个渲染/绘制过程:

if (sConfig.mRendering.isRenderTypeActive(RENDER_TYPE_SINGLE_MESH) || 
    sConfig.mRendering.isRenderTypeActive(RENDER_TYPE_TWO_MESH)) {
    const int mesh_count = sConfig.mRendering.isRenderTypeActive(RENDER_TYPE_TWO_MESH) ? 2 : 1;
    for (int i = 0; i < mesh_count; i++) {
        std::lock_guard<std::mutex> lock(mModelDataMutex[i]);
        mUniV_VertexTransform->setValue(mModelTransform[i]);
        glBindBuffer(GL_ARRAY_BUFFER, mVBOs[i]); CHECK_GL_ERR;
        glDrawArrays(GL_TRIANGLES, 0, (GLsizei)mVertexCount[i]); CHECK_GL_ERR;
    }
}

并使用对以下函数的几次调用为每个 VBO 设置数据:

bool ::updateModelData(const RenderCloud& data, VERTEX_BUFFER_ID id /*= VBID_MESH_0*/)
{
    if (id < VBID_COUNT)
    {
        std::lock_guard<std::mutex> lock(mModelDataMutex[id]);
        // Bind Point VBO
        glBindBuffer(GL_ARRAY_BUFFER, mVBOs[id]); CHECK_GL_ERR_RET;
        // Set coordinate attribute
        glVertexAttribPointer(BTID_COORDS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)BT_COORDS_OFFSET); CHECK_GL_ERR_RET;
        glEnableVertexAttribArray(BTID_COORDS); CHECK_GL_ERR_RET;

        // Set the normals attribute
        glVertexAttribPointer(BTID_NORMALS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)(BT_NORMALS_OFFSET)); CHECK_GL_ERR_RET;
        glEnableVertexAttribArray(BTID_NORMALS); CHECK_GL_ERR_RET;

        // Set the colors attribute
        glVertexAttribPointer(BTID_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, RenderCloud::elemSize(), (GLvoid*)(BT_COLOR_OFFSET)); CHECK_GL_ERR_RET;
        glEnableVertexAttribArray(BTID_COLOR); CHECK_GL_ERR_RET;
        // Copy Data
        glBufferData(GL_ARRAY_BUFFER, data.pts.size() * data.elemSize(), data.pts.data(), GL_STATIC_DRAW); CHECK_GL_ERR_RET;
        mVertexCount[id] = data.pts.size();
        // Unbind buffer
        glBindBuffer(GL_ARRAY_BUFFER, 0); CHECK_GL_ERR_RET;
        return true;
    }
    return false;
}

我可以验证两个 VBO 的数据是否存在,但只有 for 循环中的第一个 VBO 使用 glDrawArrays() 呈现

它们共享 shame 几何着色器,然后由延迟渲染堆栈使用它来应用效果。

是否每个 glDrawArrays() 调用都需要自己的几何着色器实例,只要它们都共享相同的绘制缓冲区?

最佳答案

定义通用顶点属性数据数组的不是绑定(bind)的顶点缓冲区对象,而是存储在默认顶点数组对象中的状态。

当您调用 glVertexAttribPointer 时定义了通用顶点属性数据的数组。如果此时绑定(bind)了数组缓冲区,则数组定义引用缓冲区对象。

这意味着您必须在绘制对象之前切换数组定义:

glBindBuffer(GL_ARRAY_BUFFER, mVBOs[id]);

glVertexAttribPointer(BTID_COORDS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)BT_COORDS_OFFSET);
glEnableVertexAttribArray(BTID_COORDS);

glVertexAttribPointer(BTID_NORMALS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)(BT_NORMALS_OFFSET));
glEnableVertexAttribArray(BTID_NORMALS);

glVertexAttribPointer(BTID_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, RenderCloud::elemSize(), (GLvoid*)(BT_COLOR_OFFSET));
glEnableVertexAttribArray(BTID_COLOR);

glDrawArrays(GL_TRIANGLES, 0, (GLsizei)mVertexCount[i]);
glBindBuffer(GL_ARRAY_BUFFER, 0);

但我建议使用 Vertex Array Object .顶点数组对象存储通用顶点数组定义的状态:

GLuint vao[VBID_COUNT];

....

glGenVertexArrays( 1, vao[i] );
glBindVertexArray( vao[i] );

glBindBuffer(GL_ARRAY_BUFFER, mVBOs[id]);

glVertexAttribPointer(BTID_COORDS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)BT_COORDS_OFFSET);
glEnableVertexAttribArray(BTID_COORDS);

glVertexAttribPointer(BTID_NORMALS, 3, GL_FLOAT, GL_FALSE, RenderCloud::elemSize(), (GLvoid*)(BT_NORMALS_OFFSET));
glEnableVertexAttribArray(BTID_NORMALS);

glVertexAttribPointer(BTID_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, RenderCloud::elemSize(), (GLvoid*)(BT_COLOR_OFFSET));
glEnableVertexAttribArray(BTID_COLOR);

glBufferData(GL_ARRAY_BUFFER, data.pts.size() * data.elemSize(), data.pts.data(), GL_STATIC_DRAW);
mVertexCount[id] = data.pts.size();

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray( 0 );

glBindVertexArray( vao[i] );
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)mVertexCount[i]); 
glBindVertexArray( 0 );

关于c++ - OpenGL——多个 glDrawArrays() 调用只显示第一次的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49947957/

相关文章:

c++ - 重载 << 运算符以打印出 std::list

c++ - NSIS 插件在 MSVS 2003/2005 中内置时加载退出

C:如何将任意数组放入可用内存中? (基本的)

在C中创建指针

c++ - TerminateThread 在线程有无限循环时锁定

c++ - 在哪里可以下载 c 的标准数学库的静态库/头文件?

c - 如何在不交换顺序的情况下将多位数字分成单独的数字

c# - 创建一个 Windows 钩子(Hook)来检测菜单点击

java - 32位Win7、32位JDK和32位MS Access导致java.sql.SQLException : No suitable driver found

c++ - 为什么 RangeSlider 在 QtQuick 中可用而不是标准 Widget