Проблемы с текстурами OpenGL и QtQuick

Я разрабатываю простую реализацию QQuickItem в C ++ на основе примера «openglunderqml», поставляемого с Qt. Я сделал несколько модификаций, чтобы использовать разные шейдеры и две загружаемые текстуры. Идея состоит в том, что шейдеры будут плавно переходить между двумя текстурами (которые по сути являются просто изображениями, которые я загрузил в текстуры).

Когда я помещаю этот 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
}
}

3

Решение

Недавно я выполнил почти то же самое упражнение и (не выполняя ваш код и работая только с одной текстурой), я думаю, у меня может быть представление о том, что вы пропустили: вы должны убедиться, что Конечный автомат OpenGL остается в конце вашей функции рисования (более или менее) точно как вы нашли это в начале. Вы выпустили программу шейдера и отключили атрибут массива, но не связали две текстуры в ваших двух текстурных единицах. Следующее в конце вашей функции-члена рисования должно помочь:

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

Кроме этого, два дальнейших комментария:

  • Обратите внимание, что ваш image1 Изображение из файла QML полностью скрывает ваш элемент ImageCrossfader (если я не ошибаюсь, интерпретируя свойство якоря). Все, что вы добавите в свою QML-сцену, будет нарисовано над ваш подкладка opengl (отсюда и название;)).

  • Вы можете безопасно удалить все glEnable (), glDisable () а также glBlendFunc () звонки. На самом деле их удаление должно сделать ваш код более безопасным, потому что чем меньше вы изменяете, тем меньше изменений вы должны помнить, чтобы вернуться.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]