0

我有一个带有着色器的 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 不会导致崩溃。

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

(编辑:拼写错误)

4

1 回答 1

2

第二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);
于 2018-03-15T16:10:18.073 回答