Qt와 함께 제공되는 "openglunderqml"예제를 기반으로 C++에서 간단한 QQuickItem 구현을 개발 중입니다. 다른 셰이더와 두 개의 텍스처를 사용하기 위해 몇 가지 수정을했습니다. 아이디어는 셰이더가 두 텍스처 (기본적으로 텍스처에로드 된 이미지) 사이를 교차 페이딩 할 것이라는 것입니다.OpenGL 및 QtQuick 텍스처 문제
이 QQuickItem을 QML 파일 안에 넣고 실행하면 모든 것이 잘 동작합니다. 이미지는 서로간에 교차 페이드 (crossfading을 유지하기 위해 속성 애니메이션을 설정했습니다) 모든 것이 잘 보입니다. 그러나 텍스트와 같은 다른 요소를 넣으면 텍스트가 제대로 렌더링되지 않습니다. 이상한 모양의 블록 만 있습니다. 이미지를 넣으면 정말 이상해진다. QQuickItem 대신에 렌더링 할 상자를 렌더링하는 대신 전체 화면과 거꾸로 렌더링합니다. 멀리 내가 말할 수있는 한 다른 이미지는 절대로드되지 않습니다.
내가해야 할 일을하고 있지 않아야한다고 생각하지만, 나는 모릅니다. 첫 번째 코드 블록에는 쉐이더와 렌더링 항목이 포함되어 있으며 두 번째 코드에는 텍스처에 새 이미지를로드하는 loadNewTexture() 함수가 포함되어 있습니다 (모든 렌더링이 아닌 텍스처마다 한 번만 호출 됨). 세 번째 코드 블록에는 QtQuick .qml 파일 .
을 Heres합니다 (QQuckItem 내의 :: 페인트 방법)는 OpenGL 번호 :
// 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 요소와 결합 될 때 전체 화면이 표시되는 대신 아무 것도 인쇄되지 않습니다.나는 이것이 더 나은 것처럼 느낀다. 그러나 나는 아직도 그것을 능숙하게 멈추게하는 것을 게을리해야한다. 이 테스트는 독자적으로 수행했는데 작동하는 것처럼 보입니다. 그러나 하나의 QML 파일에서 두 개의 ImageCrossfader 요소를 사용하더라도 하나만 표시됩니다. 더 이상 아이디어가 없습니까? 고마워 btw! –
위의 네 줄 (페인트 기능의 끝 부분)은 자신의 QQuickItem 텍스처의 가시성에 영향을 주어서는 안됩니다. 하지만 내 자신의 조언에 따라, 나는 두 개의'glActiveTexture (...)'호출을 바꿔서, 텍스처 uni 0이 마지막에 활성화되었다. 여전히 작동하지 않는 경우 전체 프로젝트를 어딘가에 액세스 할 수 있습니까? * GL 언더 레이 * 아이템 중 두 개는'glClear()'를 호출하기 때문에 작동하지 않습니다. 이 접근법은 실제로 QML 장면의 배경을 채우는 것만으로 의미가 있습니다. – axxel
선생님, 훌륭합니다. 결국 glClear()에 대한 호출이 단순히 glViewport가 아닌 전체 화면을 지우는 것을 이해하지 못했습니다. 마지막 질문 : glViewport() 호출로 설치 한 뷰포트 만 지우는 좋은 방법이 있습니까? (주 : 활성 텍스처 호출의 순서가 바뀌 었습니다.) –