类的顶点数组问题

Posted

技术标签:

【中文标题】类的顶点数组问题【英文标题】:Vertex array issue with classes 【发布时间】:2017-12-10 16:45:57 【问题描述】:

我正在 youtube 上的 Chernov @ sparky 引擎教程中学习 openGL 编程。目前我有一个顶点和一个片段着色器,其中包含窗口、着色器等管理所需的类。我可以使用单个顶点数组对象在屏幕上绘制,但是当通过创建 vertexArray 类完成相同操作时,它会失败。 顶点数组类:

#include"vertexArray.h"
 namespace graphics
VertexArray::VertexArray()
    glGenVertexArrays(1,&arrayID);


void VertexArray::addBuffer(Buffer* buffer, GLint index)
    bind();

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayID);
    glEnableVertexAttribArray(index);
    glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);



void VertexArray::bind() const
    glBindVertexArray(arrayID);

void VertexArray::unbind() const
    glBindVertexArray(0);

VertexArray::~VertexArray()


我的 main.cpp 文件

    #include"graphics\window.h"
    #include"utils\reader.h"
    #include"graphics\shader.h"
    #include"math\vec.h"
    #include"math\mat4.h"
    #include"graphics\buffers\buffer.h"
    #include"graphics\buffers\indexbuffer.h"
    #include"graphics\buffers\vertexArray.h"
    using namespace graphics;
    using namespace utils;
    using namespace math;
    int main()
        Window window;
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glClearColor(0, 0, 0, 1);
        Reader read1("src/shaders/test.vert");
        Reader read2("src/shaders/test.frag");
        char * r1 = read1.getData();
        char * r2 = read2.getData();

        GLfloat vert[] = 
            0, 0, 0, 
            0, 3, 0, 
            8, 0, 0, 
            8, 3, 0, 
        ;
        Buffer* vbo = new Buffer(vert,4*3,3);

        GLushort indices[] =  
            0,1,2, 
            1,3,2
        ;
        indexBuffer ibo(indices,6);

        Shader shader(r1, r2);
        shader.enable();
    #if 0
        GLuint sprite1;
        glGenVertexArrays(1, &sprite1);
        glBindVertexArray(sprite1);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sprite1);
        vbo->bind();
        glVertexAttribPointer(0, vbo->getComCount(), GL_FLOAT, 0, 0, 0);
        shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
        shader.setUniformMat4("ml_matrix", mat4::translation(vec3(0, 0, 0)));
        shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
        shader.setUniform4f("colour", vec4(0.2, 0.0, 0.4, 1));
        glEnableVertexAttribArray(0);
        glBindVertexArray(0);

        GLuint sprite2;
        glGenVertexArrays(1, &sprite2);
        glBindVertexArray(sprite2);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sprite2);
        vbo->bind();
        glVertexAttribPointer(5, vbo->getComCount(), GL_FLOAT, 0, 0, 0);
        shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
        shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));
        shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
        shader.setUniform4f("colour", vec4(0.3, 0.0, 0.2, 1));
        glEnableVertexAttribArray(0);
        glBindVertexArray(0);
    #endif
        VertexArray vao;
        vao.addBuffer(vbo, 0);

        while (!window.closed())

    #if 0 
            window.clear();

            glDrawArrays(GL_TRIANGLES, 0,6);
    #endif
            double x, y;
            x = window.getX();
            y = window.getY();

            vao.bind();
            ibo.bind();
            shader.setUniform2f("light_pos", vec2((float) (x*16.0f/960.0f)  , (float) (9- 9*y/540.0f)));

            glDrawElements(GL_TRIANGLES, ibo.getCount(), GL_UNSIGNED_SHORT, 0);
            window.update();

            vao.unbind();
            ibo.unbind();
        
        return 0;
    

请注意,如果我只是在 main 中为 GLuint 变量创建一个顶点数组并使用它,那么一切都有效。 我似乎无法在这里找到问题。 任何帮助都非常感谢..

【问题讨论】:

@Rabbid76 哦,我的上帝!非常感谢你......我整天都在敲我的头而不知道这一点。当它起作用时,我几乎高兴得哭了!!非常感谢你 【参考方案1】:

您必须将数据绑定到缓冲区(请参阅glBufferData)。

顶点属性缓冲区可以这样创建:

 GLfloat vert[] = 
    0, 0, 0, 
    0, 3, 0, 
    8, 0, 0, 
    8, 3, 0, 
;

GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*4, vert, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

元素缓冲区可以这样创建:

GLushort indices[] =  
    0,1,2, 
    1,3,2
;

GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*3*2, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

Vertex Array Object 和顶点属性指针是这样指定的:

GLuint attr_index = 0; // attribute index according to the shader program

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

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(attr_index , 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(attr_index );

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glBindVertexArray( 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

注意,Vertex Array Object 存储了您指定的有关顶点属性(格式、大小、属性索引...)的所有信息,它引用元素数组缓冲区。

最后,您可以像这样绘制网格:

glBindVertexArray( vao );
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glBindVertexArray( 0 );

【讨论】:

@Rabbid76: "你必须为缓冲区使用正确的目标。" 请不要宣传buffer objects是类型的观点.他们不是。缓冲区对象的用途是有类型的,但缓冲区对象不直接与类型相关联。在为它们创建存储时,没有什么能阻止您使用 GL_COPY_READ_BUFFER @Rabbid76:这是您暗示您打算稍后用于顶点数组的缓冲区对象必须通过绑定分配其存储的部分发给GL_ARRAY_BUFFER。其余的答案都很好。

以上是关于类的顶点数组问题的主要内容,如果未能解决你的问题,请参考以下文章

Opengl 顶点数组对象

OpenGL:顶点数组与 glBegin()

为啥顶点数组对象会导致错误?

顶点数组对象是上下文的一部分吗?

在两个不同的顶点数组对象中使用顶点缓冲区

我的OpenGL学习进阶之旅顶点属性顶点数组