【问题标题】:What is the issue with this QOpenGLWidget?这个 QOpenGLWidget 有什么问题?
【发布时间】:2021-08-20 09:39:49
【问题描述】:

为什么/如何将顶点属性绑定到着色器? - 有例子,但从不解释。

如果我在 GLSL 位置 = 0 中允许顶点属性,是否还必须在代码中允许?

如何正确设置 Q-vertex 数组缓冲区/对象?

这个*奇怪的神器是从哪里来的?

*蓝色方块是用于显示 QPixmap 图像的标签。绿色的是继承自 QOpenGLWidget 的 1 个 GLWidget。如您所见,它还在左上角创建了一个奇怪的正方形。

绿色窗口应该在右下角显示一个红色三角形。

相关代码可能只有最后一段,GLWidget.h。

由于某种原因,paintGL() 也只运行了几次。 代码:

.pro:

QT       += core gui opengl

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11 console

LIBS += -lopengl32

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    GLWidget.h \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

主要:

#include <iostream>
#include <cstdlib>
#include "mainwindow.h"
#include <QApplication>
#include <QGLFormat>
#include <qimagereader.h>
#include "GLWidget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(3, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    //format.setSampleBuffers(true); - throws undefined
    QSurfaceFormat::setDefaultFormat(format);
    std::cout<<"\nContext set up!";

    MainWindow w;
    GLWidget g(&w);
    w.show();

    return a.exec();
}

主窗口.h

#include <QMainWindow>
#include <QPixmap>
#include <QDir>
#include <QFileDialog>
#include <QListWidgetItem>
#include <map>


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:

    void on_openButton_clicked();

    void on_closeButton_clicked();

    void on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);

private:
    Ui::MainWindow *ui;
    std::map<QString, QPixmap> pictures;
};
#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->label_pic->setStyleSheet("QLabel { background-color : blue; color: white;}");
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_openButton_clicked()
{
    QString file_name = "";
    file_name = QFileDialog::getOpenFileName(this, "Open a File", QDir::homePath());
    if(file_name == "") return;
    QPixmap map(file_name);

    ///chopping just the filename
    for(unsigned i = file_name.length()-1; i > 0; i--){
        if(file_name[i] == '/'){
            file_name = file_name.mid(i+1);
            break;
        }
    }
    ui->listWidget->addItem(file_name);
    pictures.insert(std::pair<QString, QPixmap>(file_name, map));
}



void MainWindow::on_closeButton_clicked()
{
    QString item = ui->listWidget->currentItem()->text();
    std::map<QString, QPixmap>::iterator It = pictures.find(item);

    if( It != pictures.end() ) pictures.erase( It );
    QList<QListWidgetItem*> items = ui->listWidget->selectedItems();
    foreach(QListWidgetItem * item, items)
    {
        delete ui->listWidget->takeItem(ui->listWidget->row(item));
    }
}


void MainWindow::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    QString item = ui->listWidget->currentItem()->text();
    ui->label_pic->setPixmap(pictures.at(item));
}

GLWidget.h

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QSurface>
#include <QWindow>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>            //for compiling
#include <QOpenGLShaderProgram>     //for link and use
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QMatrix>
#include <QGLFormat>

#include <iostream>
#include <cstdlib>

const QString vertex_src =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
    "gl_Position = vec4(aPos, 1.0);\n"
"}\n";

const QString fragment_src =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
    "FragColor = FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
"}\n";

const GLfloat vertices[] = {

    1.0f, 1.0f, -4.0f,
    -1.0f, -1.0f, -4.0f,
    1.0f, -1.0f, -4.0f,

    1.0f, 1.0f, 0.0f,
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,

    1.0f, 1.0f, 4.0f,
    -1.0f, -1.0f, 4.0f,
    1.0f, -1.0f, 4.0f

};

class GLWidget : public QOpenGLWidget
{
private:
        QOpenGLShader *fragmentShader;
        QOpenGLShader *vertexShader;
        QOpenGLShaderProgram *shaderProgram;
        QOpenGLFunctions_3_3_Core *f;
        //QOpenGLFunctions *f;
        QOpenGLVertexArrayObject VAO;
        QOpenGLBuffer VBO;

public:
    GLWidget(QWidget *parent = 0) : QOpenGLWidget(parent) {
        std::cout<<"\nGLWidget lives";
    }

protected:
    void initializeGL() override
    {
        connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);
        //initializeOpenGLFunctions<QT_OPENGL_3_3_FUNCTIONS>();
        //f = QOpenGLFunctions::initializeOpenGLFunctions();
        // Set up the rendering context, load shaders and other resources, etc.:

