Qt OpenGL (QOpenGLWidget) - 简单三角形

Posted

技术标签:

【中文标题】Qt OpenGL (QOpenGLWidget) - 简单三角形【英文标题】:Qt OpenGL (QOpenGLWidget) - Simple Triangle 【发布时间】:2016-07-31 14:37:00 【问题描述】:

作为使用 QOpenGLWidget 的 QT+OpenGL 的新手,我无法为我的三角形着色。 请在此处找到我的代码,使用 QMainWindow for GUI ...

// main.cpp
#include "mainwindow.h"
#include <QApplication>

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

    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();

这里是 GUI - 窗口

// MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
;

#endif // MAINWINDOW_H

这里的实现——文件...

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

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)

    ui->setupUi(this);


MainWindow::~MainWindow()

    delete ui;

这里是渲染 Opengl-Context 的小部件。

#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H

#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLContext>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QMatrix4x4>

class OpenglWidget : public QOpenGLWidget, public QOpenGLFunctions

public:
    OpenglWidget(QWidget *parent = 0);
    ~OpenglWidget();

protected:
    void initializeGL();
    void resizeGL(int width, int height);
    void paintGL();
    GLuint m_posAttr;
    GLuint m_colAttr;
    GLuint m_matrixUniform;
    QOpenGLShaderProgram *m_program;
;
#endif // OPENGLWIDGET_H

这里是实现文件...

#include "openglwidget.h"


OpenglWidget::OpenglWidget(QWidget *parent) :
    QOpenGLWidget(parent)

    setFormat(QSurfaceFormat::defaultFormat());


OpenglWidget::~OpenglWidget()



static const char *vertexShaderSource =
    "attribute highp vec4 posAttr;\n"
    "attribute lowp vec4 colAttr;\n"
    "varying lowp vec4 col;\n"
    "uniform highp mat4 matrix;\n"
    "void main() \n"
    "   col = vec4(1, 0, 0, 1);\n"
    "   gl_Position = matrix * posAttr;\n"
    "\n";

static const char *fragmentShaderSource =
    "varying lowp vec4 col;\n"
    "void main() \n"
    "   gl_FragColor = col;\n"
    "\n";

void OpenglWidget::initializeGL()

    makeCurrent();
    initializeOpenGLFunctions();
    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

    // Create Shader (Do not release until VAO is created)
    m_program = new QOpenGLShaderProgram(this);
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    m_program->link();
    m_posAttr = m_program->attributeLocation("posAttr");
    m_colAttr = m_program->attributeLocation("colAttr");
    m_matrixUniform = m_program->attributeLocation("matrix");

    m_program->release();


void OpenglWidget::paintGL()

    glClear(GL_COLOR_BUFFER_BIT);
    makeCurrent();

    //m_program->bind();

    QMatrix4x4 matrix;
    matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
    matrix.translate(0, 0, -2);

    m_program->setUniformValue(m_matrixUniform, matrix);

    GLfloat vertices[] = 
        0.0f, 0.707f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f
    ;

    GLfloat colors[] = 
        1.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 1.0f
    ;

    glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, 0, colors);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_TRIANGLES, 0, 3);

    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(0);

    m_program->release();


void OpenglWidget::resizeGL(int width, int height)

    glViewport(0, 0, width, height);

这里渲染的三角形只是白色的。 我无法理解着色器是否已编译并且属性是否已链接,但我仍然无法为三角形着色。

如果我能得到任何指导...... ???Output

【问题讨论】:

检查着色器编译是否成功。这些着色器不会使用兼容的 OpenGL 实现进行编译。 GLSL 1.10 不支持精度限定符,如果您不指定着色器版本,您将使用它。 我查了一下,addShaderFromSourceCode的返回标志是真的。 那么你很幸运,因为 OpenGL 实现没有检测到错误。它很可能在另一个平台上失败。另一个问题是您在某些地方使用attributeLocation() 的结果作为属性位置,但在其他地方使用硬连线值,例如glEnableVertexAttribArray() 调用。 【参考方案1】:

让我们看看你的着色器做了什么。您的片段着色器:

varying lowp vec4 col;
[...]
   gl_FragColor = col;

因此它将获取每个顶点的col 输出,为图元中的每个片段进行插值,并将其用作最终颜色。

现在你的顶点着色器:

   col = vec4(1, 0, 0, 1);

这显然是红色。您添加了一些 colAttr 输入属性并为此指定了一些顶点数组的事实完全不相关,只要您不实际使用该属性 - 目前,它是一个刚刚优化的非活动属性,因为它从不影响任何输出。

更新

如果你得到一个白色的三角形,这表明你的着色器根本没有使用。在您的 paintGL 方法中有一个 mprogram-&gt;release() 调用,但您从未真正启用该程序,因此不会使用它。

【讨论】:

(1, 0, 0, 1) 是红色的,不是白色的。 @RetoKoradi:天哪,我什至没有注意到这一点。那么肯定还有其他问题。 @derhass:嗨!我很感谢你的友好答复。我注意到您的 2 点第 1 点:(在测试 ColAttr 时 - 我将其硬编码为红色。),如果编译器针对“colAttr”优化它。三角形至少是红色的。第2点:我相信你指向://m_program->bind(); m_program->绑定();如果我取消注释它(定义:相当于调用 glUseProgram()。)三角形没有渲染。【参考方案2】:

也许你可以使用

m_colAttr = m_program->attributeLocation("col");

而不是

m_colAttr = m_program->attributeLocation("colAttr"); 

如果你写在着色器中

gl_FragColor = col;

col = col, colAttr != col

更改属性名称,如果这无助于更改 initializeGL 中的此调用

program->release(); 

program->bind();

【讨论】:

以上是关于Qt OpenGL (QOpenGLWidget) - 简单三角形的主要内容,如果未能解决你的问题,请参考以下文章

Qt 5.5 QOpenGLWidget链接错误未链接任何openGL调用

将OpenGL帧缓冲区对象与Qt(QOpenGLWidget)一起使用,绘制到帧缓冲区时如何禁用多重采样

添加到 QGraphicsScene 时如何更新 OpenGL 绘图(QOpenGLWidget)?

加不了openglwidget

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

OpenGL:如何在 Qt 中使用 glMapBuffer?