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));
}