魔方网表 让信息化更简单

 找回密码
 注册
查看: 8302|回复: 2

Qt OpenGL教程【1.创建一个OpenGL窗口】

[复制链接]
admin 发表于 2008-12-10 10:30:00 | 显示全部楼层 |阅读模式

png

png
  1. 我假设您对Qt编程已经有了一定的了解,如果您还没有熟悉Qt编程,建议您先学习一下Qt编程的基础知识。

  2. Qt中已经包含了OpenGL模块,具体情况您可以参考Qt OpenGL模块的相关内容。

  3. NeHeWidget类
  4. 这就是我们继承QGLWidget类得到的OpenGL窗口部件类。

  5. (由nehewidget.h展开。)

  6. #include

  7. class NeHeWidget : public QGLWidget
  8. {
  9. Q_OBJECT

  10. 因为QGLWidget类被包含在qgl.h头文件中,所以我们的类就需要包含这个头文件。Q_OBJECT是Qt中的一个专用的宏,具体说明请参见Qt的文档。

  11. public:

  12. NeHeWidget( QWidget* parent = 0, const char* name = 0, bool fs = false );
  13. ~NeHeWidget();

  14. protected:

  15. void initializeGL();
  16. void paintGL();
  17. void resizeGL( int width, int height );

  18. 因为QGLWidget类已经内置了对OpenGL的处理,就是通过对initializeGL()、paintGL()和resizeGL()这个三个函数实现的,具体情况可以参考QGLWidget类的文档。

  19. 因为我们的这个Qt OpenGL教程取材于NeHe OpenGL教程,所以这里就用这个NeHeWidget类来继承QGLWidget类来使用相关OpenGL的功能。

  20. initializeGL()是用来初始化这个OpenGL窗口部件的,可以在里面设定一些有关选项。paintGL()就是用来绘制OpenGL的窗口了,只要有更新发生,这个函数就会被调用。resizeGL()就是用来处理窗口大小变化这一事件的,width和height就是新的大小状态下的宽和高了,另外resizeGL()在处理完后会自动刷新屏幕。

  21. void keyPressEvent( QKeyEvent *e );

  22. 这是Qt里面的鼠标按下事件处理函数。

  23. protected:

  24. bool fullscreen;

  25. 用来保存窗口是否处于全屏状态的变量。

  26. };

  27. (由nehewidget.cpp展开。)

  28. #include "nehewidget.h"

  29. NeHeWidget::NeHeWidget( QWidget* parent, const char* name, bool fs )
  30. : QGLWidget( parent, name )
  31. {
  32. fullscreen = fs;

  33. 保存窗口是否为全屏的状态。

  34. setGeometry( 0, 0, 640, 480 );

  35. 设置窗口的位置,即左上角为(0,0)点,大小为640*480。

  36. setCaption( "NeHe's OpenGL Framework" );

  37. 设置窗口的标题为“NeHe's OpenGL Framework”。

  38. if ( fullscreen )
  39. showFullScreen();

  40. 如果fullscreen为真,那么就全屏显示这个窗口。

  41. }

  42. 这个是构造函数,parent就是父窗口部件的指针,name就是这个窗口部件的名称,fs就是窗口是否最大化。

  43. NeHeWidget::~NeHeWidget()
  44. {
  45. }

  46. 这个是析构函数。

  47. void NeHeWidget::initializeGL()
  48. {
  49. glShadeModel( GL_SMOOTH );

  50. 这一行启用smooth shading(阴影平滑)。阴影平滑通过多边形精细的混合色彩,并对外部光进行平滑。我将在另一个教程中更详细的解释阴影平滑。

  51. glClearColor( 0.0, 0.0, 0.0, 0.0 );

  52. 这一行设置清除屏幕时所用的颜色。如果您对色彩的工作原理不清楚的话,我快速解释一下。色彩值的范围从0.0到1.0。0.0代表最黑的情况,1.0就是最亮的情况。glClearColor后的第一个参数是红色,第二个是绿色,第三个是蓝色。最大值也是1.0,代表特定颜色分量的最亮情况。最后一个参数是Alpha值。当它用来清除屏幕的时候,我们不用关心第四个数字。现在让它为0.0。我会用另一个教程来解释这个参数。

  53. 通过混合三种原色(红、绿、蓝),您可以得到不同的色彩。希望您在学校里学过这些。因此,当您使用glClearColor(0.0, 0.0, 1.0, 0.0 ),您将用亮蓝色来清除屏幕。如果您用glClearColor(0.5, 0.0, 0.0, 0.0 )的话,您将使用中红色来清除屏幕。不是最亮(1.0),也不是最暗 (0.0)。要得到白色背景,您应该将所有的颜色设成最亮(1.0)。要黑色背景的话,您该将所有的颜色设为最暗(0.0)。

  54. glClearDepth( 1.0 );

  55. 设置深度缓存。

  56. glEnable( GL_DEPTH_TEST );

  57. 启用深度测试。

  58. glDepthFunc( GL_LEQUAL );

  59. 所作深度测试的类型。

  60. 上面这三行必须做的是关于depth buffer(深度缓存)的。将深度缓存设想为屏幕后面的层。深度缓存不断的对物体进入屏幕内部有多深进行跟踪。我们本节的程序其实没有真正使用深度缓存,但几乎所有在屏幕上显示3D场景OpenGL程序都使用深度缓存。它的排序决定那个物体先画。这样您就不会将一个圆形后面的正方形画到圆形上来。深度缓存是OpenGL十分重要的部分。

  61. glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );

  62. 真正精细的透视修正。这一行告诉OpenGL我们希望进行最好的透视修正。这会十分轻微的影响性能。但使得透视图看起来好一点。

  63. }

  64. 这个函数中,我们对OpenGL进行所有的设置。我们设置清除屏幕所用的颜色,打开深度缓存,启用smooth shading(阴影平滑),等等。这个例程直到OpenGL窗口创建之后才会被调用。

  65. void NeHeWidget::paintGL()
  66. {
  67. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

  68. 清楚屏幕和深度缓存。

  69. glLoadIdentity();

  70. 重置当前的模型观察矩阵。

  71. }

  72. 这个函数中包括了所有的绘图代码。任何您所想在屏幕上显示的东东都将在此段代码中出现。以后的每个教程中我都会在例程的此处增加新的代码。如果您对OpenGL已经有所了解的话,您可以在 glLoadIdentity()调用之后,函数返回之前,试着添加一些OpenGL代码来创建基本的形。如果您是OpenGL新手,等着我的下个教程。目前我们所作的全部就是将屏幕清除成我们前面所决定的颜色,清除深度缓存并且重置场景。我们仍没有绘制任何东东。

  73. void NeHeWidget::resizeGL( int width, int height )
  74. {
  75. if ( height == 0 )
  76. {
  77. height = 1;
  78. }

  79. 防止height为0。

  80. glViewport( 0, 0, (GLint)width, (GLint)height );

  81. 重置当前的视口(Viewport)。

  82. glMatrixMode( GL_PROJECTION );

  83. 选择投影矩阵。

  84. glLoadIdentity();

  85. 重置投影矩阵。

  86. gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0 );

  87. 建立透视投影矩阵。

  88. glMatrixMode( GL_MODELVIEW );

  89. 选择模型观察矩阵。

  90. glLoadIdentity();

  91. 重置模型观察矩阵。

  92. }

  93. 上面几行为透视图设置屏幕。意味着越远的东西看起来越小。这么做创建了一个现实外观的场景。此处透视按照基于窗口宽度和高度的45度视角来计算。0.1,100.0是我们在场景中所能绘制深度的起点和终点。

  94. glMatrixMode(GL_PROJECTION)指明接下来的两行代码将影响projection matrix(投影矩阵)。投影矩阵负责为我们的场景增加透视。 glLoadIdentity()近似于重置。它将所选的矩阵状态恢复成其原始状态。调用glLoadIdentity()之后我们为场景设置透视图。

  95. glMatrixMode(GL_MODELVIEW)指明任何新的变换将会影响 modelview matrix(模型观察矩阵)。模型观察矩阵中存放了我们的物体讯息。最后我们重置模型观察矩阵。如果您还不能理解这些术语的含义,请别着急。在以后的教程里,我会向大家解释。只要知道如果您想获得一个精彩的透视场景的话,必须这么做。

  96. 这个函数的作用是重新设置OpenGL场景的大小,而不管窗口的大小是否已经改变(假定您没有使用全屏模式)。甚至您无法改变窗口的大小时(例如您在全屏模式下),它至少仍将运行一次——在程序开始时设置我们的透视图。OpenGL场景的尺寸将被设置成它显示时所在窗口的大小。


  97. void NeHeWidget::keyPressEvent( QKeyEvent *e )
  98. {
  99. switch ( e->key() )
  100. {
  101. case Qt::Key_F2:
  102. fullscreen = !fullscreen;
  103. if ( fullscreen )
  104. {
  105. showFullScreen();
  106. }
  107. else
  108. {
  109. showNormal();
  110. setGeometry( 0, 0, 640, 480 );
  111. }
  112. updateGL();
  113. break;

  114. 如果按下了F2键,那么屏幕是否全屏的状态就切换一次。然后再根据需要,显示所要的全屏窗口或者普通窗口。

  115. case Qt::Key_Escape:
  116. close();
  117. }

  118. 如果按下了Escape键,程序退出。

  119. }

  120. main.cpp
  121. (由main.cpp展开。)

  122. #include
  123. #include

  124. Qt的应用程序都是一个QApplication类,所以qapplication.h必须要包含。因为我们在进入OpenGL窗口之前让用户选择是否使用全屏窗口,所以使用了QMessageBox类,所以qmessagebox.h也要包含。

  125. #include "nehewidget.h"


  126. int main( int argc, char **argv )
  127. {
  128. bool fs = false;

  129. 我们把这个布尔型变量的初始值设置为false。

  130. QApplication a(argc,argv);

  131. 每一个Qt应用程序都使用QApplication类。

  132. switch( QMessageBox::information( 0,
  133. "Start FullScreen?",
  134. "Would You Like To Run In Fullscreen Mode?",
  135. QMessageBox::Yes,
  136. QMessageBox::No | QMessageBox::Default ) )
  137. {
  138. case QMessageBox::Yes:
  139. fs = true;
  140. break;
  141. case QMessageBox::No:
  142. fs = false;
  143. break;
  144. }

  145. 这里弹出一个消息对话框,让用户选择是否使用全屏模式。

  146. NeHeWidget w( 0, 0, fs );

  147. 创建一个NeHeWidget对象。

  148. a.setMainWidget( &w );

  149. 设置应用程序的主窗口部件为w。

  150. w.show();

  151. 显示w。

  152. return a.exec();

  153. 程序返回。

  154. }
复制代码
本课程的源代码
lesson01.tar.rar (15.77 KB, 下载次数: 2390)
刘家媳妇 发表于 2012-3-24 18:54:49 | 显示全部楼层
百年不遇的好帖子,不得不顶
回复

使用道具 举报

宏宇 发表于 2012-8-10 10:32:25 | 显示全部楼层
看看                                          
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|魔方软件 ( 京ICP备08008787号 )

京公网安备 11010702001722号

GMT+8, 2024-5-5 09:16 , Processed in 0.066664 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表