pascal sautot
pascal sautot

Reputation: 405

vertex buffer object and data buffers [opengl]

I'm trying to figure out how to use multiple buffers associated to a single vertex array object on the basis of one buffer per "object model" (e.g. verticies, normal, textures). To make it very simple in the sample code that follows I have couple objects composed of just one triangles (3 vertices) and associated colors. Buffer element indexed by ArrayBuffer1 receive the vertex coords (homogeneous coords) and an RGBA color vectors. Same for Buffer element indexed by ArrayBuffer2.

The vertex shader is a passthrough as following

    #version 400 core

    layout( location = 0 ) in vec4 vPosition;
    layout( location = 1 ) in vec4 vColor;
    out vec4 color;
    void
    main()
    {
        color= vColor;
        gl_Position = vPosition;
    }

The fragment shader is a passthroug has well

    #version 450 core

    in vec4 color;
    out vec4 fColor;

    void main()
    {
        fColor = color; 
    }

I d like to pass on data with one buffer per object grouping vertex attributes in the same buffer.

I can't figure how to raw these 2 objects. Here is the client code (init part)

    enum VertexDim { xDim, yDim, zDim, wDim, NumDim};
    enum VAO_IDs { Triangles, NumVAOs };
    enum Buffer_IDs { ArrayBuffer1, ArrayBuffer2, NumBuffers };
    enum Attrib_IDs { vPosition = 0, vColor=1 };

    GLuint  VAOs[NumVAOs];
    GLuint  Buffers[NumBuffers];

    const GLuint  NumVertices = 6;
    const GLuint curDim= NumDim;
    // first triangle 
    GLfloat  static_vertices1[NumVertices/2][NumDim] = {
        { -0.90f, -0.90f, 0.5f, 1}, {  0.85f, -0.90f, 0.3f, 1 }, { -0.90f,  0.85f, 0.0f, 1 }  // Triangle 1
    };
    // second triangle
    GLfloat  static_vertices2[NumVertices/2][NumDim] = {
        {  0.90f, -0.85f, -0.1f, 1 }, {  0.90f,  0.90f, -0.5f, 1 }, { -0.85f,  0.90f, -0.8f, 1 }   // Triangle 2
    };
    // a base color from which to compute different vertex colors
    GLfloat infColor_value[4]= {0.9f, 0.7f, 0.5f, 1.0f};  

    //----------------------------------------------------------------------------
    //
    // init
    //

    void
    init( void )
    {   
        const unsigned int n=NumVertices/2;
        GLfloat infColor_values1[n][curDim];    
        GLfloat infColor_values2[n][curDim];  
        // compute different vertex colors from base color   infColor_value
        // .. loop over    infColor_values1 and infColor_values2

        ShaderInfo  shaders[] =
        {
            { GL_VERTEX_SHADER, "media/shaders/triangles/triangles2.vert" },
            { GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles2.frag" },
            { GL_NONE, NULL }
        };
        // LoadShaders is a wrapper to load, compile code and link shaders
        GLuint program = LoadShaders( shaders );
        if( program == 0) { std::cerr<<"shader program failed to build" << std::endl; }
        glUseProgram( program );

        glGenVertexArrays( NumVAOs, VAOs );
        glBindVertexArray( VAOs[Triangles] );
        glCreateBuffers( NumBuffers, Buffers );

        // vertex 1
        glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer1] );
        glNamedBufferData( Buffers[ArrayBuffer1], sizeof(static_vertices1)+sizeof(infColor_values1) , NULL, GL_STATIC_DRAW);
        glNamedBufferSubData( Buffers[ArrayBuffer1], 0,  sizeof(static_vertices1), static_vertices1);
        glNamedBufferSubData( Buffers[ArrayBuffer1], sizeof(static_vertices1),  sizeof(infColor_values1), infColor_values1);

        GLuint64 offset = 0;
        glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
        glEnableVertexAttribArray( vPosition );
        offset = sizeof(static_vertices1);
        glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
        glEnableVertexAttribArray( vColor );

        // vertex 2 
        glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer2] );       
        glNamedBufferData( Buffers[ArrayBuffer2], sizeof(static_vertices2)+sizeof(infColor_values2) , NULL, GL_STATIC_DRAW);
        glNamedBufferSubData( Buffers[ArrayBuffer2], 0,  sizeof(static_vertices2), static_vertices1);
        glNamedBufferSubData( Buffers[ArrayBuffer2], sizeof(static_vertices2),  sizeof(infColor_values2), infColor_values2);

        offset = 0;
        glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
        glEnableVertexAttribArray( vPosition );
        offset = sizeof(static_vertices2);
        glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
        glEnableVertexAttribArray( vColor );
        
        glBindBuffer( GL_ARRAY_BUFFER, 0 );
        glBindVertexArray(0);
    }

