2

タイル イメージの一部を描画しようとしていますが、glDrawElements 関数を呼び出すと GL_INVALID_VALUE エラーが発生します。この関数を glDrawArrays で変更しても問題ありません。問題は、インデックス カウント パラメータが負の数ではないことです。

コードがあります:

#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
 #define VERTEX_ATTR_PTR(loc, count, member, type) \
    glEnableVertexAttribArray(loc); \
    glVertexAttribPointer(loc, count, GL_FLOAT, GL_FALSE, sizeof(type),  BUFFER_OFFSET(offsetof(struct type, member)))
// ---------- TextRenderer
void TextRenderer::setText(const string& text) {
    vector<Vertex2f> vertex_buffer;
    vector<GLuint> index_buffer;

    GLfloat cursor = 0.f;
    FPoint2D cell_size = font->getCellSize();

    for (char c : text) {
        TILE_ITER iter = font->getCharacter(c);
        {
            // UV
            for (GLuint i = 0; i < 4; ++i) {
                TILE_ITER _v = iter + i;
                vertex_buffer.push_back( {
                        {
                                _v->pos[0]  + cursor,
                                _v->pos[1],
                                _v->pos[2]
                        },
                        { _v->uv[0], _v->uv[1] }
                });
            }
            // Index
            for (GLuint i = 0; i < 6; ++i)
                index_buffer.push_back(
                        Tile::indices[i] + vertex_buffer.size() - 4);
        }
        cursor += cell_size.X;
    }

    vertices_count = vertex_buffer.size();
    indices_count = index_buffer.size();

    glBindVertexArray(vao);
    {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
        glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
                0,
                indices_count * sizeof(GLuint),
                &index_buffer[0]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

        glBindBuffer(GL_ARRAY_BUFFER, vbo);
        glBufferSubData(GL_ARRAY_BUFFER,
                0,
                vertices_count * sizeof(Vertex2f),
                &vertex_buffer[0]);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    glBindVertexArray(0);
}
void TextRenderer::create() {
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    {
        indices = genGLBuffer( {
                nullptr,
                BUFFER_SIZE / 2 * sizeof(GLuint),
                GL_ELEMENT_ARRAY_BUFFER
        }, true, GL_DYNAMIC_DRAW);

        vbo = genGLBuffer( {
                nullptr,
                BUFFER_SIZE * sizeof(Vertex2f),
                GL_ARRAY_BUFFER
        }, true, GL_DYNAMIC_DRAW);

        VERTEX_ATTR_PTR(0, 3, pos, Vertex2f); // Vertex
        VERTEX_ATTR_PTR(1, 2, uv, Vertex2f); // UV
    }
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    setText("DUPA");
}
void TextRenderer::draw(MatrixStack& matrix, GLint) {
    static Shader shader(
            getFileContents("shaders/text_frag.glsl"),
            getFileContents("shaders/text_vert.glsl"),
            "");

    shader.begin();
    shader.setUniform(GL_TEXTURE_2D, "texture", 0,
            font->getHandle());
    shader.setUniform("matrix.mvp", matrix.vp_matrix * matrix.model);
    shader.setUniform("col", col);
    {
        glBindVertexArray(vao);
        //glDrawArrays(GL_LINE_STRIP, 0, vertices_count);
        glDrawElements(GL_LINES, indices_count, GL_UNSIGNED_INT,
                nullptr);
        glBindVertexArray(0);
        showGLErrors();
    }
    shader.end();
}
4

2 に答える 2

4

setText()問題は、メソッド内の次の (短縮された) 呼び出しシーケンスにあります。

glBindVertexArray(vao);
{
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    ...
}
glBindVertexArray(0);

のバインディングはGL_ELEMENT_ARRAY_BUFFER、VAO 状態の一部です。したがって、VAO がバインドされている間に次の呼び出しを行うと、次のようになります。

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

の要素配列バッファバインディングを持つようにVAO状態を設定しています0draw()したがって、後でメソッドでVAO をバインドすると、 のバインドがなくなりますGL_ELEMENT_ARRAY_BUFFER

これを回避するための最も簡単な解決策は、その呼び出しを削除することです。バインドすると他のコードに望ましくない副作用が生じる可能性があるため、明示的にバインドを解除したい場合は、VAO のバインドを解除した後に移動する必要があります。

glBindVertexArray(vao);
{
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, ...);

    ...
}
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
于 2014-07-12T16:27:34.913 に答える
1

コード全体を見て、正確な GL のバージョンを知らなくても、正しい答えを出そうとします。

まず、ES2 を使用している場合、インデックス タイプを GL_UNSIGNED_INT として使用することはデフォルトではサポートされていませんが、それは問題ではないと思います。

実際の問題は、要素配列が実際には VAO オブジェクトに格納されず、頂点データ構成のみに格納されることです。したがって、 glDrawElements は、要素配列がバインドされていないと見なし、関数へのインデックス引数として NULL を渡したため、このエラーを返します。

これを解決するには、glDrawElements を呼び出す前に適切な要素配列をバインドします。

于 2014-07-12T06:56:36.860 に答える