Opengl 和 Qml 混合編程
- Opengl 描繪3D效果
- Qml描繪2D效果
效果
源代碼
加強版效果
- 1.底層的opengl描繪背景
- 2.在qml描繪前描繪opengl,所以opengl處於底層
- 3.中間層描繪qml
- 4.在qml描繪後描繪opengl,所以opengl處於頂層
- 5.使用QQuickItem構建組件,供qml調用,組件內部描繪opengl
- 6.爲了讓上層opengl背景透明
觀察可以發現每層的遮擋效果
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-QmctiXdd-1593416516901)(https://res.cloudinary.com/qtdream/image/upload/v1527139252/cloundinary/hm9mn8ltlhrrkn1q3isw.gif)]
1.底層的opengl描繪背景
原理是在最遠的地方放一張圖片,放大圖片,直到完全鋪滿視口
//混合顯示背景
glBlendFunc(GL_ONE, GL_ZERO);
//描繪背景
glBindVertexArray(m_VAO[1]);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO[1]);
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)(sizeof(QVector3D)*1));
glVertexAttribPointer(m_texcoordLocation, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (GLvoid*)(sizeof(QVector3D)*2));
//背景的矩陣
QMatrix4x4 modelBg;
modelBg.translate(0.0f, 0.0f, -10.0f);
modelBg.scale(4.0f * 8, 3.0f * 8, 1.0f);
modelBg.rotate(0, 0, 1, 0);
m_program->setUniformValue(m_model, modelBg);
m_textureBg->bind();
glDrawArrays(GL_QUADS,0, 4);
m_textureBg->release();
2.在qml描繪前描繪opengl,所以opengl處於底層
以前我們是用timer來更新繪製,現在我們根據qml繪製時機,在渲染前,先渲染opengl,且不清除畫面,然後再繪製qml,這樣就變成上下兩層,
connect(window(), &QQuickWindow::beforeRendering, m_triangleWindow, &TriangleWindow::renderNow, Qt::DirectConnection);
//渲染qml前不清畫面,保留opengl
win->setClearBeforeRendering(false);
4.在qml描繪後描繪opengl,所以opengl處於頂層
渲染qml後,再次渲染opengl
connect(window(), &QQuickWindow::afterRendering, m_triangleWindow, &UpTriangleWindow::renderNow, Qt::DirectConnection);
- mainwindow類繼承QQuickItem,裏面使用渲染qml前繪製opengl
- upmainwindow類繼承QQuickItem,裏面使用渲染qml後繪製opengl
- mainwindow類使用TriangleWindow這個opengl類,TriangleWindow裏面繪製了背景圖片
- upmainwindow類使用UpTriangleWindow這個opengl類,裏面爲了透明背景,沒有清除GL_COLOR_BUFFER_BIT顏色緩衝區
- 關於清除opengl背景問題,我使用混合,成功去除了清除色,但是背景仍然顯示一個黑色,實在沒有辦法,於是使用了這個餿主意——沒有清除GL_COLOR_BUFFER_BIT
註冊
將c++類註冊到qml使用
//註冊opengl到qml
qmlRegisterType<MainWindow>("MainWindow", 1, 0, "MainWindow");
qmlRegisterType<UpMainWindow>("UpMainWindow", 1, 0, "UpMainWindow");