QOpenGLWidget绘制对象
QOpenGLWidget draw object
我已经问了一个关于 QOpenglWidget 的问题 。
在我的最后一个问题中,我只是错误地调用了 sharedid。
现在我正在尝试从一个对象加载我的顶点。
我写了一个加载器来加载顶点、纹理坐标、法线和索引。我已经用本机 openGL 编写了这段代码并检查了输出。顶点等与我的 Qt 代码中的匹配。
唯一的问题是我无法让 paintGL() 方法绘制我的对象,它应该是一个简单的立方体。
--Main.cpp
#include <QApplication>
#include <QLabel>
#include <QSurfaceFormat>
#ifndef QT_NO_OPENGL
#include "mainwidget.h"
#endif
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
QSurfaceFormat::setDefaultFormat(format);
app.setApplicationName("MainWidget");
#ifndef QT_NO_OPENGL
MainWidget widget;
widget.resize(800, 600);
widget.show();
#else
QLabel note("OpenGL Support required");
note.show();
#endif
return app.exec();
}
--MainWidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QVector2D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QOpenGLVertexArrayObject>
#include <QVector>
#include "geometryengine.h"
class GeometryEngine;
class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
protected:
void initializeGL()Q_DECL_OVERRIDE;
void resizeGL(int w, int h)Q_DECL_OVERRIDE;
void paintGL()Q_DECL_OVERRIDE;
void initShaders();
private:
QOpenGLShaderProgram program;
GeometryEngine *geometries;
};
#endif // MAINWIDGET_H
--MainWidget.cpp
#include "mainwidget.h"
#include <iostream>
extern QVector<QVector3D> m_vertices;
extern QVector<QVector2D> m_uvs;
extern QVector<QVector3D> m_normals;
extern QVector<QVector3D> m_indexed_vertices;
extern QVector<QVector2D> m_indexed_uvs;
extern QVector<QVector3D> m_indexed_normals;
extern QVector<unsigned short> m_indices;
MainWidget::MainWidget(QWidget *parent):QOpenGLWidget(parent), geometries(0){
}
MainWidget::~MainWidget(){
makeCurrent();
delete geometries;
doneCurrent();
}
void MainWidget::initializeGL(){
initializeOpenGLFunctions();
glClearColor(0, 0, 0.4f, 0);
glEnable(GL_DEPTH_TEST);
initShaders();
geometries = new GeometryEngine;
for(auto i : m_indexed_vertices){
std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
//std::cout << i << " " << std::endl;
}
}
void MainWidget::resizeGL(int w, int h){
}
void MainWidget::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*for(auto i : m_indices){
//std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
std::cout << i << " " << std::endl;
}*/
geometries->drawGeometry(&program, m_indices);
}
void MainWidget::initShaders(){
// Compile vertex shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, "vertex.vert"))
close();
// Compile fragment shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, "fragment.frag"))
close();
// Link shader pipeline
if (!program.link())
close();
// Bind shader pipeline for use
if (!program.bind())
close();
}
--GeometryEngine.h
#ifndef GEOMETRYENGINE_H
#define GEOMETRYENGINE_H
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include "mainwidget.h"
class GeometryEngine : protected QOpenGLFunctions
{
public:
GeometryEngine();
virtual ~GeometryEngine();
void drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices);
private:
void initGeometry(const char *path, QVector<QVector3D> &vert, QVector<QVector2D> &uv, QVector<QVector3D> &norm,QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices,
QVector<QVector2D> &indexed_uvs,
QVector<QVector3D> &indexed_normals);
QOpenGLBuffer arrayBuf;
QOpenGLBuffer indexBuf;
QOpenGLVertexArrayObject vertexArrayID;
};
#endif // GEOMETRYENGINE_H
--GeometryEngine.cpp
#include "geometryengine.h"
#include "mainwidget.h"
#include "loadobj.h"
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <string>
#include <iostream>
QVector<QVector3D> m_vertices;
QVector<QVector2D> m_uvs;
QVector<QVector3D> m_normals;
QVector<QVector3D> m_indexed_vertices;
QVector<QVector2D> m_indexed_uvs;
QVector<QVector3D> m_indexed_normals;
QVector<unsigned short> m_indices;
GeometryEngine::GeometryEngine() : indexBuf(QOpenGLBuffer::IndexBuffer)
{
initializeOpenGLFunctions();
vertexArrayID.create();
vertexArrayID.bind();
//generate vbos
arrayBuf.create();
indexBuf.create();
initGeometry("cube.obj", m_vertices, m_uvs, m_normals, m_indices, m_indexed_vertices, m_indexed_uvs, m_indexed_normals);
}
GeometryEngine::~GeometryEngine(){
arrayBuf.destroy();
indexBuf.destroy();
vertexArrayID.destroy();
}
void GeometryEngine::initGeometry(const char *path,QVector<QVector3D> &vertices, QVector<QVector2D> &uvs, QVector<QVector3D> &normals, QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices, QVector<QVector2D> &indexed_uvs, QVector<QVector3D> &indexed_normals ){
bool res = loadObj(path, vertices, uvs, normals);
vboIndexer(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals );
/*for(auto i : indices){
//std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
std::cout << i << " " << std::endl;
}*/
arrayBuf.bind();
arrayBuf.allocate(&indexed_vertices, indexed_vertices.size() * sizeof(QVector3D));
indexBuf.bind();
indexBuf.allocate(&indices, indices.size() * sizeof(unsigned short));
}
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices){
arrayBuf.bind();
indexBuf.bind();
int vertexLocation = program->attributeLocation("vertex");
program->enableAttributeArray(vertexLocation);
program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(GLfloat));
//glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_SHORT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}
--vertex.vert
#version 330
layout(location = 0) in vec3 vertex;
void main(){
gl_Position = vec4(vertex, 1.0);
}
--fragment.frag
#version 330
out vec3 color;
void main(){
color = vec3(1,0,0);
}
我不知道是我搞砸了一些 QOpenGL 代码,还是因为我将顶点存储在 QVector 而不是数组中。正如您在代码相似性中看到的那样,我首先使用了 Qt 中的立方体示例。
好的问题解决了。
本机 openGL 能够绘制来自 Vectors 的数据,而 QopenGLWidget 只能在数据存储在数组中时绘制。即使数组包含 Qvector3D 数据。
如果我错了请纠正我..因为这对我来说有点可疑。
我已经问了一个关于 QOpenglWidget 的问题
唯一的问题是我无法让 paintGL() 方法绘制我的对象,它应该是一个简单的立方体。
--Main.cpp
#include <QApplication>
#include <QLabel>
#include <QSurfaceFormat>
#ifndef QT_NO_OPENGL
#include "mainwidget.h"
#endif
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setDepthBufferSize(24);
QSurfaceFormat::setDefaultFormat(format);
app.setApplicationName("MainWidget");
#ifndef QT_NO_OPENGL
MainWidget widget;
widget.resize(800, 600);
widget.show();
#else
QLabel note("OpenGL Support required");
note.show();
#endif
return app.exec();
}
--MainWidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QVector2D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QOpenGLVertexArrayObject>
#include <QVector>
#include "geometryengine.h"
class GeometryEngine;
class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
protected:
void initializeGL()Q_DECL_OVERRIDE;
void resizeGL(int w, int h)Q_DECL_OVERRIDE;
void paintGL()Q_DECL_OVERRIDE;
void initShaders();
private:
QOpenGLShaderProgram program;
GeometryEngine *geometries;
};
#endif // MAINWIDGET_H
--MainWidget.cpp
#include "mainwidget.h"
#include <iostream>
extern QVector<QVector3D> m_vertices;
extern QVector<QVector2D> m_uvs;
extern QVector<QVector3D> m_normals;
extern QVector<QVector3D> m_indexed_vertices;
extern QVector<QVector2D> m_indexed_uvs;
extern QVector<QVector3D> m_indexed_normals;
extern QVector<unsigned short> m_indices;
MainWidget::MainWidget(QWidget *parent):QOpenGLWidget(parent), geometries(0){
}
MainWidget::~MainWidget(){
makeCurrent();
delete geometries;
doneCurrent();
}
void MainWidget::initializeGL(){
initializeOpenGLFunctions();
glClearColor(0, 0, 0.4f, 0);
glEnable(GL_DEPTH_TEST);
initShaders();
geometries = new GeometryEngine;
for(auto i : m_indexed_vertices){
std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
//std::cout << i << " " << std::endl;
}
}
void MainWidget::resizeGL(int w, int h){
}
void MainWidget::paintGL(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*for(auto i : m_indices){
//std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
std::cout << i << " " << std::endl;
}*/
geometries->drawGeometry(&program, m_indices);
}
void MainWidget::initShaders(){
// Compile vertex shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, "vertex.vert"))
close();
// Compile fragment shader
if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, "fragment.frag"))
close();
// Link shader pipeline
if (!program.link())
close();
// Bind shader pipeline for use
if (!program.bind())
close();
}
--GeometryEngine.h
#ifndef GEOMETRYENGINE_H
#define GEOMETRYENGINE_H
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include "mainwidget.h"
class GeometryEngine : protected QOpenGLFunctions
{
public:
GeometryEngine();
virtual ~GeometryEngine();
void drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices);
private:
void initGeometry(const char *path, QVector<QVector3D> &vert, QVector<QVector2D> &uv, QVector<QVector3D> &norm,QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices,
QVector<QVector2D> &indexed_uvs,
QVector<QVector3D> &indexed_normals);
QOpenGLBuffer arrayBuf;
QOpenGLBuffer indexBuf;
QOpenGLVertexArrayObject vertexArrayID;
};
#endif // GEOMETRYENGINE_H
--GeometryEngine.cpp
#include "geometryengine.h"
#include "mainwidget.h"
#include "loadobj.h"
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <string>
#include <iostream>
QVector<QVector3D> m_vertices;
QVector<QVector2D> m_uvs;
QVector<QVector3D> m_normals;
QVector<QVector3D> m_indexed_vertices;
QVector<QVector2D> m_indexed_uvs;
QVector<QVector3D> m_indexed_normals;
QVector<unsigned short> m_indices;
GeometryEngine::GeometryEngine() : indexBuf(QOpenGLBuffer::IndexBuffer)
{
initializeOpenGLFunctions();
vertexArrayID.create();
vertexArrayID.bind();
//generate vbos
arrayBuf.create();
indexBuf.create();
initGeometry("cube.obj", m_vertices, m_uvs, m_normals, m_indices, m_indexed_vertices, m_indexed_uvs, m_indexed_normals);
}
GeometryEngine::~GeometryEngine(){
arrayBuf.destroy();
indexBuf.destroy();
vertexArrayID.destroy();
}
void GeometryEngine::initGeometry(const char *path,QVector<QVector3D> &vertices, QVector<QVector2D> &uvs, QVector<QVector3D> &normals, QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices, QVector<QVector2D> &indexed_uvs, QVector<QVector3D> &indexed_normals ){
bool res = loadObj(path, vertices, uvs, normals);
vboIndexer(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals );
/*for(auto i : indices){
//std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
std::cout << i << " " << std::endl;
}*/
arrayBuf.bind();
arrayBuf.allocate(&indexed_vertices, indexed_vertices.size() * sizeof(QVector3D));
indexBuf.bind();
indexBuf.allocate(&indices, indices.size() * sizeof(unsigned short));
}
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices){
arrayBuf.bind();
indexBuf.bind();
int vertexLocation = program->attributeLocation("vertex");
program->enableAttributeArray(vertexLocation);
program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(GLfloat));
//glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_SHORT, 0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
}
--vertex.vert
#version 330
layout(location = 0) in vec3 vertex;
void main(){
gl_Position = vec4(vertex, 1.0);
}
--fragment.frag
#version 330
out vec3 color;
void main(){
color = vec3(1,0,0);
}
我不知道是我搞砸了一些 QOpenGL 代码,还是因为我将顶点存储在 QVector 而不是数组中。正如您在代码相似性中看到的那样,我首先使用了 Qt 中的立方体示例。
好的问题解决了。
本机 openGL 能够绘制来自 Vectors 的数据,而 QopenGLWidget 只能在数据存储在数组中时绘制。即使数组包含 Qvector3D 数据。
如果我错了请纠正我..因为这对我来说有点可疑。