首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在QOpenGLWidget中使用OpenGL

在QOpenGLWidget中使用OpenGL
EN

Stack Overflow用户
提问于 2019-03-12 04:59:03
回答 1查看 0关注 0票数 0

我正在尝试在QMainWindow中使用QOpenGLWidget来绘制三角形。不幸的是它没有渲染。我想使用索引绘图。

我有以下代码:

代码语言:javascript
复制
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
#include "model.h"

包括所有necesseties。

代码语言:javascript
复制
class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{
    Q_OBJECT

public:
    OGLWidget(const QString* vshadersrc,const QString* fshadersrc, QWidget *parent = 0);
    ~OGLWidget();
public slots:
    void cleanup();

覆盖方法initializeGL,paintGL和resizeGL。除了鼠标事件,它们现在也是空的。

代码语言:javascript
复制
protected:
    void initializeGL() override;
    void paintGL() override;
    void resizeGL(int w, int h) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;

private:

着色器程序的句柄

代码语言:javascript
复制
    QOpenGLShaderProgram *shaderprogram;

保存着色器源

代码语言:javascript
复制
    const  QString* vshadersrc;
    const  QString* fshadersrc;

3个矩阵,投影,视图(相机)和模型。

代码语言:javascript
复制
    QMatrix4x4 mproj;
    QMatrix4x4 mcamera;
    QMatrix4x4 mmodel;

VertexArrayObject和VertexBufferObject + IndexBufferObject。

代码语言:javascript
复制
    QOpenGLVertexArrayObject vao;
    QOpenGLBuffer vbo;
    QOpenGLBuffer ibo;
};

这是实现文件:

代码语言:javascript
复制
#include "oglwidget.h"

OGLWidget::OGLWidget(const QString* vsrc
                 ,const  QString* fsrc, QWidget *parent) :      QOpenGLWidget(parent)
{
    vshadersrc = vsrc;
    fshadersrc = fsrc;
    hasModel = false;

我将surfaceFormat设置为请求OpenGL 4.5 Core。

代码语言:javascript
复制
    QSurfaceFormat surfaceFormat = this->format();
    surfaceFormat.setVersion(4,5);
    surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
    this->setFormat(surfaceFormat);
}

OGLWidget::~OGLWidget()
{
    cleanup();
}

void OGLWidget::initializeGL()
{

这些是我的立方体的索引和顶点。

代码语言:javascript
复制
     const std::vector<GLushort> indices = {// front
                        0, 1, 2,
                        2, 3, 0,
                        // top
                        1, 5, 6,
                        6, 2, 1,
                        // back
                        7, 6, 5,
                        5, 4, 7,
                        // bottom
                        4, 0, 3,
                        3, 7, 4,
                        // left
                        4, 5, 1,
                        1, 0, 4,
                        // right
                        3, 2, 6,
                        6, 7, 3};

    float width, height, depth;
    width = height = depth = 3;
    const std::vector<QVector3D> vertices = {
        // front
        QVector3D(-width / 2.0f, -height / 2.0f,  depth / 2.0f),
        QVector3D(width / 2.0f, -height / 2.0f,  depth / 2.0f),
        QVector3D(width / 2.0f,  height / 2.0f,  depth / 2.0f),
        QVector3D(-width / 2.0f,  height / 2.0f,  depth / 2.0f),
        // back
        QVector3D(-width / 2.0f, -height / 2.0f, -depth / 2.0f),
        QVector3D(width / 2.0f, -height / 2.0f, -depth / 2.0f),
        QVector3D(width / 2.0f,  height / 2.0f, -depth / 2.0f),
        QVector3D(-width / 2.0f,  height / 2.0f, -depth / 2.0f)
    };

    connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OGLWidget::cleanup);
    initializeOpenGLFunctions();
    glClearColor(0, 0, 0, 1);

着色器程序汇编在一起以形成源代码

代码语言:javascript
复制
    shaderprogram = new QOpenGLShaderProgram();
    shaderprogram->addShaderFromSourceFile(QOpenGLShader::Vertex, *vshadersrc);
    shaderprogram->addShaderFromSourceFile(QOpenGLShader::Fragment, *fshadersrc);
    shaderprogram->bindAttributeLocation("position", 0);
    shaderprogram->link();

    shaderprogram->bind();

我创建了VAO并通过Qt类绑定它

代码语言:javascript
复制
    vao.create();
    QOpenGLVertexArrayObject::Binder vaoBinder(&vao);

    QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();

创建VBO并分配顶点数据并启用vertexattrib。

代码语言:javascript
复制
    vbo.create();
    vbo.bind();
    vbo.allocate(vertices.data(), vertices.size() * sizeof(QVector3D));
    vbo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
    f->glEnableVertexAttribArray(0);
    f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    vbo.release();

创建IBO并分配索引数据。

代码语言:javascript
复制
    ibo.create();
    ibo.bind();
    ibo.allocate(indices.data(), indices.size() * sizeof(GLushort));
    ibo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
    ibo.release();

