将代码放到这里,以便日后使用。隔段时间后再来看opengl,就会发现突然无从下手,但那时却是可以简简单单地、轻轻松松地写出这么个程序。基于此,还是给自己留下完整的东西,基础框架,省得日后忘记了还得重新看、重新写。
.pro:
- QT += core gui
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
- TARGET = draw
- TEMPLATE = app
- SOURCES += \
- main.cpp \
- glwigdet.cpp \
- drawtriangle.cpp
- HEADERS += \
- glwigdet.h \
- drawtriangle.h
- RESOURCES += \
- shaders.qrc
main.cpp:
- #include <QApplication>
- #include <QSurfaceFormat>
- #include "drawtriangle.h"
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- QSurfaceFormat format;
- format.setDepthBufferSize(24);
- QSurfaceFormat::setDefaultFormat(format);
- DrawTriangle drawT;
- drawT.show();
- return app.exec();
- }
glwidget.h:
- #ifndef GLWIGDET_H
- #define GLWIGDET_H
- #include <QOpenGLWidget>
- #include <QOpenGLFunctions>
- #include <QOpenGLShaderProgram>
- #include <QOpenGLBuffer>
- #include <QMouseEvent>
- #include <QTimerEvent>
- #include <QKeyEvent>
- #include <QBasicTimer>
- #include <QVector3D>
- #include <QVector2D>
- /* 从OpenGL 3开始,编程模式被分为3种:
- * 1.兼容模式:即传统的方式
- * 2.核心模式:完全新式纯可编程流水线模式,但兼容废弃特性。(注:API不兼容旧的)
- * 3.核心向前兼容模式:完全不兼容废弃特性,其它同核心模式。(主要表现在线宽、线调色板这一类,其它同核心模式)
- *******************************************************************************************/
- class GLWigdet : public QOpenGLWidget, protected QOpenGLFunctions
- {
- Q_OBJECT
- public:
- GLWigdet(QWidget *parent = 0);
- protected:
- void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
- void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
- void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
- void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
- void initializeGL() Q_DECL_OVERRIDE;
- void resizeGL(int w, int h) Q_DECL_OVERRIDE;
- void paintGL() Q_DECL_OVERRIDE;
- void initShaders();
- virtual void do_init() {}
- virtual void do_paint() {}
- virtual void do_resize() {}
- protected:
- QOpenGLShaderProgram program;
- int a_position;
- private:
- QBasicTimer timer;
- QVector2D mousePressPosition;
- QVector3D rotationAxis;
- qreal angularSpeed;
- QQuaternion rotation;
- QMatrix4x4 m_proj; /* 投影矩阵 */
- };
- #endif // GLWIGDET_H
glwidget.cpp:
- #include "glwigdet.h"
- GLWigdet::GLWigdet(QWidget *parent)
- : QOpenGLWidget(parent)
- {
- setWindowTitle("opengl");
- resize(1280, 720);
- angularSpeed = 0;
- }
- void GLWigdet::initializeGL()
- {
- /* 初始化函数,使得函数可以使用 */
- initializeOpenGLFunctions();
- initShaders();
- a_position = program.attributeLocation("a_position");
- do_init();
- // Use QBasicTimer because its faster than QTimer
- timer.start(12, this);
- }
- void GLWigdet::initShaders()
- {
- // Compile vertex shader
- if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl"))
- close();
- // Compile fragment shader
- if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
- close();
- // Link shader pipeline
- if (!program.link())
- close();
- // Bind shader pipeline for use
- if (!program.bind())
- close();
- }
- void GLWigdet::paintGL()
- {
- glClear(GL_COLOR_BUFFER_BIT);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_DEPTH_BUFFER_BIT);
- glEnable(GL_DEPTH_TEST);
- // Calculate model view transformation
- QMatrix4x4 matrix;
- matrix.translate(0.0, 0.0, -5.0);
- matrix.rotate(rotation);
- // Set modelview-projection matrix
- int mvp_matrix = program.uniformLocation("mvp_matrix");
- program.setUniformValue(mvp_matrix, m_proj * matrix);
- do_paint();
- }
- void GLWigdet::resizeGL(int w, int h)
- {
- // Calculate aspect ratio
- qreal aspect = qreal(w) / qreal(h ? h : 1);
- // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees
- const qreal zNear = 3.0, zFar = 7.0, fov = 45.0;
- // Reset projection
- m_proj.setToIdentity();
- // Set perspective projection
- m_proj.perspective(fov, aspect, zNear, zFar);
- }
- void GLWigdet::keyPressEvent(QKeyEvent *kev)
- {
- if(kev->key() == Qt::Key_Escape) {
- close();
- } else {
- QOpenGLWidget::keyPressEvent(kev);
- }
- }
- void GLWigdet::mousePressEvent(QMouseEvent *e)
- {
- // Save mouse press position
- mousePressPosition = QVector2D(e->localPos());
- }
- void GLWigdet::mouseReleaseEvent(QMouseEvent *e)
- {
- // Mouse release position - mouse press position
- QVector2D diff = QVector2D(e->localPos()) - mousePressPosition;
- // Rotation axis is perpendicular to the mouse position difference
- // vector
- QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
- // Accelerate angular speed relative to the length of the mouse sweep
- qreal acc = diff.length() / 100.0;
- // Calculate new rotation axis as weighted sum
- rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
- // Increase angular speed
- angularSpeed += acc;
- }
- void GLWigdet::timerEvent(QTimerEvent *)
- {
- // Decrease angular speed (friction)
- angularSpeed *= 0.99;
- // Stop rotation when speed goes below threshold
- if (angularSpeed < 0.01) {
- angularSpeed = 0.0;
- } else {
- // Update rotation
- rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
- // Request an update
- update();
- }
- }
drawtriangle.h:
- #ifndef DRAWTRIANGLE_H
- #define DRAWTRIANGLE_H
- #include "glwigdet.h"
- class DrawTriangle : public GLWigdet
- {
- public:
- DrawTriangle(QWidget *parent = 0);
- protected:
- void do_init() Q_DECL_OVERRIDE;
- void do_paint() Q_DECL_OVERRIDE;
- private:
- int num;
- int mvp_matrix;
- };
- #endif // DRAWTRIANGLE_H
drawtriangle.cpp
- #include "drawtriangle.h"
- DrawTriangle::DrawTriangle(QWidget *parent)
- : GLWigdet(parent), num(0)
- {
- setWindowTitle("绘制三角形");
- }
- void DrawTriangle::do_init()
- {
- }
- void DrawTriangle::do_paint()
- {
- /* 1.5 为使用项目对象去渲染,需要绑定 */
- program.bind();
- /* 2.3 三角形顶点的坐标 */
- GLfloat vVertices[] = {
- 0.0f, 0.5f, 0.0f,
- -0.5f, -0.5f, 0.0f,
- 0.5f, -0.5f, 0.0f
- };
- /* 2.4 Load the vertex data */
- glVertexAttribPointer(a_position, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
- glEnableVertexAttribArray(a_position);
- /* 三角形 */
- glDrawArrays(GL_TRIANGLES, 0, 3);
- glFlush();
- }
vshader.glsl:
- #version 130
- uniform mat4 mvp_matrix;
- attribute highp vec4 a_position;
- //out
- varying lowp vec4 v_color;
- void main() {
- gl_Position = mvp_matrix * a_position;
- v_color = a_position;
- }
- #version 130
- varying lowp vec4 v_color;
- out highp vec4 fragColor;
- void main() {
- fragColor = v_color;
- }
运行结果:
鼠标拖动让其旋转的代码是拷贝官方cube这个例子的。由于这样代码看上去显得繁多,所以做一个基础类,后面具体绘制什么就继承这个类。
继承后的子类肯定要做些东西,所以预留do_xxx接口。
由于子类很有可能需要使用program,因此暂时作为protected成员。
FROM: http://blog.csdn.net/fu851523125/article/details/51626489