现在的位置: 首页 > 综合 > 正文

OpenGL教程之显示列表

2013年09月21日 ⁄ 综合 ⁄ 共 5347字 ⁄ 字号 评论关闭

Jeff Molofee(NeHe)的OpenGL教程
- 显示列表

  原 文Lesson 12: Display Lists
  译 者Marhoo


  这次我将教你如何使用显示列表,显示列表将加快程序的速度,而且可以减少代码的长度。
  当你在制作游戏里的小行星场景时,每一层上至少需要两个行星,你可以用OpenGL中的多边形来构造每一个行星。聪明点的做法是做一个循环,每个循环画出行星的一个面,最终你用几十条语句画出了一个行星。每次把行星画到屏幕上都是很困难的。当你面临更复杂的物体时你就会明白了。
  那么,解决的办法是什么呢?用现实列表,你只需要一次性建立物体,你可以贴图,用颜色,想怎么弄就怎么弄。给现实列表一个名字,比如给小行星的显示列表命名为“asteroid”。现在,任何时候我想在屏幕上画出行星,我只需要调用glCallList(asteroid)。之前做好的小行星就会立刻显示在屏幕上了。因为小行星已经在显示列表里建造好了,OpenGL不会再计算如何构造它。它已经在内存中建造好了。这将大大降低CPU的使用,让你的程序跑的更快。
  那么,开始学习咯。我称这个DEMOQ-Bert显示列表。最终这个DEMO将在屏幕上画出15个立方体。每个立方体都由一个盒子和一个顶构成,顶部是一个单独的显示列表,盒子没有顶。
  这一课是建立在第六课的基础上的,我将重写大部分的代码,这样容易看懂。下面的这些代码在所有的课程中差不多都用到了。

  #include <windows.h>                    // Header File For Windows
  #include <stdio.h>                     // Header File For Standard Input/Output
  #include <gl/gl.h>                     // Header File For The OpenGL32 Library
  #include <gl/glu.h>                     // Header File For The GLu32 Library
  #include <gl/glaux.h>                    // Header File For The GLaux Library

  HDC hDC=NULL;                        // Private GDI Device Context
  HGLRC hRC=NULL;                       // Permanent Rendering Context
  HWND hWnd=NULL;                       // Holds Our Window Handle
  HINSTANCE hInstance;                    // Holds The Instance Of The Application

  bool keys[256];                       // Array Used For The Keyboard Routine
  bool active=TRUE;                      // Window Active Flag Set To TRUE By Default
  bool fullscreen=TRUE;                    // Fullscreen Flag Set To Fullscreen Mode By Default

  下面设置变量。首先是存储纹理的变量,然后两个新的变量用于显示列表。这些变量是指向内存中显示列表的指针。命名为boxtop
  然后用两个变量xloop,yloop表示屏幕上立方体的位置,两个变量xrotyrot表示立方体的旋转。

  GLuint texture[1];                     // Storage For One Texture
  GLuint box;                         // Storage For The Display List
  GLuint top;                         // Storage For The Second Display List
  GLuint xloop;                        // Loop For X Axis
  GLuint yloop;                        // Loop For Y Axis

  GLfloat xrot;                        // Rotates Cube On The X Axis
  GLfloat yrot;                        // Rotates Cube On The Y Axis

  接下来建立两个颜色数组。

  static GLfloat boxcol[5][3]=                // Array For Box Colors
  {
      // Bright: Red, Orange, Yellow, Green, Blue
      {1.0f,0.0f,0.0f},{1.0f,0.5f,0.0f},{1.0f,1.0f,0.0f},{0.0f,1.0f,0.0f},{0.0f,1.0f,1.0f}
  };

  static GLfloat topcol[5][3]=                // Array For Top Colors
  {
      // Dark: Red, Orange, Yellow, Green, Blue
      {.5f,0.0f,0.0f},{0.5f,0.25f,0.0f},{0.5f,0.5f,0.0f},{0.0f,0.5f,0.0f},{0.0f,0.5f,0.5f}
  };

  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // Declaration For WndProc

  现在正式开始建立显示列表。你可能注意到了,所有创造盒子的代码都在第一个显示列表里,所有创造顶部的代码都在另一个列表里。我会努力解释这些细节。

  GLvoid BuildLists()                    // Build Box Display List
  {

  开始的时候我们告诉OpenGL我们要建立两个显示列表。glGenLists(2)建立了两个显示列表的空间,并返回第一个显示列表的指针。“box”指向第一个显示列表,任何时候调用“box”第一个显示列表就会显示出来。

      box=glGenLists(2);                 // Building Two Lists

  现在开始构造第一个显示列表。我们已经申请了两个显示列表的空间了,并且有box指针指向第一个显示列表。所以现在我们应该告诉OpenGL要建立什么类型的显示列表。
  我们用glNewList()命令来做这个事情。你一定注意到了box是第一个参数,这表示OpenGL将把列表存储到box所指向的内存空间。第二个参数GL_COMPILE告诉OpenGL我们想预先在内存中构造这个列表,这样每次画的时候就不必重新计算怎么构造物体了。
  GL_COMPILE类似于编程。在你写程序的时候,把它装载到编译器里,你每次运行程序都需要重新编译。而如果他已经编译成了.exe文件,那么每次你只需要点击那个.exe文件就可以运行它了,不需要编译。当OpenGL编译过显示列表后,就不需要再每次显示的时候重新编译它了。这就是为什么用显示列表可以加快速度。

      glNewList(box,GL_COMPILE);             // New Compiled box Display List

  下面这部分的代码画出一个没有顶部的盒子,它不会出现在屏幕上,只会存储在显示列表里。
  你可以在glNewList()glEngList()中间加上任何你想加上的代码。可以设置颜色,贴图等等。唯一不能加进去的代码就是会改变显示列表的代码。显示列表一旦建立,你就不能改变它。
  比如你想加上glColor3ub(rand()%255,rand()%255,rand()%255),使得每一次画物体时都会有不同的颜色。但因为显示列表只会建立一次,所以每次画物体的时候颜色都不会改变。物体将会保持第一次建立显示列表时的颜色。如果你想改变显示列表的颜色,你只有在调用显示列表之前改变颜色。后面将详细解释这一点。

          glBegin(GL_QUADS);             // Start Drawing Quads

              // Bottom Face
              glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Top Right Of The Texture and Quad
              glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Top Left Of The Texture and Quad
              glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
              glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad

              // Front Face
              glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad
              glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);   // Bottom Right Of The Texture and Quad
              glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);   // Top Right Of The Texture and Quad
              glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad

              // Back Face
              glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
              glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
              glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);   // Top Left Of The Texture and Quad
              glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Left Of The Texture and Quad

              // Right face
              glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);  // Bottom Right Of The Texture and Quad
              glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);   // Top Right Of The Texture and Quad
              glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);   // Top Left Of The Texture and Quad
              glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);   // Bottom Left Of The Texture and Quad

              // Left Face
              glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f

【上篇】
【下篇】

抱歉!评论已关闭.