3

Qtに付属の「openglunderqml」の例に基づいて、C++で簡単なQQuickItem実装を開発しています。異なるシェーダーとロードする2つのテクスチャを使用するようにいくつかの変更を加えました。アイデアは、シェーダーが2つのテクスチャ(基本的にはテクスチャにロードした画像)間でクロスフェードすることです。

このQQuickItemをQMLファイル内に単独で配置して実行すると、すべてが正常に機能します。画像は互いにクロスフェードし(クロスフェードを維持するためにプロパティアニメーションを設定しました)、すべてが正常に表示されます。ただし、テキストなどの他の要素を配置すると、テキストが適切にレンダリングされません。奇妙な形のブロックが少しだけ表示されます。画像を入れると、すごく変になります。QQuickItemは、レンダリングするはずのボックスをレンダリングする代わりに、フルスクリーンで上下逆にレンダリングします。私が知る限り、他の画像はロードされません。

あるべきことをしていないに違いないと思いますが、何がいいのかわかりません。最初のコードブロックにはシェーダーとレンダリングが含まれ、2番目のコードブロックには新しい画像をテクスチャにロードする関数loadNewTexture()が含まれ(テクスチャごとに1回だけ呼び出され、すべてのレンダリングではありません)、3番目のコードブロックには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
    }
}
4

1 に答える 1

3

私は最近ほとんど同じ演習を行いました(実際にコードを実行しておらず、1つのテクスチャのみを処理した)私はあなたが見逃したものを知っているかもしれないと思います:OpenGLステートマシンが最後に残っていることを確認する必要がありますペイント機能(多かれ少なかれ)は、最初に見つけたとおりです。シェーダープログラムを解放し、配列属性を無効にしましたが、2つのテクスチャユニットの2つのテクスチャのバインドを解除しませんでした。ペイントメンバー関数の最後にある次の方法でうまくいくはずです。

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);

それ以外に、さらに2つのコメントがあります。

  • QMLファイルのimage1Imageは、ImageCrossfaderアイテムを完全に非表示にすることに注意してください(アンカープロパティの解釈を間違えない限り)。QMLシーンに追加するものはすべて、 openglアンダーレイのにペイントされます(そのため、名前は;))。

  • すべてのglEnable()glDisable()、およびglBlendFunc()呼び出しを安全に削除できます。実際にそれらを削除すると、コードがより安全になるはずです。変更が少なければ少ないほど、元に戻すために覚えておく必要のある変更が少なくなるからです。

于 2013-02-20T01:41:42.750 に答える