Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在Qt-OpenGL中使用PBO_C++_Qt_Opengl - Fatal编程技术网

C++ 如何在Qt-OpenGL中使用PBO

C++ 如何在Qt-OpenGL中使用PBO,c++,qt,opengl,C++,Qt,Opengl,我正在尝试使用QOpenGLBuffer作为像素缓冲区对象。目标是显示高分辨率视频流(4K,60FPS),因此我需要良好的性能 因为我刚刚开始使用OpenGL,所以我首先尝试以最好的方式显示一个简单的2D纹理。我已经包括了VBO和VAO,下一步(如我所读)将是使用PBO以获得更好的性能 有关于PBO的教程,但有glGenBufferARB(),而没有QOpenGLBuffer 这是我的密码: glwidget.h #ifndef GLWIDGET_H #define GLWIDGET_H #i

我正在尝试使用QOpenGLBuffer作为像素缓冲区对象。目标是显示高分辨率视频流(4K,60FPS),因此我需要良好的性能

因为我刚刚开始使用OpenGL,所以我首先尝试以最好的方式显示一个简单的2D纹理。我已经包括了VBO和VAO,下一步(如我所读)将是使用PBO以获得更好的性能

有关于PBO的教程,但有glGenBufferARB(),而没有QOpenGLBuffer

这是我的密码:

glwidget.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QDebug>
#include <QOpenGLTexture>
#include <QOpenGLShader>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>




class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget *parent = 0);

    ~GLWidget();

    void initializeGL();
    void paintGL();
    void resizeGL(int w, int h);
    void LoadGLTextures();

private :

    QOpenGLShaderProgram *program;
    QOpenGLBuffer vbo;
    QOpenGLVertexArrayObject vao;
    GLuint tex;

    GLint vertexLocation;
    GLint texcoordLocation;

    int tailleVerticesBytes;
    int tailleCoordTexturesBytes;

    float vertices[8];
    float coordTexture[8];


public slots:



private slots:



};

#endif // GLWIDGET_H
\ifndef GLWIDGET\u H
#定义glu\H
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
类GLWidget:公共QOpenGLWidget,受保护的QopenglFunction
{
Q_对象
公众:
显式GLWidget(QWidget*parent=0);
~GLWidget();
void initializeGL();
void paintGL();
无效尺寸(整数w,整数h);
void loadgl纹理();
私人:
QOpenGLShaderProgram*计划;
QOpenGLBuffer vbo;
QOpenGLVertexArrayObject vao;
胶合特克斯;
闪烁顶点定位;
闪烁定位;
int tailleVerticesBytes;
int tailleCoordTexturesBytes;
浮动顶点[8];
浮动坐标纹理[8];
公众时段:
专用插槽:
};
#endif//glu\H
glwidget.cpp

#ifndef BUFFER_OFFSET
#define BUFFER_OFFSET(offset) ((char*)NULL + (offset))

#include "glwidget.h"
#include <QElapsedTimer>


GLWidget::GLWidget(QWidget *parent) :
        QOpenGLWidget(parent)
{
    tailleVerticesBytes = 8*sizeof(float);
    tailleCoordTexturesBytes = 8*sizeof(float);
}

GLWidget::~GLWidget(){

    vao.destroy();
    vbo.destroy();
    delete program;
    glDeleteTextures(1, &tex);

}

void GLWidget::LoadGLTextures(){

    QImage img;

    if(!img.load("C:\\Users\\Adrien\\Desktop\\open3.bmp")){
        qDebug()<<"Image loading failed";
    }

    QImage t = (img.convertToFormat(QImage::Format_RGBA8888)).mirrored();

    glGenTextures(1, &tex);

    glBindTexture(GL_TEXTURE_2D, tex);

        glTexImage2D(GL_TEXTURE_2D, 0, 3, t.width(), t.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, t.bits());
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glBindTexture( GL_TEXTURE_2D, 0);



}

void GLWidget::initializeGL(){


    float verticesTmp[] = {-1.0,-1.0,  1.0,-1.0,  1.0,1.0,  -1.0,1.0};
    float coordTextureTmp[] = {0.0,0.0,  1.0,0.0,  1.0,1.0,  0.0,1.0};

    for(int i = 0; i<8; i++){
        vertices[i] = verticesTmp[i];
        coordTexture[i] = coordTextureTmp[i];
    }

    initializeOpenGLFunctions();
    glClear(GL_COLOR_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    LoadGLTextures();

    //Shader setup
    QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    const char *vsrc =
        "#version 150 core\n"
        "in vec2 in_Vertex;\n"
        "in vec2 vertTexCoord;\n"
        "out vec2 fragTexCoord;\n"
        "void main(void)\n"
        "{\n"
        "    gl_Position = vec4(in_Vertex, 0.0, 1.0);\n"
        "    fragTexCoord = vertTexCoord;\n"
        "}\n";
    vshader->compileSourceCode(vsrc);

    QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    const char *fsrc =
            "#version 150 core\n"
            "uniform sampler2D tex;\n"
            "in vec2 fragTexCoord;\n"
            "void main(void)\n"
            "{\n"
            "    gl_FragColor = texture2D(tex,fragTexCoord);\n"
            "}\n";
    fshader->compileSourceCode(fsrc);

    program = new QOpenGLShaderProgram;
    program->addShader(vshader);
    program->addShader(fshader);
    program->link();
    program->bind();
    glActiveTexture(GL_TEXTURE0);
    program->setUniformValue("tex", 0);

    vertexLocation = glGetAttribLocation(program->programId(), "in_Vertex");
    texcoordLocation = glGetAttribLocation(program->programId(), "vertTexCoord");

    //VAO setup
    vao.create();
    vao.bind();

    //VBO setup
    vbo.create();
    vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);
    vbo.bind();
    vbo.allocate(tailleVerticesBytes + tailleCoordTexturesBytes);
    vbo.write(0, vertices, tailleVerticesBytes);
    vbo.write(tailleVerticesBytes, coordTexture, tailleCoordTexturesBytes);

    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 2);
    program->enableAttributeArray(texcoordLocation);
    program->setAttributeBuffer(texcoordLocation, GL_FLOAT, tailleVerticesBytes, 2);

    vbo.release();
    vao.release();
    program->release();



}

