QOpenGLShaderProgram - 多个实例产生损坏的结果

时间:2015-04-26 15:53:01

标签: c++ qt opengl qglwidget

我有一个QGLWidget(Qt 5.2.1)。

GLWidget实例化另外两个类,每个类包含自己的QOpenGLShaderPrograms,加载自己的着色器,并处理自己的绘图。这样可以很好地封装。

但是 - 问题是来自轴网格的数据(第一个被初始化)出现在第二个类的着色器中。因此,它永远不会使用自己的着色器绘制自己的对象。如果我颠倒了init()调用的顺序,那么反过来就会发生同样的事情。

两个绘图类的结构相同,所以为了简洁,我只包括Mesh类。

这是结果。绘制线条的AxisMesh将它们绘制在Scatter类上,颜色相同,而不是它们自己的颜色以及应该绘制它们的位置。

此图片中的线条应为不同的颜色和不同的位置: The lines in this picture should be a different color and a different location

问题:

是否允许在QGLWidget中有两个QOpenGLShaderPrograms?

下面的方法有问题吗?

GLWidget initialzeGL方法:

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

GLWidget paintGL方法:

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

Axis Mesh init方法:

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

Axis Mesh构建方法:

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::DynamicDraw);
    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();
}

Axis Mesh绘制方法:

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

1 个答案:

答案 0 :(得分:1)

感谢@Reto Koradi提供的解决方案

修复方法是更改​​绘制方法以在绘制时启用/设置属性缓冲区。

void PlotItemAxisMesh::draw(PlotCamera *camera, const QMatrix4x4 &modelMatrix)
{
    m_program->bind();
    {
        m_vertexBuffer.bind();

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

        // Set modelview-projection matrix
        m_program->setUniformValue("mvpMatrix",  camera->getProjection() * camera->getView() * modelMatrix);

        glDrawArrays(GL_LINES, 0, m_vertexArray.size());
        m_vertexBuffer.release();
    }
    m_program->release();
}

正确的绘图

enter image description here