        //this->setFormat(QSurfaceFormat::defaultFormat());
        //f = QOpenGLContext::currentContext()->functions();
        f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
        f->glClearColor(0.0f, 0.2f, 0.0f, 1.0f);
        f->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        f->glDisable(GL_CULL_FACE);

        vertexShader = new QOpenGLShader ( QOpenGLShader :: Vertex );
        if (!vertexShader->compileSourceCode(vertex_src) ) {std::cout<<"\ncould not compile vertex shader"; exit(1);}

        fragmentShader = new QOpenGLShader( QOpenGLShader :: Fragment ) ;
        if (! fragmentShader->compileSourceCode(fragment_src) ) {std::cout<<"\ncould not compile fragment shader"; exit(1);}

        shaderProgram = new QOpenGLShaderProgram(QOpenGLContext::currentContext());
        shaderProgram->addShader( vertexShader );
        shaderProgram->addShader( fragmentShader );
        shaderProgram->link();
        //shaderProgram->create();
        shaderProgram->bind();

        shaderProgram->enableAttributeArray("aPos");
        shaderProgram->setAttributeArray("aPos", &vertices[0], 3, 0);

        /*
        VAO = new QOpenGLVertexArrayObject(this);
        VAO->create();
        VAO->bind();

        VBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        VBO->create();
        VBO->setUsagePattern(QOpenGLBuffer::StaticDraw);
        VBO->bind();
        VBO->allocate(&vertices[0], 9);
        m_funcs->glEnableVertexAttribArray(0);
        m_funcs->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3, (void*)0);
        shaderProgram->enableAttributeArray(0);
        shaderProgram->setAttributeBuffer("aPos", GL_FLOAT, 0, 3, 0);
          */

        VAO.create();
        if (VAO.isCreated()) VAO.bind();
        else {std::cout<<"\nCould not bind VAO"; exit(1);}

        VBO = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        VBO.create();
        VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
        if (VBO.isCreated()) VBO.bind();
        else {std::cout<<"\nCould not bind VBO"; exit(1);}
        VBO.allocate(&vertices[0], 9);

        f->glEnableVertexAttribArray(0);
        f->glVertexAttribPointer(0, 27 * sizeof(float), GL_FLOAT, GL_FALSE, 0, (void*)0);


    }

    void resizeGL(int w, int h) override
    {
        // Update projection matrix and other size related settings:
        // m_projection.setToIdentity();
        // m_projection.perspective(45.0f, w / float(h), 0.01f, 100.0f);
        glViewport( 0, 0, w, qMax( h, 1 ) );
    }

    void paintGL() override
    {
        //QOpenGLFunctions_3_3_Core *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
        // Draw the scene:
        std::cout<<"\npaint runs";
        f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebufferObject());
        f->glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        if(shaderProgram->bind()) {std::cout<<"\n\tshader bound";}

        if(VBO.bind()) {std::cout<<"\n\tVAO bound";}
        f->glDrawArrays(GL_TRIANGLES, 0, 9);
    }
public:
    void cleanup()
    {
        makeCurrent();
        delete vertexShader;
        delete fragmentShader;
        delete shaderProgram;
        VAO.destroy();
        VBO.destroy();
        doneCurrent();
    }

    ~GLWidget()
    {
        cleanup();
    }

};
#endif // GLWIDGET_H

(三角形顶点存在于 -1、0 和 1 Z 位置。我不想将它们绘制在视图窗格的后面。)

