带有 QOpenGLWidget 的 Qt 5.5,核心配置文件中的不可见三角形
Posted
技术标签:
【中文标题】带有 QOpenGLWidget 的 Qt 5.5,核心配置文件中的不可见三角形【英文标题】:Qt 5.5 with QOpenGLWidget, invisible triangle in core profile 【发布时间】:2015-11-10 20:36:25 【问题描述】:我无法将我习惯于在 Qt 之外使用 Glew 和 GLFW 执行的 hello 三角形移植到 Qt 5.5 和 QOpenGlWidget 中,使用 QSurfaceFormat、QOpenGLfunctions、QOpenGLShaderProgram 等“新”方式与核心配置文件和opengl >= 3.3。
这是我的 QOpenGLWidget 子类“OGLWidget”,我改编自 this post. 和这个 Qt tutorial
#include "oglwidget.h"
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
OGLWidget::OGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
, m_program(0)
OGLWidget::~OGLWidget()
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 = colAttr;\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 OGLWidget::initializeGL()
initializeOpenGLFunctions();
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->uniformLocation("matrix");
void OGLWidget::paintGL()
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
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);
void OGLWidget::resizeGL(int w, int h)
matrix.setToIdentity();
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
这适用于这个 main.cpp:
#include <QApplication>
#include <QSurfaceFormat>
#include "oglwidget.h"
int main(int argc, char *argv[])
QApplication a(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
format.setVersion(3, 3);
QSurfaceFormat::setDefaultFormat(format);
OGLWidget myGLWidget;
myGLWidget.resize(640, 480);
myGLWidget.show();
return a.exec();
但是,当我添加:format.setProfile(QSurfaceFormat::CoreProfile);
到上面的块,并将我的着色器更改为我最近通过使用核心配置文件和 GLSL 3.3 的 openGL 教程学习的内容:
static const char *vertexShaderSource =
"#version 330 core;\n"
"layout (location = 0) in vec3 posAttr;\n"
"layout (location = 1) in vec3 colAttr;\n"
"out vec3 fragColor;\n"
"void main()\n"
" gl_Position = matrix * vec4(posAttr, 1.0f);\n"
" fragColor = colAttr;\n"
"\n";
static const char *fragmentShaderSource =
"#version 330 core;\n"
"in vec3 fragColor;\n"
"out vec4 color;\n"
"void main()\n"
" color = vec4(fragColor, 1.0f);"
"\n";
我的代码可以编译,但我有一个黑屏。没有三角了。
我在 macbook pro 视网膜上使用 Qt 5.5,优胜美地 10.10.5。 GPU 英特尔虹膜。
知道我要在那里修改什么来再次向我的彩色三角形问好吗?
谢谢
编辑
这里是新版本的cmets代码,建议添加VAO。我认为 VBO 是必需的,但我正在即兴创作的这些最近的 Qt 类没有工作示例。尽管如此,我的三角形仍然没有出现。我在这里进行了简化,因为我使用了直接在着色器中编码的单一颜色。
OGLWidget::OGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
, m_program(0)
OGLWidget::~OGLWidget()
static const char *vertexShaderSource =
"#version 330 core\n"
"layout (location = 0) in vec3 posAttr;\n"
"uniform mat4 matrix;\n"
"void main()\n"
" gl_Position = matrix * vec4(posAttr, 1.0f);\n"
"\n";
static const char *fragmentShaderSource =
"#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
" color = vec4(0.5f, 0.0f, 0.0f, 1.0f);\n"
"\n";
void OGLWidget::initializeGL()
initializeOpenGLFunctions();
GLfloat vertices[] =
0.0f, 0.707f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
;
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_matrixUniform = m_program->uniformLocation("matrix");
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
// Create Vertex Array Object
m_vao.create();
m_vao.bind();
// Create Vertex Buffer (Do not release until VAO is created)
m_vertexBuffer = QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
m_vertexBuffer.create();
m_vertexBuffer.bind();
m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
m_vertexBuffer.allocate(sizeof(vertices));
m_program->bind();
m_program->setAttributeBuffer(m_posAttr, GL_FLOAT, 0, 3*sizeof(GLfloat));
m_program->enableAttributeArray(m_posAttr);
m_program->setAttributeArray(m_posAttr, vertices, 3);
m_vao.release();
m_vertexBuffer.release();
m_program->release();
void OGLWidget::paintGL()
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
m_program->setUniformValue(m_matrixUniform, matrix);
m_vao.bind();
glDrawArrays(GL_TRIANGLES, 0 , 3);
m_vao.release();
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
void OGLWidget::resizeGL(int w, int h)
matrix.setToIdentity();
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -2);
【问题讨论】:
核心配置文件 capital-R 要求您在设置属性启用/指针和渲染之前创建并绑定 VAO。 绑定 VAO 与我已经在使用的 QOpenGLShaderProgram 类的所有绑定函数有何不同?我不能用这个类的方法来做吗? 我看到 Qt 5 有一个用于 VAO 的 wrapper,但不清楚这是否是为了与 QOpenGLShaderProgram 类交互。我找不到任何工作示例。 我用绑定 VAO 和 VBO 的代码编辑了我的答案。我仍然有黑色图像。 我找到了一个可行的解决方案,这个问题可以重新打开以便我发布吗? 【参考方案1】:在阅读和测试代码片段后,我在这里提交了一些有效的东西。如果您认为有一个甚至“更好”的方式(相对于 Qt 或 openGL 推荐的方式更好),请务必纠正我。
(main.cpp不变)
oglwidget.h
#include <QWidget>
#include <QOpenGLWidget>
#include <QtGui/QWindow>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLBuffer>
class QPainter;
class QOpenGLContext;
class QOpenGLPaintDevice;
class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
public:
OGLWidget(QWidget *parent = 0);
~OGLWidget();
protected:
void initializeGL();
void resizeGL(int w, int h);
void paintGL();
private:
bool prepareShaderProgram( const QString& vertexShaderPath,
const QString& fragmentShaderPath );
QOpenGLVertexArrayObject m_vao;
QOpenGLBuffer m_vertexBuffer;
QOpenGLShaderProgram m_shader;
;
我没有将以上内容放在我的原始帖子中。所以这会让事情变得更清楚。下面是更正后的 oglwidget.cpp,用于显示红色三角形。
oglwidget.cpp
OGLWidget::OGLWidget(QWidget *parent)
:QOpenGLWidget(parent)
, m_shader(0)
, m_vertexBuffer(QOpenGLBuffer::VertexBuffer)
OGLWidget::~OGLWidget()
void OGLWidget::initializeGL()
initializeOpenGLFunctions();
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
if ( !prepareShaderProgram( "/file Path To vertex shader source file", "/file Path To fragment shader source file" ) )
return;
GLfloat vertices[] =
0.0f, 0.707f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
;
// Setup Vertex Buffer
m_vertexBuffer.create();
m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
// Bind Vertex Buffer + check
if ( !m_vertexBuffer.bind() )
qWarning() << "Could not bind vertex buffer to the context";
return;
m_vertexBuffer.allocate(vertices, sizeof(vertices));
// Bind the shader program so that we can associate variables from
// our application to the shaders
if ( !m_shader.bind() )
qWarning() << "Could not bind shader program to context";
return;
// Create Vertex Array Object
m_vao.create();
m_vao.bind();
m_shader.setAttributeBuffer("vertex", GL_FLOAT, 0, 3);
m_shader.enableAttributeArray("vertex");
m_vao.release();
m_vertexBuffer.release();
m_shader.release();
void OGLWidget::paintGL()
glClear(GL_COLOR_BUFFER_BIT);
m_shader.bind();
m_vao.bind();
glDrawArrays(GL_TRIANGLES, 0 , 3);
m_vao.release();
m_shader.release();
void OGLWidget::resizeGL(int w, int h)
// const qreal retinaScale = devicePixelRatio();
// glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glViewport( 0, 0, w, qMax( h, 1 ) );
bool OGLWidget::prepareShaderProgram(const QString &vertexShaderPath, const QString &fragmentShaderPath)
// First we load and compile the vertex shader…
bool result = m_shader.addShaderFromSourceFile( QOpenGLShader::Vertex, vertexShaderPath );
if ( !result )
qWarning() << m_shader.log();
// fragment shader
result = m_shader.addShaderFromSourceFile( QOpenGLShader::Fragment, fragmentShaderPath );
if ( !result )
qWarning() << m_shader.log();
// link the shaders
result = m_shader.link();
if ( !result )
qWarning() << "Could not link shader program:" << m_shader.log();
return result;
我不清楚我是否需要使用:glDisableVertexAttribArray
,我一直在非 Qt 代码中使用它。在这里我没有,但如果必须,我什么时候使用它?无论如何,三角形显示。
【讨论】:
我尝试使用您的代码,但没有成功。只是出现了一个黑色的小部件。有什么提示吗? 我已经 4 年没碰过这个项目了……你用的是什么平台/操作系统? Windows 10、MacOS X 和 Linux。必须支持所有平台:-/ 几年过去了,我没有跟踪 Qt 和 openGL 中的更新,所以也许这不再像 SO 中那样有效。但是,这篇 SO 帖子与我在 github.com/WaaallEEE/LightDrops 上的 Github 项目相关,上次我在 Windows 10 和 MacOsX 上编译并运行它是在 2017 年,所以这仍然比这篇 SO 帖子更新。也许你可以找到我是如何实现所有 openGL 上下文的,如果它仍然有效的话。以上是关于带有 QOpenGLWidget 的 Qt 5.5,核心配置文件中的不可见三角形的主要内容,如果未能解决你的问题,请参考以下文章
Qt 5.5 QOpenGLWidget链接错误未链接任何openGL调用