我有一個QGLWidget(Qt 5.2.1)。QOpenGLShaderProgram - 多個實例產生損壞的結果
GLWidget實例化兩個其他類,每個類都包含它們自己的QOpenGLShaderPrograms,加載它們自己的着色器,並處理它們自己的圖形。這使得一個很好的封裝。
然而,問題是來自軸網格的數據(第一個被初始化)出現在第二類的着色器中。因此,它從不用自己的着色器繪製自己的對象。如果我逆轉init()調用的順序,則相反的情況會發生。
這兩個繪圖類的結構相同,所以爲了簡潔起見,我只包含Mesh類。
結果如下。繪製線條的AxisMesh將它們繪製在Scatter類上,使用相同的顏色,而不是用它們自己的顏色以及它們應該繪製的位置。
在這幅畫的線條應該是一個不同的顏色和不同的位置:
問題:
是否允許有兩個QOpenGLShaderPrograms在QGLWidget來繪圖?
下面的方法有什麼問題嗎?
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);
}
軸網格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();
}
軸網格生成方法:
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();
}
軸網繪製方法:
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();
}
我不知道Qt的東西,但我懷疑,這個問題是有關您在設置頂點屬性的方式。頂點設置狀態不是程序的一部分。由於您似乎有在程序類中設置頂點狀態的方法,因此它看起來就像是這樣,這可能會讓您失望。程序和頂點狀態是不相關的,並且將它們設置在同一個類中的方法看起來像一個不幸的設計。 –
謝謝Reto。在設計方面,如果我有兩個需要不同着色器的對象,你會如何設置它們?如果不是將着色器程序封裝爲對象的一部分,您會如何推薦? – Alchete
如果我的理論是正確的,你可以通過在'draw()'方法中調用'enableAttributeArray()'和'setAttributeBuffer()'來調用它。 –