После моего последнего вопроса: Мой OpenGL QQuickItem не будет иметь нужный мне размер , я сейчас пытаюсь, вместо того, чтобы иметь произвольный размер для моего видео OpenGL, чтобы он поместился внутри моего QQuickItem,
Я слышал, что QQuickItem::transform()
даст мне список матриц преобразования.Я предполагаю , что этот список содержит все преобразования, необходимые для получения квадрата размера и положения моего QQuickItem.<<<< Это правда?Если да, то из каких координат и размеров области просмотра происходят преобразования? </p>
Учитывая это как истинное, я сделал следующий минимальный проверяемый и компилируемый пример, который пытается привести зеленый экран в соответствие с размером моего QQuickItem.Но в настоящее время он занимает весь экран.
Я использовал функцию getModelMatrix()
, которую вы можете найти ниже, чтобы получить все преобразования и сделать из них матрицу.Затем я применяю эти преобразования к своему вершинному шейдеру, выполняя
gl_Position = u_transform * vertexIn;
Как я уже сказал, в результате получается зеленый экран.Тем не менее, он имеет те же размеры моего окна, вместо размеров 640x480 и x, y = 0, как указано в main.qml
. Здесь вы можете найти минимальный скомпилируемый и проверяемый пример: https://github.com/lucaszanella/openglqtquickexample/tree/88fe0092d663dd92c551c72acccd0bf058fe7e5b
OpenGlVideoQtQuick.cpp:
#include "OpenGlVideoQtQuick.h"
#define GET_STR(x) #x
#define A_VER 3
#define T_VER 4
//Simple shader. Outpus the same location as input, I guess
const char *vString2 = GET_STR(
attribute vec4 vertexIn;
attribute vec2 textureIn;
varying vec2 textureOut;
uniform mat4 u_transform;
void main(void)
{
gl_Position = u_transform * vertexIn;
textureOut = textureIn;
}
);
const char *tString2 = GET_STR(
varying vec2 textureOut;
uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;
void main(void)
{
vec3 yuv;
vec3 rgb;
yuv.x = texture2D(tex_y, textureOut).r;
yuv.y = texture2D(tex_u, textureOut).r - 0.5;
yuv.z = texture2D(tex_v, textureOut).r - 0.5;
rgb = mat3(1.0, 1.0, 1.0,
0.0, -0.39465, 2.03211,
1.13983, -0.58060, 0.0) * yuv;
gl_FragColor = vec4(rgb, 1.0);
}
);
OpenGlVideoQtQuick::OpenGlVideoQtQuick():
openGlVideoQtQuickRenderer(nullptr)
{
connect(this, &QQuickItem::windowChanged, this, &OpenGlVideoQtQuick::handleWindowChanged);
update();
}
void OpenGlVideoQtQuick::handleWindowChanged(QQuickWindow *win)
{
if (win) {
connect(win, &QQuickWindow::beforeSynchronizing, this, &OpenGlVideoQtQuick::sync, Qt::DirectConnection);
win->setClearBeforeRendering(false);
}
}
QMatrix4x4 OpenGlVideoQtQuick::getModelMatrix() {
QMatrix4x4 result;
// Compose model matrix from our transform properties in the QML
QQmlListProperty<QQuickTransform> transformations = transform();
const int count = transformations.count(&transformations);
for (int i=0; i<count; i++) {
QQuickTransform *transform = transformations.at(&transformations, i);
transform->applyTo(&result);
}
return result;
}
void OpenGlVideoQtQuick::update()
{
if (window())
window()->update();
}
OpenGlVideoQtQuickRenderer::~OpenGlVideoQtQuickRenderer()
{
delete program;
}
void OpenGlVideoQtQuick::sync()
{
if (!openGlVideoQtQuickRenderer) {
openGlVideoQtQuickRenderer = new OpenGlVideoQtQuickRenderer();
connect(window(), &QQuickWindow::beforeRendering, openGlVideoQtQuickRenderer, &OpenGlVideoQtQuickRenderer::render, Qt::DirectConnection);
connect(window(), &QQuickWindow::afterRendering, this, &OpenGlVideoQtQuick::update, Qt::DirectConnection);
}
this->openGlVideoQtQuickRenderer->qQuickVideoMatrix = getModelMatrix();
}
static const GLfloat ver[] = {
-1.0f,-1.0f,
1.0f,-1.0f,
-1.0f, 1.0f,
1.0f, 1.0f
};
static const GLfloat tex[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f
};
void OpenGlVideoQtQuickRenderer::render()
{
if (this->firstRun) {
std::cout << "Creating QOpenGLShaderProgram " << std::endl;
this->firstRun = false;
program = new QOpenGLShaderProgram();
initializeOpenGLFunctions();
std::cout << "Fragment Shader compilation: " << program->addShaderFromSourceCode(QOpenGLShader::Fragment, tString2) << std::endl;
std::cout << "Vertex Shader compilation: " << program->addShaderFromSourceCode(QOpenGLShader::Vertex, vString2) << std::endl;
program->bindAttributeLocation("vertexIn",A_VER);
program->bindAttributeLocation("textureIn",T_VER);
std::cout << "program->link() = " << program->link() << std::endl;
glGenTextures(3, texs);//TODO: ERASE THIS WITH glDeleteTextures
}
program->bind();
program->setUniformValue("u_transform", this->qQuickVideoMatrix);
//glViewport(50, 50, 50, 50);
glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);
glEnableVertexAttribArray(A_VER);
glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);
glEnableVertexAttribArray(T_VER);
unis[0] = program->uniformLocation("tex_y");
unis[1] = program->uniformLocation("tex_u");
unis[2] = program->uniformLocation("tex_v");
//Y
glBindTexture(GL_TEXTURE_2D, texs[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//U
glBindTexture(GL_TEXTURE_2D, texs[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
//V
glBindTexture(GL_TEXTURE_2D, texs[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
program->disableAttributeArray(A_VER);
program->disableAttributeArray(T_VER);
program->release();
}
OpenGlVideoQtQuick.h :
#ifndef OpenGlVideoQtQuick_H
#define OpenGlVideoQtQuick_H
#include <QtQuick/QQuickItem>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLFunctions>
#include <QtQuick/qquickwindow.h>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLContext>
#include <QString>
#include <iostream>
#include <QTimer>
class OpenGlVideoQtQuickRenderer : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
public:
OpenGlVideoQtQuickRenderer() {
}
~OpenGlVideoQtQuickRenderer();
QMatrix4x4 qQuickVideoMatrix;
public slots:
void render();
private:
QOpenGLShaderProgram* program;
GLuint unis[3] = {0};
GLuint texs[3] = {0};
unsigned char *datas[3] = { 0 };
bool firstRun = true;
//TODO: make this variable according to video data
int width = 1920;
int height = 1080;
};
class OpenGlVideoQtQuick : public QQuickItem
{
Q_OBJECT
public:
OpenGlVideoQtQuick();
QMatrix4x4 getModelMatrix();
private slots:
void handleWindowChanged(QQuickWindow *win);
public slots:
void sync();
void update();//Updates the window
private:
OpenGlVideoQtQuickRenderer *openGlVideoQtQuickRenderer;
};
#endif // OpenGlVideoQtQuick_H
main.qml:
import QtQuick 2.0
import OpenGLComponents 1.0
Item {
width: 1280
height: 720
OpenGlVideoQtQuick {
width: 640
height: 480
}
}