QOpenGLWidget 绘制对象

Posted

技术标签:

【中文标题】QOpenGLWidget 绘制对象【英文标题】:QOpenGLWidget draw object [closed] 【发布时间】:2015-11-17 11:50:56 【问题描述】:

我已经问过一个关于 QOpenglWidget here 的问题。 在我的最后一个问题中,我只是以错误的方式调用了 shaderid。 现在我正在尝试从一个对象加载我的顶点。 我编写了一个加载器来加载顶点、纹理坐标、法线和索引。我已经用原生 openGL 编写了这段代码并检查了输出。顶点等与我的 Qt 代码中的匹配。

唯一的问题是我无法让 paintGL() 方法绘制我的对象,它应该是一个简单的立方体。

--Main.cpp

    #include <QApplication>
#include <QLabel>
#include <QSurfaceFormat>

#ifndef QT_NO_OPENGL
#include "mainwidget.h"
#endif

int main(int argc, char *argv[])

    QApplication app(argc, argv);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    QSurfaceFormat::setDefaultFormat(format);

    app.setApplicationName("MainWidget");

#ifndef QT_NO_OPENGL
    MainWidget widget;
    widget.resize(800, 600);
    widget.show();
#else
    QLabel note("OpenGL Support required");
    note.show();
#endif
    return app.exec();

--MainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QVector2D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QOpenGLVertexArrayObject>
#include <QVector>
#include "geometryengine.h"


class GeometryEngine;
class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions

    Q_OBJECT
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();
protected:
    void initializeGL()Q_DECL_OVERRIDE;
    void resizeGL(int w, int h)Q_DECL_OVERRIDE;
    void paintGL()Q_DECL_OVERRIDE;

    void initShaders();
private:
    QOpenGLShaderProgram program;
    GeometryEngine *geometries;

;

#endif // MAINWIDGET_H

--MainWidget.cpp

#include "mainwidget.h"
#include <iostream>


extern QVector<QVector3D> m_vertices;
extern QVector<QVector2D> m_uvs;
extern QVector<QVector3D> m_normals;

extern QVector<QVector3D> m_indexed_vertices;
extern QVector<QVector2D> m_indexed_uvs;
extern QVector<QVector3D> m_indexed_normals;
extern QVector<unsigned short> m_indices;

MainWidget::MainWidget(QWidget *parent):QOpenGLWidget(parent), geometries(0)



MainWidget::~MainWidget()
    makeCurrent();
    delete geometries;
    doneCurrent();


void MainWidget::initializeGL()
    initializeOpenGLFunctions();
    glClearColor(0, 0, 0.4f, 0);
    glEnable(GL_DEPTH_TEST);
    initShaders();

    geometries = new GeometryEngine;
    for(auto i : m_indexed_vertices)
            std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            //std::cout << i << " " << std::endl;
        


void MainWidget::resizeGL(int w, int h)



void MainWidget::paintGL()
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /*for(auto i : m_indices)
            //std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            std::cout << i << " " << std::endl;
        */
    geometries->drawGeometry(&program, m_indices);



void MainWidget::initShaders()
    // Compile vertex shader
    if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, "vertex.vert"))
        close();

    // Compile fragment shader
    if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, "fragment.frag"))
        close();

    // Link shader pipeline
    if (!program.link())
        close();

    // Bind shader pipeline for use
    if (!program.bind())
        close();

--GeometryEngine.h

#ifndef GEOMETRYENGINE_H
#define GEOMETRYENGINE_H
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include "mainwidget.h"


class GeometryEngine : protected QOpenGLFunctions

public:
    GeometryEngine();
    virtual ~GeometryEngine();

    void drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices);


private:
    void initGeometry(const char *path, QVector<QVector3D> &vert, QVector<QVector2D> &uv, QVector<QVector3D> &norm,QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices,
    QVector<QVector2D> &indexed_uvs,
    QVector<QVector3D> &indexed_normals);

    QOpenGLBuffer arrayBuf;
    QOpenGLBuffer indexBuf;
    QOpenGLVertexArrayObject vertexArrayID;

;

#endif // GEOMETRYENGINE_H

--GeometryEngine.cpp

#include "geometryengine.h"
#include "mainwidget.h"
#include "loadobj.h"
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <string>
#include <iostream>


QVector<QVector3D> m_vertices;
QVector<QVector2D> m_uvs;
QVector<QVector3D> m_normals;

QVector<QVector3D> m_indexed_vertices;
QVector<QVector2D> m_indexed_uvs;
QVector<QVector3D> m_indexed_normals;
QVector<unsigned short> m_indices;

GeometryEngine::GeometryEngine() : indexBuf(QOpenGLBuffer::IndexBuffer)



    initializeOpenGLFunctions();
    vertexArrayID.create();
    vertexArrayID.bind();
    //generate vbos
    arrayBuf.create();
    indexBuf.create();


    initGeometry("cube.obj", m_vertices, m_uvs, m_normals, m_indices, m_indexed_vertices, m_indexed_uvs, m_indexed_normals);



GeometryEngine::~GeometryEngine()
    arrayBuf.destroy();
    indexBuf.destroy();
    vertexArrayID.destroy();

void GeometryEngine::initGeometry(const char *path,QVector<QVector3D> &vertices, QVector<QVector2D> &uvs, QVector<QVector3D> &normals, QVector<unsigned short> &indices,  QVector<QVector3D> &indexed_vertices, QVector<QVector2D> &indexed_uvs, QVector<QVector3D> &indexed_normals )
    bool res = loadObj(path, vertices, uvs, normals);
    vboIndexer(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals );
    /*for(auto i : indices)
            //std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            std::cout << i << " " << std::endl;
        */
    arrayBuf.bind();
    arrayBuf.allocate(&indexed_vertices, indexed_vertices.size() * sizeof(QVector3D));

    indexBuf.bind();
    indexBuf.allocate(&indices, indices.size() * sizeof(unsigned short));



void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices)
    arrayBuf.bind();
    indexBuf.bind();

    int vertexLocation = program->attributeLocation("vertex");
    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(GLfloat));

    //glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_SHORT, 0);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(0);

--vertex.vert

#version 330

layout(location = 0) in vec3 vertex;

void main()
    gl_Position = vec4(vertex, 1.0);

--fragment.frag

#version 330

out vec3 color;
void main()
    color = vec3(1,0,0);

我不知道我是否弄乱了一些 QOpenGL 代码,或者是因为我将顶点存储在 QVector 而不是数组中。作为引导,我使用了 Qt 中的立方体示例,您可以在代码相似性中看到。

【问题讨论】:

没人知道吗? 【参考方案1】:

好的问题解决了。

原生 openGL 能够从 Vectors 中绘制数据,而 QopenGLWidget 只有在数据存储在数组中时才能绘制。即使数组包含 Qvector3D 数据。

如果我错了,请纠正我。因为这对我来说有点可疑。

【讨论】:

以上是关于QOpenGLWidget 绘制对象的主要内容,如果未能解决你的问题,请参考以下文章

QOpenGLWidget不绘制数组

Qt音视频开发24-视频显示QOpenGLWidget方式(占用GPU)

在QOpenGLWidget上使用Qt5小部件而不重写?

QOpenGLWidget,QOpenGLWindow的问题

在qt的QOpenGLWidget开启opengl的抗锯齿

Qt OpenGL (QOpenGLWidget) - 简单三角形