我正在開發的C++基礎上使用Qt來了「openglunderqml」例如一個簡單的QQuickItem實現。我做了一些修改,以使用不同的着色器和兩個我加載的紋理。其思想是着色器將在兩個紋理之間交叉淡入淡出(實際上這只是我加載到紋理中的圖像)。OpenGL和QtQuick紋理問題
當我把這個QQuickItem單獨一個QML文件中並運行它,一切工作正常。圖像在彼此之間交叉淡入淡出(我已經設置了一個屬性動畫來保持它們淡入淡出),一切都很好。但是,如果我放置其他元素(如文本),則文本無法正確呈現 - 只是形狀奇怪的塊。如果我把圖像放進去,事情變得很奇怪。而不是呈現它應該呈現的框的QQuickItem,它呈現全屏並顛倒。據我所知,其他圖像從未加載。
我想我一定是沒有做的東西,我是應該的,但我不知道是什麼。請注意,第一個代碼塊包含着色器和渲染材料,第二個代碼塊包含將新圖像加載到紋理中的函數loadNewTexture()(每個紋理只調用一次 - 不是每次渲染),第三個包含QtQuick .qml文件。
赫雷什OpenGL的代碼(QQuckItem內:: Paint方法):
// Builds the OpenGL shaders that handle the crossfade
if (!m_program) {
m_program = new QOpenGLShaderProgram();
// Shader loads coordinate positions
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,
"attribute vec2 position;"
"varying vec2 texcoord;"
"void main() {"
" gl_Position = vec4(position, 0.0, 1.0);"
" texcoord = position * vec2(0.5) + vec2(0.5);"
"}");
// Shader does the crossfade
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,
"uniform lowp float xfade;"
"uniform sampler2D textures[2];"
"varying vec2 texcoord;"
"void main() {"
" gl_FragColor = mix("
" texture2D(textures[0], texcoord),"
" texture2D(textures[1], texcoord),"
" xfade"
" );"
"}");
m_program->bindAttributeLocation("vertices", 0);
m_program->link();
connect(window()->openglContext(), SIGNAL(aboutToBeDestroyed()),
this, SLOT(cleanup()), Qt::DirectConnection);
}
m_program->bind();
// Loads corner vertices as triangle strip
m_program->enableAttributeArray(0);
float values[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
m_program->setAttributeArray(0, GL_FLOAT, values, 2);
// Loads the fade value
m_program->setUniformValue("xfade", (float) m_thread_xfade);
glEnable(GL_TEXTURE_2D);
// Check if a new texture needs to be loaded
if (!new_source_loaded && !m_adSource.isEmpty())
new_source_loaded = loadNewTexture(m_adSource);
// Loads texture 0 into the shader
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
m_program->setUniformValue("textures[0]", 0);
// Loads texture 1 into the shader
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
m_program->setUniformValue("textures[1]", 1);
// Sets the OpenGL render area to the space given to this components
glViewport((GLint) this->x(), (GLint) this->y(), (GLint) this->width(), (GLint) this->height());
// Sets some parameters
glDisable(GL_DEPTH_TEST);
// Sets the clear color (backround color) to black
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
// Draws triangle strip
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
// Cleans up vertices
m_program->disableAttributeArray(0);
m_program->release();
的loadNewTexture()函數:
bool AdRotator::loadNewTexture(QUrl source) {
// Load the image from source url
QImage image(source.path());
// Check that the image was loaded properly
if (image.isNull()) {
qDebug() << QString("AdRotator::loadTexture: Loading image from source: ") << source.toString() << QString(" failed.");
return false;
}
// Update this as the active texture
active_texture = !active_texture;
// Convert into GL-friendly format
QImage GL_formatted_image = QGLWidget::convertToGLFormat(image);
// Check that the image was converted properly
if (image.isNull()) {
qDebug() << QString("AdRotator::loadTexture: Converting image from source: ") << source.toString() << QString(" failed.");
return false;
}
// Generate the texture base
glGenTextures(1, &textures[active_texture]);
glBindTexture(GL_TEXTURE_2D, textures[active_texture]);
// Give texture parameters (scaling and edging options)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Load pixels from image into texture
glTexImage2D(
GL_TEXTURE_2D, 0, /* target, level of detail */
GL_RGBA, /* internal format */
GL_formatted_image.width(), GL_formatted_image.height(), 0, /* width, height, border */
GL_RGBA, GL_UNSIGNED_BYTE, /* external format, type */
GL_formatted_image.bits() /* pixels */
);
if (textures[active_texture] == 0) qDebug() << QString("New Texture post-load failed.");
return true;
}
的.qml文件:
import QtQuick 2.0
Item {
width: 1920
height: 1080
/* Image{} element breaks things
Image {
id: image1
x: 0
y: 0
anchors.rightMargin: 0
anchors.bottomMargin: 0
anchors.leftMargin: 0
anchors.topMargin: 0
sourceSize.height: 1080
sourceSize.width: 1920
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
source: "images/background.png"
}*/
/* The QQuickItem */
ImageCrossfader {
x: 753
y: 107
width: 1150
height: 865
}
}
這無疑是正確的方向邁出的一步。現在,當與其他QML元素結合使用時,圖像不會顯示爲顛倒和全屏,也不會打印任何圖像。我覺得這樣比較好,但我仍然必須忽略一些阻止它發揮出色的東西。 請注意,我已經對其進行了單獨測試,它似乎可以正常工作,但即使我將兩個ImageCrossfader元素放在一個QML文件中,也只顯示一個。還有什麼想法?非常感謝btw! – 2013-02-21 05:16:34
上面提到的4行(在繪製函數結束時)不應該影響您自己的QQuickItem紋理的可見性。但是按照我自己的建議,我換了兩個'glActiveTexture(...)'調用,所以紋理單元0在最後被激活。 如果它仍然不起作用,你可以讓整個項目在某個地方訪問嗎? 由於兩者都調用glClear(),所以有兩個* GL底層*項不起作用。這種方法對於呈現QML場景的一個(填充)背景真的非常有意義。 – axxel 2013-02-21 12:48:38
你先生,很棒。事實證明,我只是不明白調用glClear()會清除整個屏幕,而不僅僅是glViewport。最後一個問題:是否有一種很好的方法來清除我用glViewport()調用設置的視口? (注意:它正在切換活動紋理調用的順序) – 2013-02-21 17:58:13