PDA

View Full Version : QGLWidget + multiple QOpenGLShaderPrograms -- data going to wrong shader



alketi
26th April 2015, 16:20
First, I'm under the assumption that it's possible to have multiple shader programs and that only the currently bound one is active.

I have a QGLWidget (Qt 5.2.1).

The GLWidget instantiates two other classes that each contain their own QOpenGLShaderPrograms, load their own shaders, and handle their own drawing. This makes for a nice encapsulation.

HOWEVER -- the issue is that the data from the axis mesh (first one being initialized) is appearing in the second class's shader. So, it never draws it's own object with it's own shader. If I reverse the order of init() calls, the same thing happens in reverse.

The two drawing classes are structured identically, so I'm including only the Mesh class for brevity.

Here's the result. The AxisMesh, which draws lines, is drawing them over the Scatter class, with the same color, instead of in their own color and where they're supposed to be drawn.

11135

Is it allowed to have two QOpenGLShaderPrograms in a QGLWidget?
Is there something wrong with the approach below?


void GLWidget::initializeGL()
{
// Instantiate our drawing objects
m_axisMesh = new PlotItemAxisMesh(m_plotManager, m_plotSelection, &m_axisScale);
m_surfaceScatter = new PlotItemSurfaceScatter(m_plotManager, m_plotSelection, &m_axisScale);

...

// Initialize the axis mesh class
m_axisMesh->init();

// Initialize the scatter points class
m_surfaceScatter->init();
}



void GLWidget::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

...

// Draw the mesh
m_axisMesh->draw(m_camera.data(), modelMatrix);

// Draw the points
m_surfaceScatter->draw(m_camera.data(), modelMatrix);
}



void PlotItemAxisMesh::init()
{
initializeOpenGLFunctions();

// Initialize the shaders
initShaders();

m_program->link();
m_program->bind();

// Load the data into the local VBO
build();

// Release (unbind) all
m_program->release();
}



void PlotItemAxisMesh::build()
{
ShmooPlotMatrix *matrix = m_plotManager->getPlotPointMatrix();

// Calculate the y-axis height in OpenGL terms
uint32_t yHeight = (m_xMax + m_yMax)/2;
float yScale = yHeight / fabs(m_axisScale->getMax() - m_axisScale->getMin());
float yOffset = 0 ? m_axisScale->getMin() > 0 : -m_axisScale->getMin();

// Since we swept X/Y but are plotting the points as X/Z, then Y becomes the value
m_xMax = matrix->getXMax();
m_yMax = yHeight;
m_zMax = matrix->getYMax();

m_vertexArray.clear();
m_vertexArray.reserve(4*(m_xMax + m_yMax));

... (load vertexAray with data)

m_vertexBuffer.create();
m_vertexBuffer.bind();
m_vertexBuffer.setUsagePattern(QOpenGLBuffer::Dyna micDraw);
m_vertexBuffer.allocate(&(m_vertexArray.front()), vertexSize);

// Tell VBO how to read the data
m_positionAttrIndex = m_program->attributeLocation(m_positionAttr);
m_colorAttrIndex = m_program->attributeLocation(m_colorAttr);

int offset = 0;
m_program->enableAttributeArray(m_positionAttrIndex);
m_program->setAttributeBuffer(m_positionAttrIndex, GL_FLOAT, offset, 3, sizeof(VertexData));

offset = sizeof(QVector3D);
m_program->enableAttributeArray(m_colorAttrIndex);
m_program->setAttributeBuffer(m_colorAttrIndex, GL_FLOAT, offset, 3, sizeof(VertexData));

// Release (unbind) all
m_vertexBuffer.release();
}



void PlotItemAxisMesh::draw(PlotCamera *camera, const QMatrix4x4 &modelMatrix)
{

m_program->bind();
{
// Set modelview-projection matrix
m_program->setUniformValue("mvpMatrix", camera->getProjection() * camera->getView() * modelMatrix);
m_vertexBuffer.bind();
glDrawArrays(GL_LINES, 0, m_vertexArray.size());
m_vertexBuffer.release();
}
m_program->release();
}