2.通过QOpenGLWidget绘制三角形

1.QOpenGLWidget的早先版本
QGLWidget是遗留Qt OpenGL模块的一部分,和其他QGL类一样,应该在新的应用程序中避免使用。相反,从Qt 5.4开始,最好使用QOpenGLWidget和QOpenGL类。
如果开发XP平台,由于兼容性问题,Qt5.4(不含)之后的QtOpenglWidget 则不兼容,建议还是用QGLWidget.
 
2.QOpenGLWidget类是用于呈现OpenGL图形的部件
        QOpenGLWidget提供显示集成到Qt应用程序中的OpenGL图形的功能。使用起来非常简单:让类继承它,并像其他QWidget一样使用子类,额外可以选择使用QPainer和标准的OpenGL渲染命令。
        QOpenGLWidget提供了三个方便的虚拟函数,子类中重新实现这些函数来执行OpenGL绘制任务:
  • paintGL():渲染OpenGL场景。该函数里面主要绘制部件,比如在全屏视频上面显示滑动条
  • resizeGL ():当窗口尺寸发生变化时被调用,然后会调用paintGL()函数重新绘制一次(并且第一次显示时也会调用resizeGL() )。
  • initializeGL():用于初始化,设置OpenGL要呈现的画面,只在程序开始时运行一次,之后不会再运行。
其中在initializeGL()中初始化具体如下所示:
然后在paintGL()中,每次当我们要绘制不同的物体时,便调用bind()来绑定对象、绘制完后,解绑对象,如果还要绘制下个物体,那么就取出对应的VAO,绑定它,绘制完物体后,再解绑。
 
3.三角形示例
4.头文件代码
#ifndef MYGLWIDGET_H
#define MYGLWIDGET_H
 
#include <QMainWindow>
#include <QObject>
#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
class myGlWidget : public QOpenGLWidget , protected QOpenGLFunctions
{
Q_OBJECT
public:
 
myGlWidget(QWidget *parent = nullptr);
protected:
 
void paintGL() ;
void initializeGL() ;
void resizeEvent(QResizeEvent *e) ;
 
 
private:
QOpenGLShaderProgram *program;
 
QOpenGLVertexArrayObject vao;
QOpenGLBuffer vbo;
 
};
 
#endif // MYGLWIDGET_H

5.源文件代码

 

#include "myglwidget.h"
#include <QtDebug>


//GLSL3.0版本后,废弃了attribute关键字(以及varying关键字),属性变量统一用in/out作为前置关键字
#define GL_VERSION  "#version 330 core\n"

#define GLCHA(x)  #@x           //加单引号,将x变为字符
#define GLSTR(x)  #x            //加双引号,将x变为字符串
#define GET_GLSTR(x) GL_VERSION#x


const char *vsrc = GET_GLSTR(
    layout (location = 0) in vec3 aPos;
    void main(void)
    {
      gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
    }
);

const char *fsrc =GET_GLSTR(
            out vec4 FragColor;
            void main(void)
            {
              FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);
            }
);

//fsrc 等价于 -->   const char *fsrc ="#version 330 core\n"
//                      "out vec4 FragColor;\n"
//                      "void main()\n"
//                      "{\n"
//                      "   FragColor = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
//                      "}\n\0";

myGlWidget::myGlWidget(QWidget *parent):QOpenGLWidget(parent)
{

}


void myGlWidget::paintGL()
{
   // 绘制
  // glViewport(0, 0, width(), height());

   glClear(GL_COLOR_BUFFER_BIT);

   // 渲染Shader
   program->bind(); //绑定激活Program对象
   vao.bind();      //绑定激活vao
   glDrawArrays(GL_TRIANGLES, 0, 3);    //绘制3个定点,样式为三角形
   vao.release();       //解绑
   program->release();  //解绑

}
void myGlWidget::initializeGL()
{

   // 为当前环境初始化OpenGL函数
   initializeOpenGLFunctions();

   glClearColor(1.0f, 1.0f, 1.0f, 1.0f);    //设置背景色为白色

   //1.创建顶点着色器
   QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);
   vshader->compileSourceCode(vsrc);

   //2.创建片元着色器 rgba(1.0f, 1.0f, 0.0f, 1.0f)表示黄色,而alpha值为1.0,表示完全不透明
   QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);
   fshader->compileSourceCode(fsrc);

   //3.创建着色器程序
   program = new QOpenGLShaderProgram;
   program->addShader(vshader);
   program->addShader(fshader);
   program->link();
   program->bind();//激活Program对象


   //4.初始化VBO,将顶点数据存储到buffer中,等待VAO激活后才能释放
   float vertices[] = {
   -0.5f, -0.5f, 0.0f,
   0.5f, -0.5f, 0.0f,
   0.0f, 0.5f, 0.0f
   };

   vbo.create();
   vbo.bind();              //绑定到当前的OpenGL上下文,
   vbo.allocate(vertices, 9*sizeof(GLfloat));
   vbo.setUsagePattern(QOpenGLBuffer::StreamDraw);  //设置为一次修改,多次使用


   //5.初始化VAO,设置顶点数据状态(顶点,法线,纹理坐标等)
   vao.create();
   vao.bind();

   GLint aPos = program->attributeLocation("aPos");        //获取aPos位置
   if(aPos==-1)  //未找到
   {
       return;
   }
   program->setAttributeBuffer(aPos, GL_FLOAT, 0,  3, 0);   //设置顶点属性
   program->enableAttributeArray(aPos); //使能顶点属性


   //6.解绑所有对象
   vao.release();
   vbo.release();
   program->release();


}
void myGlWidget::resizeEvent(QResizeEvent *e)
{


}

 下章学习:

3.QOpenGLWidget-通过着色器来渲染渐变三角形

 

 

 

 

posted @ 2020-09-24 14:34  诺谦  阅读(1804)  评论(0编辑  收藏  举报