调用glDrawArrays

时间:2019-01-04 04:43:51

标签: c++ opengl sprite

我正在尝试编写一个精灵批处理程序。 最初,我将以下数据上传到openGL,以查看是否可以在屏幕上看到任何内容:

static GLfloat const vertexData[] = {
        //Position                  //Color                 //UV Coords
        0.5f, 0.5f,             1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 1.0f,
        -0.5f, 0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 1.0f,
        0.5f, -0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 0.0f,

        -0.5f, -0.5f,           1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 0.0f,
        -0.5f, 0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     0.0f, 1.0f,
        0.5f, -0.5f,            1.0f, 1.0f, 1.0f, 1.0f,     1.0f, 0.0f
};

这些是我的顶点和片段着色器:

const char* vert = "#version 330 core\n"
                   "layout (location = 0) in vec2 vPos;\n"
                   "layout (location = 1) in vec4 vColor;\n"
                   "layout (location = 2) in vec2 vTexPos;\n"
                   "\n"
                   "out vec4 fColor;\n"
                   "out vec2 fTexPos;\n"
                   "\n"
                   "void main() {\n"
                   "    gl_Position = vec4(vPos.xy, 0.0, 1.0);\n"
                   "    fColor = vColor;\n"
                   "    fTexPos = vec2(vTexPos.s, 1.0 - vTexPos.t);\n"
                   "}";




const char* frag = "#version 330 core\n"
                   "in vec4 fColor;\n"
                   "in vec2 fTexPos;\n"
                   "out vec4 finalColor;\n"
                   "\n"
                   "uniform sampler2D textureUniform;\n"
                   "\n"
                   "void main() {\n"
                   "  vec4 textureColor = texture(textureUniform, fTexPos);"
                   "  finalColor = fColor * textureColor;\n"
                   "}";

我像这样设置VAO和VBO:

auto vaoID_ = 0;
auto vboID_ = 0;
glGenVertexArrays(1, &vaoID_);
glGenBuffers(1, &vboID_);

glBindVertexArray(vaoID_);
glBindBuffer(GL_ARRAY_BUFFER, vboID_);

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV

最后,在每个循环中,我都将孤立缓冲区,然后将数据放入其中。

glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexData), vertexData);
glDrawArrays(GL_TRIANGLES, 0, 6);

这很好! 因此,我尝试开始编写基本的Sprite批处理。 我将顶点数据分组为POD结构:

   struct VertexData {
        struct {
            GLfloat screenx;
            GLfloat screeny;
        } position;

        struct {
            GLfloat r;
            GLfloat g;
            GLfloat b;
            GLfloat a;
        } color;

        struct {
            GLfloat texu;
            GLfloat texv;
        } uv;
    }

并使用向量将所有内容一起批处理: std::vector<VertexData> spritebatch_

我更改了对glVertexAttribPointer的调用以匹配此结构(尽管我认为不需要进行此更改?)

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV

要对其进行测试,在每个循环中,我都会向其提供与静态GLfloat数组中相同的数据:

spritebatch_.push_back({0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,   1.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});
spritebatch_.push_back({-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f});
spritebatch_.push_back({-0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f});
spritebatch_.push_back({0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f});

然后尝试孤立缓冲区并将数据放入其中:

glBufferData(GL_VERTEX_ARRAY, spritebatch_.size() * sizeof(VertexData), nullptr, GL_DYNAMIC_DRAW);
glBufferSubData(GL_VERTEX_ARRAY, 0, spritebatch_.size() * sizeof(VertexData), spritebatch_.data());
glDrawArrays(GL_TRIANGLES, 0, spritebatch_.size());

最后,我将重置spritebatch_:spritebatch_.clear();

但是,此段错误。去孤立缓冲区并将数据放入其中时,我做错什么了吗?数据格式仍然匹配(VertexData个POD成员均为GLfloat个),spritebatch_的大小仍为6(6个顶点组成一个正方形),并且该数据的位置在每个顶点内仍然相同。

1 个答案:

答案 0 :(得分:1)

glVertexAttribPointer的第五个参数是“步幅”,即连续通用顶点属性之间的字节偏移

因此更改为

 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 8, (void*)0); // Screen Position
 glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8, (void*)(2 *sizeof(GL_FLOAT)); //Color
 glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8, (void*)(6 * sizeof(GL_FLOAT)); //UV

glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, position)); // Screen Position
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, color)); //Color
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (void*)offsetof(VertexData, uv)); //UV

很重要,因为sizeof(VertexData)不是8,而是8*sizeof(GL_FLOAT)


glBufferDataglBufferSubData的第一个参数必须是目标的枚举数常量,它是GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFER,...中的一个。
GL_VERTEX_ARRAY标识用于固定功能客户端功能的顶点数组-请参见glEnableClientState

更改:

glBufferData(GL_VERTEX_ARRAY, ...);
glBufferData(GL_ARRAY_BUFFER, ...);

glBufferSubData(GL_VERTEX_ARRAY, ...);
glBufferSubData(GL_ARRAY_BUFFER, ...);

请注意,如果您要检查OpenGL错误(glGetErrorDebug Output),则会收到GL_INVALID_ENUM错误。
未创建数组缓冲区的数据存储,这会导致段错误。