Home > Enterprise >  OpenGL color all vertices for a given buffer from one QVector3D?
OpenGL color all vertices for a given buffer from one QVector3D?

Time:11-16

I have a program that renders FACET geometry and then plots data over top of the geometry in the same OpenGL context. Everything is working as intended when doing color by vertex from a VBO that defines facet triangles and their associated colors, however the user has requested the ability to set all of the geometry vertices to a single color (GUI toggle).

Is there any way to do this without going in and setting the color portions of the VBO to that color? Just seems very inefficient, but I can't get anything I've tried from hours of googling to work.

Using C , QT6

Fragment Shader

#version 150 core
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

in vec3 Color;
out vec4 outColor;

void main()
{
    outColor = vec4(Color,1.0f);
}

Vertex Shader

#version 150 core
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif

uniform mat4 mvp_matrix;
attribute vec4 a_position;
attribute vec2 a_texcoord;
varying vec2 v_texcoord;
attribute vec3 color;
varying vec3 Color;

void main()
{
    Color = color;

    // Calculate vertex position in screen space
    gl_Position = mvp_matrix * a_position;

    // Pass texture coordinate to fragment shader
    // Value will be automatically interpolated to fragments inside polygon faces
    v_texcoord = a_texcoord;
}

Relevant snippets of code:

// initializing the buffers from vectors of structures
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Geometry
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Get a copy of the geometry to reference here
    std::vector<storedGeometry::facetData> tGeom = gUseGeom.getGeom();
    // Convert vector to array
    storedGeometry::facetData* aGeom = tGeom.data();

    // Transfer vertex data to VBO 0
    geomBuf.bind();
    geomBuf.allocate(aGeom, int(tGeom.size() * sizeof(storedGeometry::facetData)));

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Currents
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Get a copy of the currents data to reference here
    std::vector<storedGeometry::facetData> tCurrents = gUseCurrents.getGeom();
    // Convert vector to array
    storedGeometry::facetData* aCurrent = tCurrents.data();

    // Transfer vertex data to VBO 1
    currentsBuf.bind();
    currentsBuf.allocate(aCurrent, int(tCurrents.size() * sizeof(storedGeometry::facetData)));




// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// drawing 
// Get shader variable locations
    int vertexLocation = program->attributeLocation("a_position");
    int colorLocation = program->attributeLocation("color");
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Plot Geometry
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (bGeomVisible) {
        geomBuf.bind();
        program->enableAttributeArray(vertexLocation);
        program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(QVector3D));

        program->enableAttributeArray(colorLocation);
        if (bCobbleSolid) { // Solid
// This is what I can't get to work ************************************
            //program->setAttributeValue(colorLocation, 1.0, 1.0, 1.0);
            program->setAttributeValue(colorLocation, QVector3D(1.0,1.0,1.0));
        } else { // Cobble
            program->setAttributeBuffer(colorLocation, GL_FLOAT, 3*sizeof(QVector3D), 3, sizeof(QVector3D));
        }

        // Set polygon/wiremesh or solid/filled mode based on fill/wire toggle
        if (bFillWire) {
            // Polygon = TRUE
            glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
        } else {
            // Filled = FALSE
            glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
        }
        // Draw geometry
        glDrawArrays(GL_TRIANGLES, 0, gUseGeom.gSize() * 6);
    }
    // Debugging
    //out << "gUseGeom.gSize(): " << gUseGeom.gSize() << Qt::endl;
    // Draw cube geometry
    //glDrawElements(GL_TRIANGLES, gUseGeom.gSize() * 3, GL_UNSIGNED_SHORT, 0);
    //glDrawArrays(GL_TRIANGLES, 0, gUseGeom.gSize() * 6);

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Plot Currents
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if (bCurrentsVisible) {
        currentsBuf.bind();
        program->enableAttributeArray(vertexLocation);
        program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0,                   3, sizeof(QVector3D));
        program->enableAttributeArray(colorLocation);
        program->setAttributeBuffer(colorLocation,  GL_FLOAT, 3*sizeof(QVector3D), 3, sizeof(QVector3D));
        glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
        glDrawArrays(GL_TRIANGLES, 0, gUseCurrents.gSize() * 6);
    }

CodePudding user response:

When a specific vertex attribute array is not enabled (with glEnableVertexAttribArray) then the value for that attribute, for all rendered vertices, is taken from the current vertex attribute value, as defined by the glVertexAttrib family of functions.

You forgot to disable the vertex attribute array, therefore the current vertex attribute value isn't used. You can fix it as follows:

    if (bCobbleSolid) { // Solid
        program->disableAttributeArray(colorLocation);
        program->setAttributeValue(colorLocation, QVector3D(1.0,1.0,1.0));
    } else { // Cobble
        program->enableAttributeArray(colorLocation);
        program->setAttributeBuffer(colorLocation, GL_FLOAT, 3*sizeof(QVector3D), 3, sizeof(QVector3D));
    }
  • Related