【Qt】QGLWidget窗口中gl函数的理解及运行流程

https://blog.csdn.net/qq_35263780/article/details/77815957

QGLWidget类的官方文档:http://doc.qt.io/qt-5.6/qglwidget.html

主要是有如下三个函数需要重写:

 
  1. class MyGLDrawer : public QGLWidget

  2. {

  3. Q_OBJECT // must include this if you use Qt signals/slots

  4.  
  5. public:

  6. MyGLDrawer(QWidget *parent)

  7. : QGLWidget(parent) {}

  8.  
  9. protected:

  10.  
  11. void initializeGL() //初始化当前的opengl环境

    扫描二维码关注公众号,回复: 2931210 查看本文章
  12. {

  13. // Set up the rendering context, define display lists etc.:

  14. ...

  15. glClearColor(0.0, 0.0, 0.0, 0.0);

  16. glEnable(GL_DEPTH_TEST);

  17. ...

  18. }

  19.  
  20. void resizeGL(int w, int h) //主要用来对渲染区域的高度和宽度进行一些变化处理

  21. {

  22. // setup viewport, projection etc.:

  23. glViewport(0, 0, (GLint)w, (GLint)h);

  24. ...

  25. glFrustum(...);

  26. ...

  27. }

  28.  
  29. void paintGL() //绘制

  30. {

  31. // draw the scene:

  32. ...

  33. glRotatef(...);

  34. glMaterialfv(...);

  35. glBegin(GL_QUADS);

  36. glVertex3f(...);

  37. glVertex3f(...);

  38. ...

  39. glEnd();

  40. ...

  41. }

  42.  
  43. };

关于这三个虚函数,调用顺序及功能如下:参考http://blog.csdn.net/mahabharata_/article/details/52201422

先调用initializeGL(),初始化OpenGL的绘图环境(初始化窗口在initWidget()中实现),后调用resizeGL(),对渲染区域进行规定(包括大小以及投影方式),再调用paintGL()进行绘制;当窗口大小改变时会再度调用resizeGL()和paintGL(),当update()被执行时(常与QTime连用),也会再度调用paintGL进行重绘。

程序开始>>构造函数>>initializeGL()>>resizeGL()>>paintGL() 

>>若用户调用updateGL()函数>>引起paintGL()函数的调用。

>>若窗口位置或者尺寸改变>>调用resizeGL()>>调用paintGL()

关于在resizeGL()中投影方式设定的一些理解:

http://anony3721.blog.163.com/blog/static/51197420113206471827/

http://www.xuebuyuan.com/1831290.html

//包括有  视图矩阵GL_MODELVIEW、投影矩阵:GL_PROJECTION、纹理矩阵GL_TEXTURE
//如果乘以变换矩阵(平移, 缩放, 旋转), 那相乘之后, 模型的位置被变换;
//如果乘以投影矩阵(将3D物体投影到2D平面), 相乘后, 模型的投影方式被设置;
//如果乘以纹理矩阵(), 模型的纹理方式被设置.

关于其中使用的一些函数的理解和解释:

(若有问题请多加指出

1.

QTimer clk;

clk.start(30); //30毫秒计时  时间度量

QObject::connect(&clk, SIGNAL(timeout()), this, SLOT(updateWindow()));   // 发送者  信号  接收者  执行成员(函数)

2.

initWidget(); //初始化窗口

setGeometry(0, 200, 640, 480);  //相对于父窗体来说的一种对子窗体进行位置设置的方法

//想要setGeometry有效,控件就不能在布局里。  

//如果使用了布局,控件大小有布局自动控制。

setWindowTitle(tr("opengl demo")); //窗口名称

//如果opengl窗口在ui界面中设置过了,这两句话就没用了

3.

initializeGL();//该函数用来初始化当前的 OpenGL 环境

loadGLTextures();                                    //载入纹理

glEnable(GL_TEXTURE_2D);                            // Enable Texture Mapping ( NEW ) 
glShadeModel(GL_SMOOTH);                             // Enable Smooth Shading  
glClearColor(0.0, 0.0, 0.0, 0.0);                    // Black Background //设置清除颜色 
glClearDepth(1.0);                                   // Depth Buffer Setup  //指定深度缓冲区中每个像素需要的值  
glEnable(GL_DEPTH_TEST);                             // Enables Depth Testing  开启深度测试
glDepthFunc(GL_LEQUAL);                              // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // Really Nice Perspective Calculations

4.

void glClear(GLbitfield mask):

GL_COLOR_BUFFER_BIT: 当前可写的颜色缓冲
GL_DEPTH_BUFFER_BIT: 深度缓冲
GL_ACCUM_BUFFER_BIT: 累积缓冲
GL_STENCIL_BUFFER_BIT: 模板缓冲

glClear()函数的作用是用当前缓冲区清除值,也就是glClearColor或者glClearDepth、glClearIndex、glClearStencil、glClearAccum等函数所指定的值来清除指定的缓冲区,也可以使用glDrawBuffer一次清除多个颜色缓存

清除颜色缓冲区的作用是,防止缓冲区中原有的颜色信息影响本次绘图(注意!即使认为可以直接覆盖原值,也是有可能会影响的),当绘图区域为整个窗口时,就是通常看到的,颜色缓冲区的清除值就是窗口的背景颜色。所以,这两条清除指令并不是必须的:比如对于静态画面只需要设置一次,比如不需要背景色/背景色为白色。  链接:https://www.zhihu.com/question/40783239/answer/88480756
 

5.

void glLoadIdentity():将当前矩阵重置为单位矩阵【错误解释:将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作】
通俗解释glLoadIdentity(),glPushMatrix(),glPopMatrix()的作用

6.

void glTranslatef (GLfloat x, GLfloat y, GLfloat z);    沿着下x,y,z轴方向平移

void glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z); 沿x,y,z轴旋转