UI.xml

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>718</width>
    <height>472</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="label_pic">
    <property name="geometry">
     <rect>
      <x>170</x>
      <y>20</y>
      <width>211</width>
      <height>61</height>
     </rect>
    </property>
    <property name="maximumSize">
     <size>
      <width>501</width>
      <height>431</height>
     </size>
    </property>
    <property name="layoutDirection">
     <enum>Qt::LeftToRight</enum>
    </property>
    <property name="autoFillBackground">
     <bool>false</bool>
    </property>
    <property name="text">
     <string>Picture Goes Here (or not)</string>
    </property>
    <property name="alignment">
     <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
    </property>
   </widget>
   <widget class="QPushButton" name="openButton">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>20</y>
      <width>161</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Open File..</string>
    </property>
   </widget>
   <widget class="QPushButton" name="closeButton">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>430</y>
      <width>161</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>Close File</string>
    </property>
   </widget>
   <widget class="QListWidget" name="listWidget">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>50</y>
      <width>161</width>
      <height>371</height>
     </rect>
    </property>
   </widget>
   <widget class="GLWidget" name="openGLWidget">
    <property name="geometry">
     <rect>
      <x>310</x>
      <y>100</y>
      <width>281</width>
      <height>261</height>
     </rect>
    </property>
   </widget>
  </widget>
 </widget>
 <customwidgets>
  <customwidget>
   <class>GLWidget</class>
   <extends>QOpenGLWidget</extends>
   <header location="global">GLWidget.h</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

【问题讨论】:

  • 您不必在paintGl 中makeCurrent(),它已经完成了吗?除非您使用不同的程序集(在通道中进行渲染),否则每次重新绑定着色器也可能过多。大多数关于何时和为什么的知识来自 OpenGL 而不是来自 Qt。
  • @Swift-FridayPie 是的,我读到了。在这里做了很多事情只是为了看看它是否有效。您还可以看到一些注释掉的部分。这里尝试了许多排列。现在我只想看看我的三角形,不管效率如何
  • PaintGL 作为渲染过程的一部分被调用,但您通过 doneCurrent() 提前结束渲染过程。事实上,它的调用者调用了这些,但它不是递归的(即你不能“使当前”两次,然后“完成”两次)。它实际上是未定义的,因为正式的 OpenGL 上下文不再处于活动状态......并且您正在渲染到其他地方。如果您尝试在正常“更新”之外调用 OpenGL 函数,则通常使用该对,例如在事件处理程序中,以不推荐的方式呈现
  • @Swift-FridayPie 删除了它们,没有任何改变。感谢您的提示。
  • 我正在尝试重新创建,但缺少 .UI xml 会阻碍这一点。可以用最少的窗口设置重新创建它吗? (只是小部件,没有别的)

标签: c++ qt opengl


【解决方案1】:

第二个参数 f->glVertexAttribPointer(0, 27 * sizeof(float), GL_FLOAT, GL_FALSE, 0, (void*)0); 必须是组件的数量(值 1..4) 我做了一些小的改动,但是这段代码运行了,并产生了一个三角形。 承担不必要的包括。我不知道哪些是真正需要的。

#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLContext>
#include <QSurface>
#include <QWindow>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_3_3_Core>
#include <QOpenGLShader>            //for compiling
#include <QOpenGLShaderProgram>     //for link and use
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QMatrix>
#include <QGLFormat>

#include <iostream>
#include <cstdlib>

const QString vertex_src =
"#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
    "gl_Position = vec4(aPos, 1.0);\n"
"}\n";

const QString fragment_src =
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
    "FragColor = FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
"}\n";

const GLfloat vertices[] = {

    1.0f, 1.0f, -4.0f,
    -1.0f, -1.0f, -4.0f,
    1.0f, -1.0f, -4.0f,

    1.0f, 1.0f, 0.0f,
    -1.0f, -1.0f, 0.0f,
    1.0f, -1.0f, 0.0f,

    1.0f, 1.0f, 4.0f,
    -1.0f, -1.0f, 4.0f,
    1.0f, -1.0f, 4.0f

};

class GLWidget : public QOpenGLWidget
{
private:
        QOpenGLShader *fragmentShader;
        QOpenGLShader *vertexShader;
        QOpenGLShaderProgram *shaderProgram;
        QOpenGLFunctions_3_3_Core *f;
        //QOpenGLFunctions *f;
        QOpenGLVertexArrayObject VAO;
        QOpenGLBuffer VBO;

public:
    GLWidget(QWidget *parent = 0) : QOpenGLWidget(parent) {
        std::cout<<"\nGLWidget lives";
    }

protected:
    void initializeGL() override
    {
        connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);
        //f = new QOpenGLFunctions_3_3_Core();
        //f->initializeOpenGLFunctions(); "There is no need to call QAbstractOpenGLFunctions::initializeOpenGLFunctions() as long as versionFunctions context is current"
        f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
        f->glClearColor(0.0f, 0.2f, 0.0f, 1.0f);
        f->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
        f->glDisable(GL_CULL_FACE);

