我正在尝试在QMainWindow中使用QOpenGLWidget来绘制三角形。不幸的是它没有渲染。我想使用索引绘图。
我有以下代码:
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions_4_5_Core>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
#include "model.h"
包括所有necesseties。
class OGLWidget : public QOpenGLWidget, protected QOpenGLFunctions_4_5_Core
{
Q_OBJECT
public:
OGLWidget(const QString* vshadersrc,const QString* fshadersrc, QWidget *parent = 0);
~OGLWidget();
public slots:
void cleanup();
覆盖方法initializeGL,paintGL和resizeGL。除了鼠标事件,它们现在也是空的。
protected:
void initializeGL() override;
void paintGL() override;
void resizeGL(int w, int h) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
着色器程序的句柄
QOpenGLShaderProgram *shaderprogram;
保存着色器源
const QString* vshadersrc;
const QString* fshadersrc;
3个矩阵,投影,视图(相机)和模型。
QMatrix4x4 mproj;
QMatrix4x4 mcamera;
QMatrix4x4 mmodel;
VertexArrayObject和VertexBufferObject + IndexBufferObject。
QOpenGLVertexArrayObject vao;
QOpenGLBuffer vbo;
QOpenGLBuffer ibo;
};
这是实现文件:
#include "oglwidget.h"
OGLWidget::OGLWidget(const QString* vsrc
,const QString* fsrc, QWidget *parent) : QOpenGLWidget(parent)
{
vshadersrc = vsrc;
fshadersrc = fsrc;
hasModel = false;
我将surfaceFormat设置为请求OpenGL 4.5 Core。
QSurfaceFormat surfaceFormat = this->format();
surfaceFormat.setVersion(4,5);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
this->setFormat(surfaceFormat);
}
OGLWidget::~OGLWidget()
{
cleanup();
}
void OGLWidget::initializeGL()
{
这些是我的立方体的索引和顶点。
const std::vector<GLushort> indices = {// front
0, 1, 2,
2, 3, 0,
// top
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// bottom
4, 0, 3,
3, 7, 4,
// left
4, 5, 1,
1, 0, 4,
// right
3, 2, 6,
6, 7, 3};
float width, height, depth;
width = height = depth = 3;
const std::vector<QVector3D> vertices = {
// front
QVector3D(-width / 2.0f, -height / 2.0f, depth / 2.0f),
QVector3D(width / 2.0f, -height / 2.0f, depth / 2.0f),
QVector3D(width / 2.0f, height / 2.0f, depth / 2.0f),
QVector3D(-width / 2.0f, height / 2.0f, depth / 2.0f),
// back
QVector3D(-width / 2.0f, -height / 2.0f, -depth / 2.0f),
QVector3D(width / 2.0f, -height / 2.0f, -depth / 2.0f),
QVector3D(width / 2.0f, height / 2.0f, -depth / 2.0f),
QVector3D(-width / 2.0f, height / 2.0f, -depth / 2.0f)
};
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &OGLWidget::cleanup);
initializeOpenGLFunctions();
glClearColor(0, 0, 0, 1);
着色器程序汇编在一起以形成源代码
shaderprogram = new QOpenGLShaderProgram();
shaderprogram->addShaderFromSourceFile(QOpenGLShader::Vertex, *vshadersrc);
shaderprogram->addShaderFromSourceFile(QOpenGLShader::Fragment, *fshadersrc);
shaderprogram->bindAttributeLocation("position", 0);
shaderprogram->link();
shaderprogram->bind();
我创建了VAO并通过Qt类绑定它
vao.create();
QOpenGLVertexArrayObject::Binder vaoBinder(&vao);
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
创建VBO并分配顶点数据并启用vertexattrib。
vbo.create();
vbo.bind();
vbo.allocate(vertices.data(), vertices.size() * sizeof(QVector3D));
vbo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
f->glEnableVertexAttribArray(0);
f->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
vbo.release();
创建IBO并分配索引数据。
ibo.create();
ibo.bind();
ibo.allocate(indices.data(), indices.size() * sizeof(GLushort));
ibo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
ibo.release();
然后我将模型和相机矩阵设置为I-Matrix并将相机移回一点。
// move back
mcamera.setToIdentity();
mcamera.translate(0, 0, -5);
mmodel.setToIdentity();
shaderprogram->release();
}
void OGLWidget::cleanup()
{
if(shaderprogram == nullptr)
return;
makeCurrent();
delete shaderprogram;
shaderprogram = 0;
doneCurrent();
}
void OGLWidget::paintGL()
{
清除窗口并启用Faceculling和Depth Test。
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
使用Shaderprogram并绑定VAO。
shaderprogram->bind();
QOpenGLVertexArrayObject::Binder vaoBinder(&vao);
绑定统一的ViewProjection Matrix和Model Matrix。
shaderprogram->setUniformValue(shaderprogram->uniformLocation("viewProjMatrix"), mproj * mcamera);
shaderprogram->setUniformValue(shaderprogram->uniformLocation("modelMatrix"), mmodel);
最后调用draw命令并释放shaderprogam。
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
shaderprogram->release();
}
Initializing the Projectionmatrix.
void OGLWidget::resizeGL(int w, int h)
{
mproj.setToIdentity();
mproj.perspective(45.f, float(w) / h, 0.01f, 1000.0f);
}
void OGLWidget::mousePressEvent(QMouseEvent *event){}
void OGLWidget::mouseMoveEvent(QMouseEvent *event){}
着色器程序相当简单。对于顶点着色器,我有:
#version 450
layout (location = 0) in vec3 position;
out vec4 color;
uniform mat4 modelMatrix;
uniform mat4 viewProjMatrix;
void main()
{
gl_Position = viewProjMatrix * modelMatrix * vec4(position, 1.0);
color = vec4(1.0, 1.0, 0.0, 1.0);
}
至于片段着色器,我只是传递颜色:
#version 450
out vec4 FragColor;
in vec4 color;
void main()
{
FragColor = color;
}
有谁知道什么可能出错?QOpenGLWidget只是保持清晰的颜色,因为没有画出任何东西。编辑:我的MainWindow实现如下:
#include "mainwindow.h"
MainWindow::MainWindow(int height, int width, QString title)
{
// create layout
QHBoxLayout *layout = new QHBoxLayout();
// add openglwidegts for rendering
model = new OGLWidget(new QString("./shader/shader.vert"), new QString("./shader/shader.frag"));
//planar = new OGLWidget(new QString("./shader/shader.vert"), new QString("./shader/shader.frag"));
model->setFixedSize(height / 2, width / 2);
//planar->setFixedSize(height / 2, width / 2);
layout->addWidget(model);
//layout->addWidget(planar);
// Add action to load a model
QAction *loadFile = this->menuBar()->addMenu("File")->addAction("Load Model");
QObject::connect(loadFile, &QAction::triggered, this, &MainWindow::loadModel);
// setup window
this->setCentralWidget(new QWidget);
this->centralWidget()->setLayout(layout);
this->setWindowTitle(title);
this->setWindowModality(Qt::ApplicationModal);
}
MainWindow::~MainWindow()
{
}
void MainWindow::loadModel()
{
QString filename = QFileDialog::getOpenFileName(this, "Choose 3D Model", QDir::currentPath(), "OFF Files (*.off)");
if(filename.isNull())
return;
Model* model = new Model(filename.toLocal8Bit().data());
}
发布于 2019-03-12 14:18:28
顶点缓冲区QOpenGLBuffer::VertexBuffer
的类型必须是,但索引缓冲区的类型必须是QOpenGLBuffer::IndexBuffer
:
OGLWidget::OGLWidget(const QString* vsrc,const QString* fsrc, QWidget *parent)
: QOpenGLWidget(parent)
, vbo(QOpenGLBuffer::VertexBuffer) // <--- vertex buffer
, ibo(QOpenGLBuffer::IndexBuffer) // <--- index buffer
{
// [...]
}
索引缓冲区的名称(值)在顶点数组对象的状态向量中说明。绑定时(在绑定顶点数组对象之后)声明索引缓冲区:
vao.create(); QOpenGLVertexArrayObject::Binder vaoBinder(&vao);
// [...]
ibo.create(); ibo.bind();
但是如果索引被释放(当绑定顶点数组对象时),则顶点数组对象与索引缓冲区的关联被破坏。 你要省略释放索引缓冲区:
ibo.allocate(indices.data(), indices.size() * sizeof(GLushort)); ibo.setUsagePattern(QOpenGLBuffer::UsagePattern::StaticDraw);
ibo.release();
https://stackoverflow.com/questions/-100006435
复制相似问题