旋转反向:   做(0,0,0)到(x,y,z)的向量,用右手握住这条向量,大拇指指向向量的正方向,四指环绕的方向就是旋转的方向

void glScalef (GLfloat x, GLfloat y, GLfloat z);  将模型按x,y,z方向分别拉伸几倍;参数也可取负数,也可以理解为先关于某轴翻转180°,再缩放

7.

glGenTextures (GLsizei n, GLuint *textures);

开辟一个纹理内存,内存指向textur

void glBindTexture (GLenum target, GLuint texture);  

target
指明了纹理要绑定到的目标。必须是下面中的一个:

GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D,

GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY,

GL_TEXTURE_RECTANGLE, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_BUFFER, GL_TEXTURE_2D_MULTISAMPLE 或者 GL_TEXTURE_2D_MULTISAMPLE_ARRAY。

texture
指明一张纹理的名字    有多重纹理时一般设为数组当一张纹理被绑定后,GL对于这个目标的操作都会影响到这个被绑定的纹理。也就是说,这个纹理目标成为了被绑定到它上面的纹理的别名,而纹理名称为0则会引用到它的默认纹理。

当使用glBindTexture绑定一张纹理后,它会一直保持活跃状态知道另一张纹理被绑定到同一个目标上,或者这个被绑定的纹理被删除了(使用glDeleteTextures)。

【不能放在glBegin()和glEnd()函数对中】

8.

void glBegin (GLenum mode);

……

void glEnd (void);
mode:创建元素的类型,比如:点,线等。可以是以下数值:
GL_POINTS:把每个顶点作为一个点进行处理,顶点n定义了点n,绘制N个点。
GL_LINES: 把每个顶点作为一个独立的线段,顶点2n-1和2n之间定义了n条线段,绘制N/2条线段
GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,绘制n-1条线段。
GL_LINE_LOOP: 绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,绘制n条线段。
GL_TRIANGLES: 把每个顶点作为一个独立的三角形,顶点3n-2,3n-1和3n定义了第n个三角形,绘制了N/3个三角形。
GL_TRIANGLE_STPIP:绘制一组相连的三角形,对于奇数n,顶点n,n+1,和n+2定义了第n个三角形;对于偶数n,顶点n+1,n和n+2定义了第n个三角形,绘制N-2个三角
形。
GL_QUADS: 绘制由四个顶点组成的一组单独的四边形。顶点4n-3,4n-2,4n-1和4n定义了第n个四边形。绘制了N/4个四边形。

GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1,2n,2n+2和2n+1定义了第n个四边形,绘制了N/2-1个四边形。

GL_POLYGON:绘制了一个凸多边形。顶点1到n定义了这个多边形。

[  glTranslatef(),glScalef(),glRotatef()等此类几何变换接口的作用是对当前模型空间进行几何变换,在glBegin()和glEnd()之间是无效的。因此,对模型的位置进行转换,要在glBegin()和glEnd()接口之前进行处理。]

8.

void glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz);  

指定参数设置当前的法线向量 ,与光照有关 物体是否能被照射

void glTexCoord2f (GLfloat s, GLfloat t);

一个完全纹理的四个顶点的坐标分别是(0.0f, 0.0f)、(0.0f, 1.0f)、(1.0f, 1.0f)、(1.0f, 0.0f),分别对应左下、左上、右上、右下角  →x ↑y

void glVertex3f (GLfloat x, GLfloat y, GLfloat z);

该函数主要与glTexCoord2f()配合使用,glTexCoord2f()是配置纹理坐标,glVertex3f()是配置图形坐标。

[ 载入的位图大小必须是M*M,M是2的某次方,如32,64,128等。]

9.

void glViewport (GLint x, GLint y, GLsizei width, GLsizei height);

在窗口中定义一个像素矩形,最终将图像映射到这个矩形中

void glFrustum(GLdouble left, GLdouble Right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
这个函数的参数只定义近裁剪平面的左下角点和右上角点的三维空间坐标,即(left,bottom,-near)和(right,top,-near);
最后一个参数far是远裁剪平面的离视点的距离值,其左下角点和右上角点空间坐标由函数根据透视投影原理自动生成。near和far表示离视点的远近,它们总为正值(near/far 必须>0)。

10.

OpenGL API 之 glTexImage2D

void glTexImage2D( GLenum target,         :  GL_TEXTURE_2D, GL_PROXY_TEXTURE_2D……指定纹理单元的类型是哪一种
GLint level,                                                   :指定纹理单元的层次,非mipmap纹理level设置为0,mipmap纹理设置为纹理的层级
GLint internalFormat,                                  :指定OpenGL是如何管理纹理单元中数据格式的。网络上很多解释说这个参数必须和后面的                                                                                  format参数一样,这个说法是不正确的
GLsizei width,                                               :  指定纹理单元的宽度
GLsizei height,                                             :  指定纹理单元的高度
GLint border,                                                :  指定纹理单元的边框,如果包含边框取值为1,不包含边框取值为0
GLenum format,                                           :  指定data所指向的数据的格式
GLenum type,                                               :  指定data所指向的数据的类型
const GLvoid * data);                                    :  数据指针

//当所显示的纹理比加载的要小时,用 GL_LINEAR处理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);


//当所显示的纹理比加载的要大时,用 GL_LINEAR处理
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

猜你喜欢

转载自blog.csdn.net/wang13342322203/article/details/81866556