        vertexShader = new QOpenGLShader ( QOpenGLShader :: Vertex );
        if (!vertexShader->compileSourceCode(vertex_src) ) {std::cout<<"\ncould not compile vertex shader"; exit(1);}

        fragmentShader = new QOpenGLShader( QOpenGLShader :: Fragment ) ;
        if (! fragmentShader->compileSourceCode(fragment_src) ) {std::cout<<"\ncould not compile fragment shader"; exit(1);}

        shaderProgram = new QOpenGLShaderProgram(QOpenGLContext::currentContext());
        shaderProgram->addShader( vertexShader );
        shaderProgram->addShader( fragmentShader );
        shaderProgram->link();
        //shaderProgram->create(); no need, just gives back a program id.
        shaderProgram->bind();


        shaderProgram->setAttributeArray("aPos", &vertices[0], 3, 0);
        shaderProgram->enableAttributeArray("aPos");

        VAO.create();
        if (VAO.isCreated()) VAO.bind();
        else {std::cout<<"\nCould not bind VAO"; exit(1);}

        VBO = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        VBO.create();
        VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
        if (VBO.isCreated()) VBO.bind();
        else {std::cout<<"\nCould not bind VBO"; exit(1);}
        VBO.allocate(&vertices[0], 27 * sizeof(float));
        //VBO.allocate(&vertices[0], 27);

        f->glEnableVertexAttribArray(0);
        f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
        //f->glVertexAttribPointer(0, 27, GL_FLOAT, GL_FALSE, 0, (void*)0);

        std::cout<<"\nGL context version "<<QOpenGLContext::currentContext()->format().majorVersion();
        std::cout<<"."<<QOpenGLContext::currentContext()->format().minorVersion();
        std::cout<<"\nGL context profile "<<QOpenGLContext::currentContext()->format().profile();
        std::cout<<"\n\tis that Core? ";
        if(QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile) std::cout<<"True";
        else std::cout<<"False";

    }

    void resizeGL(int w, int h) override
    {
        // Update projection matrix and other size related settings:
        // m_projection.setToIdentity();
        // m_projection.perspective(45.0f, w / float(h), 0.01f, 100.0f);
        //glViewport( 0, 0, w, qMax( h, 1 ) );
        std::cout<<"\nResize called";
        glViewport( 0, 0, 800, 600 );
    }

    void paintGL() override
    {

        std::cout<<"\npaint runs";
        f->glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        if(shaderProgram->bind()) {std::cout<<"\n\tshader bound";}

        if(VBO.bind()) {std::cout<<"\n\tVAO bound";}
        f->glDrawArrays(GL_TRIANGLES, 0, 9);
        QOpenGLContext::currentContext()->swapBuffers(QOpenGLContext::currentContext()->surface());
    }
public:
    void cleanup()
    {
        makeCurrent();
        delete vertexShader;
        delete fragmentShader;
        delete shaderProgram;
        VAO.destroy();
        VBO.destroy();
        doneCurrent();
    }

    ~GLWidget()
    {
        cleanup();
    }

};

#endif // GLWIDGET_H

请注意,在 Qt 中,着色器还需要启用顶点属性,而不是原生实现。(?)

这是更新的主要内容,以防有人需要它

#include <iostream>
#include <cstdlib>
#include "mainwindow.h"
#include <QApplication>
#include <QGLFormat>
#include <qimagereader.h>
#include "GLWidget.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    format.setStencilBufferSize(8);
    format.setVersion(3, 3);
    format.setProfile(QSurfaceFormat::CoreProfile);
    //format.setSampleBuffers(true); - throws undefined
    QSurfaceFormat::setDefaultFormat(format);
    std::cout<<"\nContext set up!";

    MainWindow w;
    w.show();

    return a.exec();
}

另外请注意,我在 Qt 中启用了一个名为“在终端中运行”的设置,所以我有一个可见的控制台。这就是 cout-s 的去向。

【讨论】:

  • 啊,创建顺序很重要吗?我错过了那两条线。任意视口看起来很奇怪,但作为一个实验代码可能没问题。我倾向于从构建变换矩阵的框架开始,不习惯 Qt 的包装器。
  • 是的,ui.xml 已经过时了,因为我固定了视口的大小。我现在也在测试,如果有必要给着色器顶点属性。我通过在 AMD 驱动程序中重置我的着色器缓存来尝试这个,因为 OpenGL 倾向于记住设置。到目前为止似乎可以使用一个属性,默认情况下可能启用第 0 个属性。如果这个功能根本不是强制性的,我会感到非常惊讶。为什么我能做到这一点? QShaderProgram 的父级应该是什么?无处解释。 Qt 及其文档一团糟。
  • 似乎启用它不是问题,问题是缓冲区属性不是通过着色器控制器设置的。所以它被设置为glDrawArrays
