• Qt OpenGL 创建一个OpenGL窗口


    在这个教程里,我们将在Qt Creator环境中创建OpenGL对象,它将显示一个空的OpenGL窗口,可以在窗口和全屏模式下切换,按ESC退出,它将是我们后面应用程序的基础框架。
    Qt中写OpenGL与在VC上还是有不少差别的,对Qt机制不熟悉的朋友,请先大致了解下Qt的机制,再往下看教程。
    程序运行时效果如下:
    下面进入教程:
    新建空的Qt项目,项目名称为myOpenGL,然后往项目中添加新的C++类,类名为MyGLWidget,基类为QGLWidget,类型信息选择“继承自QWidget”。添加完成后,打开项目文件myOpenGL.pro,将代码补全如下:
     1 TARGET = myOpenGL
     2 TEMPLATE = app
     3  
     4 HEADERS += 
     5     myglwidget.h
     6  
     7 SOURCES += 
     8     main.cpp 
     9     myglwidget.cpp
    10  
    11 QT       += core gui
    12  
    13 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    14  
    15 QT       += opengl

    然后保存该文件。下面打开myglwidget.h文件,将类声明补全如下:

     1 #ifndef MYGLWIDGET_H
     2 #define MYGLWIDGET_H
     3  
     4 #include <QWidget>
     5 #include <QGLWidget>
     6  
     7 class MyGLWidget : public QGLWidget
     8 {
     9     Q_OBJECT
    10 public:
    11     explicit MyGLWidget(QWidget *parent = 0);
    12     ~MyGLWidget();
    13     
    14 protected:
    15     //对3个纯虚函数的重定义
    16     void initializeGL();
    17     void resizeGL(int w, int h);
    18     void paintGL();
    19     
    20     void keyPressEvent(QKeyEvent *event);           //处理键盘按下事件
    21     
    22 private:
    23     bool fullscreen;                                //是否全屏显示
    24 };
    25  
    26 #endif // MYGLWIDGET_H

    再到myglwidget.cpp文件中先包含#include<GL/glu.h>,#include<QKeyEvent>头文件,然后添加类中函数的定义:

     1 MyGLWidget::MyGLWidget(QWidget *parent) :
     2     QGLWidget(parent)
     3 {
     4     fullscreen = false;
     5 }
     6  
     7 MyGLWidget::~MyGLWidget()
     8 {
     9     
    10 }
    构造函数中只需对fullscreen初始化,析构函数暂时并不需要做什么。
    下面是initializeGL()的定义:
     1 void MyGLWidget::initializeGL()                         //此处开始对OpenGL进行所以设置
     2 {
     3     glClearColor(0.0, 0.0, 0.0, 0.0);                   //黑色背景
     4     glShadeModel(GL_SMOOTH);                            //启用阴影平滑
     5     
     6     glClearDepth(1.0);                                  //设置深度缓存
     7     glEnable(GL_DEPTH_TEST);                            //启用深度测试
     8     glDepthFunc(GL_LEQUAL);                             //所作深度测试的类型
     9     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //告诉系统对透视进行修正
    10 }
    glClearColor()函数用来设置清除屏幕时使用的颜色,4个参数分别用来设置红、绿、蓝颜色分量和Alpha值,它们的取值范围都是0.0~1.0,这里4个参数都为0.0,表示纯黑色。然后设置了阴影平滑,这样可以使色彩和光照更加精细。
    接下来的三行必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断地对物体进入屏幕内部有多深进行跟踪。我们本节的程序其实没有真正的使用深度缓存,但几乎所有在屏幕上显示3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。这样就不会将一个圆形后面的正方形画到圆形前面来。深度缓存是OpenGL十分重要的部分。最后我们希望进行最好的透视修正。这会十分轻微的影响性能,但使得透视图看起来好一点。
    下面是resizeGL()的定义:
     1 void MyGLWidget::resizeGL(int w, int h)                 //重置OpenGL窗口的大小
     2 {
     3     glViewport(0, 0, (GLint)w, (GLint)h);               //重置当前的视口
     4     glMatrixMode(GL_PROJECTION);                        //选择投影矩阵
     5     glLoadIdentity();                                   //重置投影矩阵
     6     //设置视口的大小
     7     gluPerspective(45.0, (GLfloat)w/(GLfloat)h, 0.1, 100.0);
     8     glMatrixMode(GL_MODELVIEW);                         //选择模型观察矩阵
     9     glLoadIdentity();                                   //重置模型观察矩阵
    10 }
    glViewport()函数用来设置视口的大小。使用glMatrixMode()设置了投影矩阵,投影矩阵用来为场景增加透视,后面使用了glLoadIdentity()重置投影矩阵,这样可以将投影矩阵恢复到初始状态。gluPerspective()用来设置透视投影矩阵,这里设置视角为45°,纵横比为窗口的纵横比,最近的位置为0.1,最远的位置为100,这两个值是场景中所能绘制的深度的临界值。可以想象,离我们眼睛比较近的东西看起来比较大,而比较远的东西看起来就比较小。最后设置并重置了模型视图矩阵。
    下面是paintGL()的定义:
    1 void MyGLWidget::paintGL()                              //从这里开始进行所以的绘制
    2 {
    3     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
    4     glLoadIdentity();                                   //重置当前的模型观察矩阵
    5 }
    paintGL()函数包含了所以的绘图代码,任何想在屏幕上显示的东西都将在此段代码中出现。以后每个教程中都会在这个函数增加代码,已达到绘图目的。
    最后是键盘事件处理函数KeyPressEvent()的定义,由于这与OpenGL关系不大,不做过多解释:
     1 void MyGLWidget::keyPressEvent(QKeyEvent *event)
     2 {
     3     switch (event->key()) 
     4     {
     5     //F1为全屏和普通屏的切换键
     6     case Qt::Key_F1:
     7         fullscreen = !fullscreen;
     8         if (fullscreen)
     9         {
    10             showFullScreen();
    11         }
    12         else
    13         {
    14             showNormal();
    15         }
    16         updateGL();
    17         break;
    18     //ESC为退出键
    19     case Qt::Key_Escape:
    20         close();
    21     }
    22 }

    最后再向项目中添加main.cpp文件,更改内容如下:

     1 #include <QApplication>
     2 #include "myglwidget.h"
     3  
     4 int main(int argc, char *argv[])
     5 {
     6     QApplication app(argc, argv);
     7     
     8     MyGLWidget w;
     9     w.resize(400, 300);
    10     w.show();
    11     
    12     return app.exec();
    13 }

    现在就可以运行程序查看效果了!

  • 相关阅读:
    「题解」:07.16NOIP模拟T1:礼物
    「题解」:07.16NOIP模拟T2:通讯
    「题解」:图论专题总结
    07.07NOIP模拟赛
    [复习]平衡树splay
    「题解」:[组合数学][DP]:地精部落
    「题解」:[组合数学]:Perm 排列计数
    「题解」:[组合数学]:排队
    dp 杂题
    插头 dp 总结
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14047782.html
Copyright © 2020-2023  润新知