我的OpenGL QQuickItem没有我想要的大小 [英] My OpenGL QQuickItem won't have the size I want

查看:134
本文介绍了我的OpenGL QQuickItem没有我想要的大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Qtquick上使用OpenGL进行绘图,无论我在QML上的OpenGlVideoQtQuick上放置多大的尺寸,它始终占据窗口的整个空间.我希望能够控制它的大小.

I'm drawing with OpenGL on Qtquick and no matter what size I put on my OpenGlVideoQtQuick on QML, it always occupies the entire space of the window. I want to be able to control its size.

我创建了这个最小的示例,该示例使用OpenGL绘制了绿色屏幕.我应该能够控制QQuickItem的大小,从而控制绿色屏幕的大小,例如占据屏幕的1/4.

I created this minimal example which draws a green screen with OpenGL. I should be able to control the size of QQuickItem and thus control the size of the green screen to occupy, for example, 1/4 of the screen.

您可以看到我什至尝试了QQuickItem上的setWidthsetHeight方法(并添加了注释).这行不通.

You can see that I even tried (and commented) the setWidth and setHeight methods on the QQuickItem. It won't work.

您可以在此处看到一个最小的可编译示例: https://github.com/lucaszanella/openglqtquickexample/tree/4de3ec1535eb40c31788512a027c1e86f76d4090

You can see a minimal working and compilable example here: https://github.com/lucaszanella/openglqtquickexample/tree/4de3ec1535eb40c31788512a027c1e86f76d4090

如何控制QQuickItem的大小?

main.qml:

import QtQuick 2.0
import OpenGLComponents 1.0
Item {
    width: 1280
    height: 720
    OpenGlVideoQtQuick {
        width: 640
        height: 480

    }
}

main.cpp:

#include <iostream>
#include <QApplication>
#include <QMediaPlayer>
#include <QPushButton> 
#include <QGuiApplication>

#include <QtQuick/QQuickView>

#include "OpenGlVideoQtQuick.h"

int main(int argc, char **argv)
{
    QGuiApplication app(argc, argv);
    QCoreApplication::addLibraryPath("./");
    qmlRegisterType<OpenGlVideoQtQuick>("OpenGLComponents", 1, 0, "OpenGlVideoQtQuick");

    QQuickView view;
    view.setResizeMode(QQuickView::SizeRootObjectToView);
    view.setSource(QUrl("qrc:/main.qml"));
    view.show();

    return app.exec();
}

OpenGlVideoQtQuick.cpp:

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;
    void main(void)
    {
        gl_Position = 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();
    //setWidth(640);
    //setHeight(480);
    //width=640
    //height=480
}

void OpenGlVideoQtQuick::handleWindowChanged(QQuickWindow *win)
{
    if (win) {
        connect(win, &QQuickWindow::beforeSynchronizing, this, &OpenGlVideoQtQuick::sync, Qt::DirectConnection);
        win->setClearBeforeRendering(false);
    }
}

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);
    }
}

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();

    //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();

}

推荐答案

您必须在顶点着色器中缩放顶点坐标.这可以通过4x4矩阵(mat4)完成. 声明类型为mat4统一变量并转换(乘)在将其分配给剪辑空间位置gl_Position之前,由矩阵确定顶点坐标:

You have to scale the vertex coordinates in the vertex shader. This can be done by 4x4 matrix (mat4). Declare a uniform variable of type mat4 and transform (multiply) the vertex coordainte by the matrix, before it is assigned to the clip space position gl_Position:

attribute vec4 vertexIn;
attribute vec2 textureIn;

varying vec2 textureOut;

uniform mat4 u_transform;   

void main(void)
{
    gl_Position = u_transform * vertexIn;
    textureOut = textureIn;
}   

必须在程序中通过 QOpenGLShaderProgram::setUniformValue() .值的类型必须为 QMatrix4x4 .

The value of the uniform has to be set in the program, by QOpenGLShaderProgram::setUniformValue(). The type of the value has to be QMatrix4x4.

例如

program->bind();

QMatrix4x4 transform;
transform.setToIdentity();
transform.scale(0.25, 0.25);

program->setUniformValue("u_transform", transform);

当然也可以使用glm::mat4.在这种情况下,必须通过 glUniformMatrix4fv :

Of course it is possible to use glm::mat4, too. It this case the value of the uniform has to be set by glUniformMatrix4fv:

GLint transformLoc = program->uniformLocation("u_transform");

program->bind();

glm::mat4 transform(1.0f);
transform = glm::scale(transform, glm::vec3(0.25f, 0.25f, 1.0f));
glUniformMatrix4fv(transformLoc , 1, GL_FALSE, glm::value_ptr(transform ));

这篇关于我的OpenGL QQuickItem没有我想要的大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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