and here follows the code to render


void
display( void )
{
    static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };

    glClearBufferfv(GL_COLOR, 0, black);

    glBindVertexArray( VAOs[Triangles] );
    glDrawArrays( GL_TRIANGLES,  0, NumVertices );
    glBindVertexArray(0);    
}

to sum it up : how to store an object vertices attributes in a single buffer and still display multiple objects ? I could fetch verything in the same sub buffers (one for vertex coord, one for vetex colors) but I can't come up wit ha solution where I would sparate the obejcts to render.

I ve read close answers ( Architecture to draw many different objects in OpenGL What are Vertex Array Objects? ) related to this question yet it does not answer my question.

Upvotes: 0

Views: 76

Answers (1)

pascal sautot
pascal sautot

Reputation: 405

Defining a VAO for each object made it following @Rabbid76 advice

change for the init code

    enum Buffer_IDs { Mesh, NumBuffers };

    //....


        // triangle 1
        glBindBuffer( GL_ARRAY_BUFFER, Buffers1[Mesh] );
        glNamedBufferData( Buffers1[Mesh], sizeof(static_vertices1)+sizeof(infColor_values1) , NULL, GL_STATIC_DRAW);
        glNamedBufferSubData( Buffers1[Mesh], 0,  sizeof(static_vertices1), static_vertices1);
        glNamedBufferSubData( Buffers1[Mesh], sizeof(static_vertices1),  sizeof(infColor_values1), infColor_values1);

        GLuint64 offset = 0;
        glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
        glEnableVertexAttribArray( vPosition );
        offset = sizeof(static_vertices1);
        glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
        glEnableVertexAttribArray( vColor );

        glBindBuffer( GL_ARRAY_BUFFER, 0 );
        glBindVertexArray(0);

        // triangle 2
        glBindVertexArray( VAOs[Triangle2] );
        glCreateBuffers( NumBuffers, Buffers2 );
        glBindBuffer( GL_ARRAY_BUFFER, Buffers2[Mesh] );
        glNamedBufferData( Buffers2[Mesh], sizeof(static_vertices2)+sizeof(infColor_values2) , NULL, GL_STATIC_DRAW);
        glNamedBufferSubData( Buffers2[Mesh], 0,  sizeof(static_vertices2), static_vertices2);
        glNamedBufferSubData( Buffers2[Mesh], sizeof(static_vertices2),  sizeof(infColor_values2), infColor_values2);

        offset = 0;
        glVertexAttribPointer( vPosition, NumDim, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
        glEnableVertexAttribArray( vPosition );
        offset = sizeof(static_vertices2);
        glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)offset );
        glEnableVertexAttribArray( vColor );

change for the render code

    void
    display( void )
    {
        static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };

        glClearBufferfv(GL_COLOR, 0, black);

        glBindVertexArray( VAOs[Triangle1] );
        glDrawArrays( GL_TRIANGLES,  0, NumVertices/2 );
        glBindVertexArray( VAOs[Triangle2] );
        glDrawArrays( GL_TRIANGLES,  0, NumVertices/2 );   
        glBindVertexArray(0);    
    }

Upvotes: 0

Related Questions