【问题标题】:Why does a 'sequential' arrangement of vertex attribute data lead to crash?为什么顶点属性数据的“顺序”排列会导致崩溃?
【发布时间】:2018-03-15 15:41:37
【问题描述】:

我有一个带有着色器的 OpenGL 应用程序,可以渲染带有纹理的对象。

当我创建具有这样的“交错”属性的简单矩形时:

GLuint createRectInterleaved(float fW, float fH) {
    GLuint vao;
    GLuint rect_buffer;

    float vertex_data[] = {
        // position       normal     texture coords
        -fW/2, -fH/2, 0,  0, 0, 1,   0, 0,  
         fW/2, -fH/2, 0,  0, 0, 1,   1, 0,
         fW/2,  fH/2, 0,  0, 0, 1,   1, 1,
        -fW/2, -fH/2, 0,  0, 0, 1,   0, 0,
         fW/2,  fH/2, 0,  0, 0, 1,   1, 1,
        -fW/2,  fH/2, 0,  0, 0, 1,   0, 1};


    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(1, &rect_buffer);
    glBindBuffer(GL_ARRAY_BUFFER, rect_buffer);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_data),
                 vertex_data,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) 0);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (3*sizeof(float)));
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*) (6*sizeof(float)));
    glEnableVertexAttribArray(2);


    return vao;
}

然后应用程序工作,正方形按预期使用其纹理进行渲染。

但是如果我使用顶点属性的顺序排列:

GLuint createRectSequential(float fW, float fH) {
    GLuint vao;
    GLuint rect_buffers[3];

    float vertex_positions[18] = {
        -fW/2, -fH/2, 0,
         fW/2, -fH/2, 0,
         fW/2,  fH/2, 0,
        -fW/2, -fH/2, 0,
         fW/2,  fH/2, 0,
        -fW/2,  fH/2, 0};

    float vertex_normals[18] = {
        0, 0, 1,
        0, 0, 1,
        0, 0, 1,
        0, 0, 1,
        0, 0, 1,
        0, 0, 1};

    float vertex_tc[12] = {
        0, 0,
        1, 0,
        1, 1,
        0, 0, 
        1, 1, 
        0, 1};


    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);

    glGenBuffers(3, rect_buffers);
    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[0]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_positions),
                 vertex_positions,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[1]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_normals),
                 vertex_normals,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[2]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_tc),
                 vertex_tc,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    glEnableVertexAttribArray(2);

    return vao;
}

然后我的应用程序在调用时崩溃

  glDrawArrays(GL_TRIANGLES, 0, 6);

两个 VAO 的处理方式完全相同 - 唯一的区别是绘制之前 glBindVertexArray() 的参数:交错或顺序 VAO。

如果我注释掉纹理属性的创建,顺序VAO不会导致崩溃。

我在“顺序”版本中做错了什么?

(编辑:拼写错误)

【问题讨论】:

    标签: opengl vertex-attributes


    【解决方案1】:

    第二个代码示例中的glVertexAttribPointer 错误。它们都对属性 0 进行操作。在第一个版本中,它们将所有属性从 0 初始化到 2。由于您仍然启用这些属性但没有将数据绑定到它,因此 OpenGL 会尝试从不属于申请。

    正确的版本是:

    glGenBuffers(3, rect_buffers);
    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[0]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_positions),
                 vertex_positions,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    glEnableVertexAttribArray(0);
    
    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[1]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_normals),
                 vertex_normals,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    //                   /\ Corrected Attribute here
    glEnableVertexAttribArray(1);
    
    glBindBuffer(GL_ARRAY_BUFFER, rect_buffers[2]);
    glBufferData(GL_ARRAY_BUFFER,
                 sizeof(vertex_tc),
                 vertex_tc,
                 GL_STATIC_DRAW);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*) 0);
    //                   /\ Corrected Attribute here
    glEnableVertexAttribArray(2);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 2019-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多