如何使OpenGL视频具有与QQuickItem相同的大小和位置? [英] How to make my OpenGL video have the same size and position of my QQuickItem?

查看:144
本文介绍了如何使OpenGL视频具有与QQuickItem相同的大小和位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是我的最新问题:我的OpenGL QQuickItem不会具有我想要的大小,我现在正在尝试,而不是为我的OpenGL视频设置一个任意大小,以使其适合我的QQuickItem.

Following my latest question: My OpenGL QQuickItem won't have the size I want, I'm now trying,, instead of having an arbitrary size for my OpenGL video, to fit it inside my QQuickItem.

我听说QQuickItem::transform()会给我一个变换矩阵的列表.我假设,该列表包含达到我的QQuickItem的大小和位置的平方所需的所有转换. <<<<这是真的?如果是这样,那么转换是从什么坐标和视口尺寸开始的?

I've heard that QQuickItem::transform() will give me a list of transformation matrices. I'm assuming that this list contains all the transformations needed to arrive at a square the size and position of my QQuickItem. <<<< Is this true? If so, the transformations are from what coordinates and viewport dimensions?

鉴于上述事实,我制作了以下最小可验证和可编译的示例,试图使绿屏适合我的QQuickItem的大小.但是目前,它只占用整个屏幕.

Given that as true, I've made the following minimal verifiable and compilable example that tries to make the green screen fit into the size of my QQuickItem. But currently, it just takes the entire screen.

我使用了可以在下面找到的函数getModelMatrix()来获取所有转换并从中生成一个矩阵.然后,通过

I used the function getModelMatrix() that you can find below, to get all the transformations and make a matrix out of it. Then I apply these transformations to my vertex shader by doing

gl_Position = u_transform * vertexIn;

正如我所说,结果是绿色屏幕.但是,它具有与窗口相同的尺寸,而不是main.qml

As I said, the result is a green screen. However, it has the same dimensions of my window, instead of having the dimensions 640x480 and x,y=0, as specified in main.qml

您可以在此处找到一个最小的可编译且可验证的示例: https://github.com/lucaszanella/openglqtquickexample/tree/88fe0092d663dd92c551c72acccd0bf058fe7e5b

You can find a minimal compilable and verifiable example here: 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

    }
}

推荐答案

从您的问题和代码中,您并不清楚您正在期待"什么,但是我确实看到了一些可能对您有所帮助的问题:

From your question and your code it is a little unclear what you were "expecting" to see but I do see a few issues which might help you:

  1. 我认为您的渲染循环实际上没有被调用.您必须在构造函数中执行此操作:setFlag(ItemHasContents);

确保您确实将某些纹理/视频数据传递到了glTexImage2D()调用中,否则会得到一些垃圾(随机的绿色垃圾?)

Make sure you do pass some texture/video data into your glTexImage2D() calls otherwise you will get some garbage (random green garbage?)

您可能想看看QQuickItem::widthChangedQQuickItem::heightChanged信号

请确保在调试时同时具有glViewport()glClear()调用以避免混淆-您可以稍后在不再需要它们时将其删除

Make sure you have that glViewport() as well as glClear() calls when debugging to avoid confusions - you can delete them later when you don't need them anymore

这篇关于如何使OpenGL视频具有与QQuickItem相同的大小和位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