【解决方案2】:

左上角的方块是您第一次渲染的小部件,当您在main() 中添加它时。当您手动添加它时,它的原点坐标默认为 (0,0)。绿色方块是第二个,在 UI 中创建,从 XML 定义编译出来的模板。

painGL() 在调用paintEvent() 时调用,可以通过调用update(0 手动触发或在Qt“感觉”需要更新小部件时触发(例如,在它们之外绘制了一些东西,调整了它们的大小等。 )。

Afaik,如果您重新绑定程序,您必须重新绑定所有内容。并且您的绑定和保持对象处于活动状态的顺序是特殊的.. 以及您显然会在没有投影矩阵的情况下超出裁剪空间。

我习惯的顺序是这样的

void initializeGL() override
{
    connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::cleanup);

    f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();
    f->glClearColor(0.0f, 0.2f, 0.0f, 1.0f);
    f->glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    f->glDisable(GL_CULL_FACE);

    vertexShader = new QOpenGLShader ( QOpenGLShader :: Vertex );
    if (!vertexShader->compileSourceCode(vertex_src) ) {std::cout<<"\ncould not compile vertex shader"; exit(1);}

    fragmentShader = new QOpenGLShader( QOpenGLShader :: Fragment ) ;
    if (! fragmentShader->compileSourceCode(fragment_src) ) {std::cout<<"\ncould not compile fragment shader"; exit(1);}

    shaderProgram = new QOpenGLShaderProgram(QOpenGLContext::currentContext());
    shaderProgram->addShader( vertexShader );
    shaderProgram->addShader( fragmentShader );
    shaderProgram->link();


    shaderProgram->bind();

    VAO.create();
    if (VAO.isCreated()) VAO.bind();
        else {std::cout<<"\nCould not bind VAO"; exit(1);}

    VBO = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
    VBO.create();
    if (VBO.isCreated()) VBO.bind();
       else {std::cout<<"\nCould not bind VBO"; exit(1);}
       VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
       VBO.allocate(&vertices[0], 9*3*sizeof(float));

       shaderProgram->setAttributeArray("aPos", &vertices[0], 3, 0);
       shaderProgram->enableAttributeArray("aPos");
       // either
       shaderProgram->setAttributeBuffer("aPos",GL_FLOAT,0,3,0);
       // or?
       // f->glEnableVertexAttribArray(0);
       // f->glVertexAttribPointer(0, 9, GL_FLOAT, GL_FALSE, 0, (void*)0);
    VAO.release();

    // unbind when VAO is inactive.
    shaderProgram->disableAttributeArray("aPos");
    VBO.release();

    shaderProgram->release();

    std::cout<<"\nGL context version "<<QOpenGLContext::currentContext()->format().majorVersion();
            std::cout<<"."<<QOpenGLContext::currentContext()->format().minorVersion();
            std::cout<<"\nGL context profile "<<QOpenGLContext::currentContext()->format().profile();
            std::cout<<"\n\tis that Core? ";
            if(QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile) std::cout<<"True";
            else std::cout<<"False";
}


void paintGL() override
{
    // Draw the scene:
    std::cout<<"\npaint runs";

    f->glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

    shaderProgram->bind();
    VAO.bind();

    f->glDrawArrays(GL_TRIANGLES, 0, 9);

    VAO.release();
    shaderProgram->release();
}

【讨论】:

  • 没错。我删除了手册,工件不见了。请扩展此答案以使三角形可见:3。
  • paintGL 至少运行了 1 次,但仍然没有任何可见的东西。感谢您澄清这一点,将 update() 放入循环将是另一个话题。
  • @BenceBlázsovics 也许在 timerEvent 中做到这一点。
猜你喜欢
  • 2012-05-26
  • 2015-09-23
  • 2021-02-27
  • 2012-03-10
  • 2010-11-01
  • 2011-08-26
  • 2020-04-16
  • 1970-01-01
  • 2016-06-28
相关资源
最近更新 更多