void GLWidget::paintGL(){

    glClear(GL_COLOR_BUFFER_BIT);

    program->bind();
    {
        vao.bind();

            glBindTexture(GL_TEXTURE_2D, tex);

                glDrawArrays(GL_QUADS, 0, 4);

            glBindTexture(GL_TEXTURE_2D, 0);

        vao.release();
    }
    program->release();

}

void GLWidget::resizeGL(int w, int h){

    glViewport(0, 0, (GLint)w, (GLint)h);

}



#endif
\ifndef缓冲区偏移量
#定义缓冲区偏移量(偏移量)((字符*)NULL+(偏移量))
#包括“glwidget.h”
#包括
GLWidget::GLWidget(QWidget*父项):
QOpenGLWidget(家长)
{
tailleVerticesBytes=8*sizeof(浮动);
tailleCoordTextureBytes=8*sizeof(浮点);
}
GLWidget::~GLWidget(){
破坏;
vbo.destroy();
删除程序;
gldelete纹理(1和tex);
}
void GLWidget::LoadGLTextures(){
QImage img;
如果(!img.load(“C:\\Users\\Adrien\\Desktop\\open3.bmp”)){
qDebug()添加着色器(vshader);
程序->添加着色器(fshader);
程序->链接();
程序->绑定();
玻璃纹理(GL_纹理0);
程序->设置统一值(“tex”,0);
vertexLocation=GLGetAttriblLocation(程序->程序ID(),“在顶点中”);
texcoordLocation=GLGetAttriblLocation(程序->程序ID(),“vertTexCoord”);
//VAO设置
创建();
vao.bind();
//VBO设置
vbo.create();
vbo.setUsagePattern(QopengelBuffer::StaticDraw);
vbo.bind();
vbo.allocate(tailleVerticesBytes+tailleCoordTexturesBytes);
vbo.write(0,顶点,tailleVerticesBytes);
vbo.write(tailleVerticesBytes、coordTexture、tailleCoordTexturesBytes);
程序->启用属性阵列(顶点位置);
program->setAttributeBuffer(顶点位置,GL_浮点,0,2);
程序->启用属性阵列(texcoordLocation);
程序->设置属性缓冲(texcoordLocation、GL_FLOAT、tailleVerticesBytes,2);
vbo.release();
vao.release();
程序->发布();
}
void GLWidget::paintGL(){
glClear(GLU颜色缓冲位);
程序->绑定();
{
vao.bind();
glBindTexture(GL_TEXTURE_2D,tex);
gldrawArray(GL_四边形,0,4);
glBindTexture(GL_TEXTURE_2D,0);
vao.release();
}
程序->发布();
}
void GLWidget::resizeGL(int w,int h){
glViewport(0,0,(闪烁)w,(闪烁)h);
}
#恩迪夫
那么,基本上,我该如何在代码中使用PBO呢

首先要做的是在指定类型(QOpenGLBuffer::PixelUnpupBuffer)的同时创建一个QOpenGLBuffer对象,然后我想我需要将像素上传到缓冲区,最后使用它而不是GLTEXAGE2D?这只是一个全局想法,我不知道如何做

谢谢

目标是显示高分辨率视频流(4K,60FPS),因此我需要良好的性能

唯一正确的方法是使用一些加速的表示API(与OpenGL无关)

如果你想坚持使用OpenGL,你至少需要让GPU进行视频解码并上传到纹理中。如何做到这一点取决于你的操作系统和GPU。例如,在Linux和使用NVIDIA时,你可以使用加速解码和使用解码帧填充纹理

如果你仍然想使用像素解包缓冲区对象(PUBO;你正在上传到GL=>这是一个解包),那么几乎没有什么神奇的效果。创建一个:

QOpenGLBuffer *pubo = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pubo->create();
然后用框架的数据填充它:

pubo->bind();
pubo->allocate(...);  // or, if already allocated, also write/map
现在PUBO的效果是,如果绑定了,某些调用将改变语义,从PUBO而不是用户内存读取数据。值得注意的是,上传纹理数据的调用。因此,如果您有纹理(并且应该使用QOpenGLTexture,它使用不可变存储,而不是手动调用
glTexImage
),你可以:

pubo->bind();
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 
             level, 
             internalFormat,
             width,
             heigth,
             border,
             externalFormat,
             type,
             data);
由于存在PUBO绑定,最后一个参数(
data
)改变了语义:它不再是指向客户端内存的指针,而是指向当前绑定的pixel unpack buffer对象的字节偏移量。因此,如果纹理数据从偏移量0开始进入缓冲区,则需要将0传递到那里(或者实际上,
(const GLvoid*)0
),否则需要相应调整

现在您可以发布pubo:

pubo->release();
然后像往常一样在着色器中使用纹理,一切都会很好


除非您直接使用纹理,否则不会获得任何性能改进!此复杂设置的全部要点是允许GL异步传输图像数据,同时渲染上一帧中上载的数据。如果您立即使用图像数据,GL需要同步整个管道,以等待图像数据上载到GPU

因此,此场景中的典型设置是以循环方式使用多个Pubo。例如,如果您有两个Pubo(在ping poing中),您可以在一个PBO中上载数据,并使用前一个PBO填充和绘制纹理。这应该为GL实际操作争取“足够的时间”