のところです。六角形を一つ描くだけならばこのままでも問題はありませんが、同じ六角形を異なる場所に多数描く 場合、上のプログラム部分を(サブルーチン化して)六角形の数だけコールするのは考えものです。プログラムの実行 時に、六角形の数だけ三角関数の計算が繰り返されることになるからです。このような場合にディスプレイリストを 利用すると大変高速にプログラムが実行されます。
ディスプレイリストでは六角形を描く上のOpenGLプログラムの一群を一つの単位として登録し、非負整数のラ ベル(指標番号)をつけます。その後、登録した指標番号を呼び出すことだけで、一連のOpenGLプログラムがまと めて実行されます。その際、三角関数の計算は、その計算結果の数値データだけを保持しているので、登録したディ スプレイリストを呼び出すたびに三角関数の計算が行われるようなことはありません。一般にディスプレイリストで は、一まとめのOpenGL関数の実行を常に最適化するように設計されているので、ディスプレイリストを利用する ことにより、利用しない場合よりも実行速度が遅くなることはありません。
ディスプレイリストを定義するには、以下の様にglNewListとglEndListでマクロ化したい一連のOpenGL関 数を挟みます。
GLuint int list_no = 1;
glNewList(list_no, GL_COMPILE);
.
.
.
.
glEndList();
これで1番のディスプレイリストが定義されます。あとはプログラム中の適当な位置で
glCallList(1);
と呼べば1番のディスプレイリストが実行されます。同様に2番、3番...のディスプレイリストも定義、実行が可能 です。一般には、ディスプレイリストを利用すべき場面として(1) プログラム中に何度も利用される物体の定義、
(2)行列操作、(3)照明処理、(4)テクスチャの定義、等があります。それでは、サンプルプログラムを見てみましょ う。
このプログラムでは同じ半径の円をたくさん描いています。その位置はすこしずつずれていて、原点は螺旋の上 にのっています。透視法射影のため遠くの円が小さく見えます。このようなプログラムをディスプレイリストを使わ ずに書けば、プログラムは複雑になり、また実行速度が大変遅くなってしまいます。
2.31ディスプレイリスト 59
7
6
4
5 circles.c
/*
* circles.c
\*
An OpenGL sample program.
- No Lighting.
- Display List.
*/
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "aux.h"
#define PI 3.14159265358979
#define TWOPI (2*PI)
GLuint list1 = 1;
void initial(void) {
int i;
GLfloat x,y;
glNewList(list1, GL_COMPILE);
glColor3f(1.0, 1.0, 0.0);
glTranslatef(1.5, 0.0, 0.0);
glBegin(GL_LINE_LOOP);
for (i=0; i<100; i++) {
x = 0.8*cos(TWOPI*i/100.0);
y = 0.8*sin(TWOPI*i/100);
glVertex3f(x,y,0.0);
}
glEnd();
glTranslatef(-1.5, 0.0, 0.0);
glRotatef(20.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 0.0, -1.0);
glEndList();
glShadeModel(GL_FLAT);
}
void display (void) {
int i;
glClear(GL_COLOR_BUFFER_BIT);
glTranslatef (0.0, 0.0, -5.0);
glPushMatrix();
for (i=0; i<200; i++)
glCallList(list1);
glPopMatrix();
glFlush();
void reshape(int width, int height) {
GLdouble ang = 60.0;
GLdouble near = 3.0;
GLdouble far = 1000.0;
glViewport (0, 0, width, height);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (ang, (GLdouble)width/(GLdouble)height, near, far);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
}
int main(int argc, char** argv) {
auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
auxInitPosition (0, 0, 500, 500);
auxInitWindow (argv[0]);
initial();
auxReshapeFunc (reshape);
auxMainLoop(display);
}
n endofcircles.c/
ディスプレイリストの指標番号には非負整数を使います。この番号は上のサンプルプログラムのようにプログラマ が自分で決めることが可能ですが、大規模なOpenGLプログラムにおいて多数のディスプレイリストを使用する場 合、重複した指標番号を選んでしまう危険があります。そこでOpenGLには未使用の指標番号を自動的に生成して くれる関数が用意されています。
未使用の指標番号を一つ生成する
GLuint glGenLists(1);
この関数の返値が未使用の指標番号です。未使用の指標番号が一度にn個欲しい時には
未使用の指標番号をn個生成する
GLuint glGenLists(n);
とすると、未使用の指標番号をn個確保します。その返値`から`+1,`+2,111,`+n01までを指標番号として利 用することができます。