OpenGL和QtQuick纹理问题
OpenGL and QtQuick Texture Problems
我正在C++中基于Qt附带的"openglunderqml"示例开发一个简单的QQuickItem实现。我做了一些修改,使用了不同的着色器和我加载的两个纹理。想法是着色器将在两个纹理之间交叉渐变(本质上只是我加载到纹理中的图像)。
当我把这个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
}
}
我最近做了几乎相同的练习,(没有真正运行代码,只处理了一个纹理)我想我可能知道你错过了什么:你必须确保你的OpenGL状态机留在绘制函数的末尾(或多或少)与你在开始时发现的一样。您确实发布了着色器程序并禁用了数组属性,但没有解除两个纹理单位中两个纹理的绑定。以下在你的绘制成员功能结束时应该做的技巧:
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
除此之外,还有两条评论:
请注意,QML文件中的image1图像会完全隐藏ImageCrossfader项目(如果我没有错误解释锚点属性)。添加到QML场景中的所有内容都将绘制在opengl参考底图上(因此得名;))。
您可以安全地删除所有glEnable()、glDisable()和glBlendFunc()调用。实际上,删除它们应该会让你的代码更安全,因为你更改的次数越少,你需要记住恢复的更改就越少。
- Qt OpenGL 渲染到纹理性能问题
- SFML 纹理使用问题
- Opengl问题:很可能是简单的纹理问题
- 从文件问题加载纹理 Android NDK 和 OpenGL
- 如何在 Opengl 中使用多个纹理解决此问题
- 初始化多个纹理 OpenGL、SDL C++ 时出现问题
- 呈现纹理D3D11的问题
- 着色器和纹理坐标问题
- 在我的模型DirectX11中添加纹理的问题
- SDL2-从Surface(屏幕快照)创建纹理的问题
- 我的深度纹理有什么问题?
- Qt OpenGL - 纹理透明度问题
- OpenGL 3D 纹理问题
- 使用纹理,法线和索引列表从VBO绘制OpenGL对象的问题
- C++返回 sf::纹理时遇到问题
- 土壤,NPOT纹理问题
- OpenGL 3.3:在3D场景上显示2D纹理的问题
- 在 OpenGL-ES 中使用 Android NDK 上的C++创建具有"glTexImage2D"的纹理会导致问题
- 渲染到纹理问题
- Cinder & C++:镜像纹理和高效绘图问题