原文:https://www.jianshu.com/p/45122bdaae77
opengl核心函数版
#include "corefunctionwidget.h" #include <QDebug> #include <QTimer> static GLuint VAO,VBO,texture1,texture2; CoreFunctionWidget::CoreFunctionWidget(QWidget *parent) : QOpenGLWidget (parent) { m_timer = new QTimer(this); connect(m_timer,&QTimer::timeout,this,[=]{ m_nTimeValue += 1; update(); }); m_timer->start(50); } CoreFunctionWidget::~CoreFunctionWidget() { glDeleteVertexArrays(1,&VAO); glDeleteBuffers(1,&VBO); } void CoreFunctionWidget::initializeGL() { this->initializeOpenGLFunctions(); bool success = m_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert"); if (!success) { qDebug() << "m_program addShaderFromSourceFile failed!" << m_program.log(); return; } success = m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/textures.frag"); if (!success) { qDebug() << "m_program addShaderFromSourceFile failed!" << m_program.log(); return; } success = m_program.link(); if(!success) { qDebug() << "m_program link failed!" << m_program.log(); } // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); //VAO,VBO data float vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); // position attribute glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // texture coord attribute glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // texture1 glGenTextures(1,&texture1); glBindTexture(GL_TEXTURE_2D,texture1); // set texture wrapping parameters glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); // SET texture filting parameters glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // load image,create texture,generate mipmaps QImage image1 = QImage(":/image/container.jpg").convertToFormat(QImage::Format_RGB888); if (!image1.isNull()){ glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,image1.width(),image1.height(),0,GL_RGB,GL_UNSIGNED_BYTE,image1.bits()); glGenerateMipmap(GL_TEXTURE_2D); } // texture2 glGenTextures(1,&texture2); glBindTexture(GL_TEXTURE_2D,texture2); // set texture wrapping parameters glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); // SET texture filting parameters glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // load image,create texture,generate mipmaps QImage image2 = QImage(":/image/awesomeface.png").convertToFormat(QImage::Format_RGBA8888).mirrored(true, true); if (!image2.isNull()){ // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,image2.width(),image2.height(),0,GL_RGBA,GL_UNSIGNED_BYTE,image2.bits()); glGenerateMipmap(GL_TEXTURE_2D); } // tell opengl for each sampler to which texture unit it belongs to (only has to be done once) m_program.bind(); // don't forget to activate/use the shader before setting uniforms! glUniform1i(m_program.uniformLocation("texture1"),0); glUniform1i(m_program.uniformLocation("texture2"),1); QMatrix4x4 view; view.translate(QVector3D(0.0f,0.0f,-3.0f)); m_program.setUniformValue("view",view); QMatrix4x4 projection; projection.perspective(45.0f,1.0f*width()/height(),0.1f,100.0f); m_program.setUniformValue("projection",projection); m_program.release(); } void CoreFunctionWidget::resizeGL(int w, int h) { glViewport(0,0,w,h); } static QVector3D cubePositions[] = { QVector3D( 0.0f, 0.0f, 0.0f), QVector3D( 2.0f, 5.0f, -15.0f), QVector3D(-1.5f, -2.2f, -2.5f), QVector3D(-3.8f, -2.0f, -12.3f), QVector3D( 2.4f, -0.4f, -3.5f), QVector3D(-1.7f, 3.0f, -7.5f), QVector3D( 1.3f, -2.0f, -2.5f), QVector3D( 1.5f, 2.0f, -2.5f), QVector3D( 1.5f, 0.2f, -1.5f), QVector3D(-1.3f, 1.0f, -1.5f) }; void CoreFunctionWidget::paintGL() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now! // bind textures on corresponding texture units glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texture2); m_program.bind(); // render boxes glBindVertexArray(VAO); for (unsigned int i = 0; i < 10; i++) { // calculate the model matrix for each object and pass it to shader before drawing QMatrix4x4 model; model.translate(cubePositions[i]); float angle = (i + 1.0f) * m_nTimeValue; model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f)); m_program.setUniformValue("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); } m_program.release(); }
#ifndef COREFUNCTIONWIDGET_H #define COREFUNCTIONWIDGET_H #include <QWidget> #include <QOpenGLWidget> #include <QOpenGLFunctions_3_3_Core> #include <QOpenGLShader> #include <QOpenGLShaderProgram> class CoreFunctionWidget : public QOpenGLWidget,protected QOpenGLFunctions_3_3_Core { Q_OBJECT public: CoreFunctionWidget(QWidget *parent = nullptr); ~CoreFunctionWidget() Q_DECL_OVERRIDE; protected: virtual void initializeGL() Q_DECL_OVERRIDE; virtual void resizeGL(int w,int h) Q_DECL_OVERRIDE; virtual void paintGL() Q_DECL_OVERRIDE; private: QOpenGLShaderProgram m_program; QTimer *m_timer; int m_nTimeValue{0}; };
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main(){ gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = aTexCoord; }
#version 330 core out vec4 FragColor; in vec2 TexCoord; uniform sampler2D texture1; uniform sampler2D texture2; void main() { FragColor = mix(texture2D(texture1, TexCoord), texture2D(texture2, TexCoord), 0.2f); }
Qt封装函数版本
#include "qtfunwidget.h" #include <QTimer> #include <QDebug> QtFunWidget::QtFunWidget(QWidget *parent) : QOpenGLWidget(parent) { m_timer = new QTimer(this); connect(m_timer,&QTimer::timeout,this,[=]{ m_nTimeValue += 1; update(); }); m_timer->start(40); } QtFunWidget::~QtFunWidget() { makeCurrent(); vbo.destroy(); vao.destroy(); delete texture1; delete texture2; doneCurrent(); } void QtFunWidget::initializeGL() { this->initializeOpenGLFunctions(); bool success = m_program.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert"); if(!success) { qDebug() << "add vertex shader failed." << m_program.log(); return; } m_program.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/textures.frag"); if(!success) { qDebug() << "add frag shader failed." << m_program.log(); return; } m_program.link(); if(!success) { qDebug() << "link shader failed." << m_program.log(); return; } // configure global opengl state // ----------------------------- glEnable(GL_DEPTH_TEST); //VAO,VBO data float vertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; QOpenGLVertexArrayObject::Binder vaoBind(&vao); vbo.create(); vbo.bind(); vbo.allocate(vertices,sizeof(vertices)); //position attribute int attr = -1; attr = m_program.attributeLocation("aPos"); m_program.setAttributeBuffer(attr,GL_FLOAT,0,3,5*sizeof(GL_FLOAT)); m_program.enableAttributeArray(attr); // coord attribute attr = m_program.attributeLocation("aTexCoord"); m_program.setAttributeBuffer(attr,GL_FLOAT,3*sizeof(GL_FLOAT),2,5*sizeof(GL_FLOAT)); m_program.enableAttributeArray(attr); // texture1 texture1 = new QOpenGLTexture(QImage(":/image/container.jpg")); if(!texture1->isCreated()) { qDebug() << "failed to load texture1"; } // set the texture wrapping parameters texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat); texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat); // set texture filtering parameters texture1->setMinificationFilter(QOpenGLTexture::Linear); texture1->setMagnificationFilter(QOpenGLTexture::Linear); // texture 2 // --------- texture2 = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored(true, true), QOpenGLTexture::GenerateMipMaps); if(!texture2->isCreated()){ qDebug() << "Failed to load texture"; } texture2->setWrapMode(QOpenGLTexture::DirectionS,QOpenGLTexture::Repeat); texture2->setWrapMode(QOpenGLTexture::DirectionT,QOpenGLTexture::Repeat); texture2->setMinificationFilter(QOpenGLTexture::Linear); texture2->setMagnificationFilter(QOpenGLTexture::Linear); m_program.bind(); m_program.setUniformValue("texture1",0); m_program.setUniformValue("texture2",1); QMatrix4x4 view; view.translate(QVector3D(0.0f,0.0f,-3.0f)); m_program.setUniformValue("view",view); QMatrix4x4 projection; projection.perspective(45.0f, 1.0f * width() / height(), 0.1f, 100.0f); m_program.setUniformValue("projection", projection); m_program.release(); vbo.release(); } void QtFunWidget::resizeGL(int w, int h) { glViewport(0,0,w,h); } static QVector3D cubePositions[] = { QVector3D( 0.0f, 0.0f, 0.0f), QVector3D( 2.0f, 5.0f, -15.0f), QVector3D(-1.5f, -2.2f, -2.5f), QVector3D(-3.8f, -2.0f, -12.3f), QVector3D( 2.4f, -0.4f, -3.5f), QVector3D(-1.7f, 3.0f, -7.5f), QVector3D( 1.3f, -2.0f, -2.5f), QVector3D( 1.5f, 2.0f, -2.5f), QVector3D( 1.5f, 0.2f, -1.5f), QVector3D(-1.3f, 1.0f, -1.5f) }; void QtFunWidget::paintGL() { glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // also clear the depth buffer now! // bind textures on corresponding texture units glActiveTexture(GL_TEXTURE0); texture1->bind(); glActiveTexture(GL_TEXTURE1); texture2->bind(); m_program.bind(); { QOpenGLVertexArrayObject::Binder vaoBind(&vao); for(int i = 0; i< 10; ++i){ QMatrix4x4 model; model.translate(cubePositions[i]); float angle = (i + 1.0f) * m_nTimeValue; model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f)); m_program.setUniformValue("model", model); glDrawArrays(GL_TRIANGLES, 0, 36); } } texture1->release(); texture2->release(); m_program.release(); }
#ifndef QTFUNWIDGET_H #define QTFUNWIDGET_H #include <QWidget> #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLShader> #include <QOpenGLShaderProgram> #include <QOpenGLBuffer> #include <QOpenGLVertexArrayObject> #include <QOpenGLTexture> class QtFunWidget : public QOpenGLWidget,protected QOpenGLFunctions { Q_OBJECT public: QtFunWidget(QWidget *parent = 0); ~QtFunWidget() Q_DECL_OVERRIDE; protected: virtual void initializeGL() Q_DECL_OVERRIDE; virtual void resizeGL(int w,int h) Q_DECL_OVERRIDE; virtual void paintGL() Q_DECL_OVERRIDE; private: QOpenGLShaderProgram m_program; QOpenGLBuffer vbo; QOpenGLVertexArrayObject vao; QOpenGLTexture *texture1{nullptr}; QOpenGLTexture *texture2{nullptr}; QTimer *m_timer; int m_nTimeValue; }; #endif // QTFUNWIDGET_H