然后我将模型和相机矩阵设置为I-Matrix并将相机移回一点。

代码语言:javascript
复制
    // move back
    mcamera.setToIdentity();
    mcamera.translate(0, 0, -5);

    mmodel.setToIdentity();

    shaderprogram->release();
}

void OGLWidget::cleanup()
{
    if(shaderprogram == nullptr)
        return;

    makeCurrent();
    delete shaderprogram;
    shaderprogram = 0;
    doneCurrent();
}

void OGLWidget::paintGL()
{ 

清除窗口并启用Faceculling和Depth Test。

代码语言:javascript
复制
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

使用Shaderprogram并绑定VAO。

代码语言:javascript
复制
    shaderprogram->bind();
    QOpenGLVertexArrayObject::Binder vaoBinder(&vao);

绑定统一的ViewProjection Matrix和Model Matrix。

代码语言:javascript
复制
    shaderprogram->setUniformValue(shaderprogram->uniformLocation("viewProjMatrix"), mproj * mcamera);
    shaderprogram->setUniformValue(shaderprogram->uniformLocation("modelMatrix"), mmodel);

最后调用draw命令并释放shaderprogam。

代码语言:javascript
复制
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
    shaderprogram->release();
}


Initializing the Projectionmatrix.

void OGLWidget::resizeGL(int w, int h)
{
    mproj.setToIdentity();
    mproj.perspective(45.f, float(w) / h, 0.01f, 1000.0f);
}
void OGLWidget::mousePressEvent(QMouseEvent *event){}
void OGLWidget::mouseMoveEvent(QMouseEvent *event){}

着色器程序相当简单。对于顶点着色器,我有:

代码语言:javascript
复制
#version 450

layout (location = 0) in vec3 position;
out vec4 color;

uniform mat4 modelMatrix;
uniform mat4 viewProjMatrix;

void main()
{
    gl_Position = viewProjMatrix * modelMatrix * vec4(position, 1.0); 
    color = vec4(1.0, 1.0, 0.0, 1.0);
}

至于片段着色器,我只是传递颜色:

代码语言:javascript
复制
#version 450

out vec4 FragColor;
in vec4 color;  

void main()
{
    FragColor = color;
}  

有谁知道什么可能出错?QOpenGLWidget只是保持清晰的颜色,因为没有画出任何东西。编辑:我的MainWindow实现如下:

代码语言:javascript
复制
#include "mainwindow.h"

MainWindow::MainWindow(int height, int width, QString title)
{
   // create layout
   QHBoxLayout *layout = new QHBoxLayout();

// add openglwidegts for rendering
   model = new OGLWidget(new QString("./shader/shader.vert"), new QString("./shader/shader.frag"));
    //planar = new OGLWidget(new QString("./shader/shader.vert"), new QString("./shader/shader.frag"));
    model->setFixedSize(height / 2, width / 2);
    //planar->setFixedSize(height / 2, width / 2);
    layout->addWidget(model);
    //layout->addWidget(planar);

    // Add action to load a model
    QAction *loadFile = this->menuBar()->addMenu("File")->addAction("Load Model");
    QObject::connect(loadFile, &QAction::triggered, this, &MainWindow::loadModel);

    // setup window
    this->setCentralWidget(new QWidget);
    this->centralWidget()->setLayout(layout);
    this->setWindowTitle(title);
    this->setWindowModality(Qt::ApplicationModal);
}

MainWindow::~MainWindow()
{ 
}

void MainWindow::loadModel()
{
    QString filename = QFileDialog::getOpenFileName(this, "Choose 3D Model",         QDir::currentPath(), "OFF Files (*.off)");
    if(filename.isNull())
        return;

    Model* model = new Model(filename.toLocal8Bit().data());
}
EN

回答 1

Stack Overflow用户

发布于 2019-03-12 14:18:28

顶点缓冲区QOpenGLBuffer::VertexBuffer的类型必须是,但索引缓冲区的类型必须是QOpenGLBuffer::IndexBuffer

代码语言:javascript
复制
OGLWidget::OGLWidget(const QString* vsrc,const  QString* fsrc, QWidget *parent) 
    : QOpenGLWidget(parent)
    , vbo(QOpenGLBuffer::VertexBuffer) // <--- vertex buffer
    , ibo(QOpenGLBuffer::IndexBuffer)  // <--- index buffer
{
    // [...]
}

索引缓冲区的名称(值)在顶点数组对象的状态向量中说明。绑定时(在绑定顶点数组对象之后)声明索引缓冲区:

vao.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&vao); // [...] ibo.create(); ibo.bind();

但是如果索引被释放(当绑定顶点数组对象时),则顶点数组对象与索引缓冲区的关联被破坏。 你要省略释放索引缓冲区:

ibo.allocate(indices.data(), indices.size() * sizeof(GLushort)); ibo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw); ibo.release();

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档