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->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)?