2 * This program is under the GNU GPL.
3 * Use at your own risk.
5 * written by David Bucciarelli (tech.hmw@plus.it)
18 #include "glut_wrap.h"
22 static int fullscreen
= 1;
25 static int WIDTH
= 640;
26 static int HEIGHT
= 480;
29 static GLint Frames
= 0;
32 #define SPHERE_RADIUS 0.75f
34 #define TEX_CHECK_WIDTH 256
35 #define TEX_CHECK_HEIGHT 256
36 #define TEX_CHECK_SLOT_SIZE (TEX_CHECK_HEIGHT/16)
37 #define TEX_CHECK_NUMSLOT (TEX_CHECK_HEIGHT/TEX_CHECK_SLOT_SIZE)
39 #define TEX_REFLECT_WIDTH 256
40 #define TEX_REFLECT_HEIGHT 256
41 #define TEX_REFLECT_SLOT_SIZE (TEX_REFLECT_HEIGHT/16)
42 #define TEX_REFLECT_NUMSLOT (TEX_REFLECT_HEIGHT/TEX_REFLECT_SLOT_SIZE)
45 #define M_PI 3.1415926535
48 #define EPSILON 0.0001
50 #define clamp255(a) ( (a)<(0.0f) ? (0.0f) : ((a)>(255.0f) ? (255.0f) : (a)) )
53 #define fabs(x) ((x)<0.0f?-(x):(x))
56 #define vequ(a,b) { (a)[0]=(b)[0]; (a)[1]=(b)[1]; (a)[2]=(b)[2]; }
57 #define vsub(a,b,c) { (a)[0]=(b)[0]-(c)[0]; (a)[1]=(b)[1]-(c)[1]; (a)[2]=(b)[2]-(c)[2]; }
58 #define dprod(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
59 #define vnormalize(a,b) { \
60 register float m_norm; \
61 m_norm=sqrt((double)dprod((a),(a))); \
66 static GLubyte checkmap
[TEX_CHECK_HEIGHT
][TEX_CHECK_WIDTH
][3];
67 static GLuint checkid
;
68 static int checkmap_currentslot
= 0;
70 static GLubyte reflectmap
[TEX_REFLECT_HEIGHT
][TEX_REFLECT_WIDTH
][3];
71 static GLuint reflectid
;
72 static int reflectmap_currentslot
= 0;
74 static GLuint lightdlist
;
75 static GLuint objdlist
;
77 static float lightpos
[3] = { 2.1, 2.1, 2.8 };
78 static float objpos
[3] = { 0.0, 0.0, 1.0 };
80 static float sphere_pos
[TEX_CHECK_HEIGHT
][TEX_REFLECT_WIDTH
][3];
84 static float fogcolor
[4] = { 0.05, 0.05, 0.05, 1.0 };
86 static float obs
[3] = { 7.0, 0.0, 2.0 };
89 static float alpha
= -90.0;
90 static float beta
= 90.0;
93 static int bfcull
= 1;
94 static int poutline
= 0;
96 static int showcheckmap
= 1;
97 static int showreflectmap
= 1;
98 static int joyavailable
= 0;
99 static int joyactive
= 0;
104 dir
[0] = sin(alpha
* M_PI
/ 180.0);
105 dir
[1] = cos(alpha
* M_PI
/ 180.0) * sin(beta
* M_PI
/ 180.0);
106 dir
[2] = cos(beta
* M_PI
/ 180.0);
108 if (dir
[0] < 1.0e-5 && dir
[0] > -1.0e-5)
110 if (dir
[1] < 1.0e-5 && dir
[1] > -1.0e-5)
112 if (dir
[2] < 1.0e-5 && dir
[2] > -1.0e-5)
115 obs
[0] += v
* dir
[0];
116 obs
[1] += v
* dir
[1];
117 obs
[2] += v
* dir
[2];
121 special(int k
, int x
, int y
)
140 key(unsigned char k
, int x
, int y
)
193 joyactive
= (!joyactive
);
203 showcheckmap
= (!showcheckmap
);
206 showreflectmap
= (!showreflectmap
);
211 glDisable(GL_CULL_FACE
);
215 glEnable(GL_CULL_FACE
);
221 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
225 glPolygonMode(GL_FRONT_AND_BACK
, GL_LINE
);
231 XMesaSetFXmode(fullscreen
? XMESA_FX_FULLSCREEN
: XMESA_FX_WINDOW
);
232 fullscreen
= (!fullscreen
);
239 reshape(int w
, int h
)
243 glViewport(0, 0, w
, h
);
244 glMatrixMode(GL_PROJECTION
);
246 gluPerspective(45.0, w
/ (float) h
, 0.8, 40.0);
247 glMatrixMode(GL_MODELVIEW
);
252 printstring(void *font
, char *string
)
256 len
= (int) strlen(string
);
257 for (i
= 0; i
< len
; i
++)
258 glutBitmapCharacter(font
, string
[i
]);
265 glColor4f(0.5, 0.5, 0.5, 0.5);
266 glRecti(40, 40, 600, 440);
269 glColor3f(0.0, 0.0, 1.0);
270 glRasterPos2i(300, 420);
271 printstring(GLUT_BITMAP_HELVETICA_18
, "Help");
273 glRasterPos2i(60, 390);
274 printstring(GLUT_BITMAP_HELVETICA_12
, "h - Toggle Help");
275 glRasterPos2i(60, 370);
276 printstring(GLUT_BITMAP_HELVETICA_12
, "f - Toggle Fog");
277 glRasterPos2i(60, 350);
278 printstring(GLUT_BITMAP_HELVETICA_12
, "b - Toggle Back face culling");
279 glRasterPos2i(60, 330);
280 printstring(GLUT_BITMAP_HELVETICA_12
, "p - Toggle Wire frame");
281 glRasterPos2i(60, 310);
282 printstring(GLUT_BITMAP_HELVETICA_12
, "Arrow Keys - Rotate");
283 glRasterPos2i(60, 290);
284 printstring(GLUT_BITMAP_HELVETICA_12
, "a - Increase velocity");
285 glRasterPos2i(60, 270);
286 printstring(GLUT_BITMAP_HELVETICA_12
, "z - Decrease velocity");
288 glRasterPos2i(60, 250);
290 printstring(GLUT_BITMAP_HELVETICA_12
,
291 "j - Toggle jostick control (Joystick control available)");
293 printstring(GLUT_BITMAP_HELVETICA_12
,
294 "(No Joystick control available)");
296 glRasterPos2i(60, 230);
297 printstring(GLUT_BITMAP_HELVETICA_12
,
298 "To move the light source: s - left, d - right, e - far, x - near, w - down r - up");
299 glRasterPos2i(60, 210);
300 printstring(GLUT_BITMAP_HELVETICA_12
,
301 "To move the mirror sphere: j - left, k - right, i - far, m - near, u - down o - up");
303 glRasterPos2i(60, 190);
304 printstring(GLUT_BITMAP_HELVETICA_12
,
305 "1 - Toggle the plane texture map window");
307 glRasterPos2i(60, 170);
308 printstring(GLUT_BITMAP_HELVETICA_12
,
309 "2 - Toggle the sphere texture map window");
313 seelight(float p
[3], float dir
[3])
315 float c
[3], b
, a
, d
, t
, dist
[3];
319 a
= dprod(c
, c
) - SPHERE_RADIUS
* SPHERE_RADIUS
;
321 if ((d
= b
* b
- a
) < 0.0 || (b
< 0.0 && a
> 0.0))
334 vsub(dist
, lightpos
, p
);
335 if (dprod(dist
, dist
) < t
* t
)
342 colorcheckmap(float ppos
[3], float c
[3])
344 static float norm
[3] = { 0.0f
, 0.0f
, 1.0f
};
345 float ldir
[3], vdir
[3], h
[3], dfact
, kfact
, r
, g
, b
;
348 x
= (int) ((ppos
[0] + BASESIZE
/ 2) * (10.0f
/ BASESIZE
));
349 if ((x
< 0) || (x
> 10))
352 y
= (int) ((ppos
[1] + BASESIZE
/ 2) * (10.0f
/ BASESIZE
));
353 if ((y
< 0) || (y
> 10))
371 vsub(ldir
, lightpos
, ppos
);
372 vnormalize(ldir
, ldir
);
374 if (seelight(ppos
, ldir
)) {
382 dfact
= dprod(ldir
, norm
);
386 vsub(vdir
, obs
, ppos
);
387 vnormalize(vdir
, vdir
);
388 h
[0] = 0.5f
* (vdir
[0] + ldir
[0]);
389 h
[1] = 0.5f
* (vdir
[1] + ldir
[1]);
390 h
[2] = 0.5f
* (vdir
[2] + ldir
[2]);
391 kfact
= dprod(h
, norm
);
392 kfact
= pow(kfact
, 6.0) * 7.0 * 255.0;
394 r
= r
* dfact
+ kfact
;
395 g
= g
* dfact
+ kfact
;
396 b
= b
* dfact
+ kfact
;
406 updatecheckmap(int slot
)
411 glBindTexture(GL_TEXTURE_2D
, checkid
);
414 for (y
= slot
* TEX_CHECK_SLOT_SIZE
; y
< (slot
+ 1) * TEX_CHECK_SLOT_SIZE
;
416 ppos
[1] = (y
/ (float) TEX_CHECK_HEIGHT
) * BASESIZE
- BASESIZE
/ 2;
418 for (x
= 0; x
< TEX_CHECK_WIDTH
; x
++) {
419 ppos
[0] = (x
/ (float) TEX_CHECK_WIDTH
) * BASESIZE
- BASESIZE
/ 2;
421 colorcheckmap(ppos
, c
);
422 checkmap
[y
][x
][0] = (GLubyte
) c
[0];
423 checkmap
[y
][x
][1] = (GLubyte
) c
[1];
424 checkmap
[y
][x
][2] = (GLubyte
) c
[2];
428 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0, slot
* TEX_CHECK_SLOT_SIZE
,
429 TEX_CHECK_WIDTH
, TEX_CHECK_SLOT_SIZE
, GL_RGB
,
431 &checkmap
[slot
* TEX_CHECK_SLOT_SIZE
][0][0]);
436 updatereflectmap(int slot
)
438 float rf
, r
, g
, b
, t
, dfact
, kfact
, rdir
[3];
439 float rcol
[3], ppos
[3], norm
[3], ldir
[3], h
[3], vdir
[3], planepos
[3];
442 glBindTexture(GL_TEXTURE_2D
, reflectid
);
444 for (y
= slot
* TEX_REFLECT_SLOT_SIZE
;
445 y
< (slot
+ 1) * TEX_REFLECT_SLOT_SIZE
; y
++)
446 for (x
= 0; x
< TEX_REFLECT_WIDTH
; x
++) {
447 ppos
[0] = sphere_pos
[y
][x
][0] + objpos
[0];
448 ppos
[1] = sphere_pos
[y
][x
][1] + objpos
[1];
449 ppos
[2] = sphere_pos
[y
][x
][2] + objpos
[2];
451 vsub(norm
, ppos
, objpos
);
452 vnormalize(norm
, norm
);
454 vsub(ldir
, lightpos
, ppos
);
455 vnormalize(ldir
, ldir
);
456 vsub(vdir
, obs
, ppos
);
457 vnormalize(vdir
, vdir
);
459 rf
= 2.0f
* dprod(norm
, vdir
);
461 rdir
[0] = rf
* norm
[0] - vdir
[0];
462 rdir
[1] = rf
* norm
[1] - vdir
[1];
463 rdir
[2] = rf
* norm
[2] - vdir
[2];
465 t
= -objpos
[2] / rdir
[2];
468 planepos
[0] = objpos
[0] + t
* rdir
[0];
469 planepos
[1] = objpos
[1] + t
* rdir
[1];
472 if (!colorcheckmap(planepos
, rcol
))
473 rcol
[0] = rcol
[1] = rcol
[2] = 0.0f
;
476 rcol
[0] = rcol
[1] = rcol
[2] = 0.0f
;
479 rcol
[0] = rcol
[1] = rcol
[2] = 0.0f
;
481 dfact
= 0.1f
* dprod(ldir
, norm
);
488 h
[0] = 0.5f
* (vdir
[0] + ldir
[0]);
489 h
[1] = 0.5f
* (vdir
[1] + ldir
[1]);
490 h
[2] = 0.5f
* (vdir
[2] + ldir
[2]);
491 kfact
= dprod(h
, norm
);
492 kfact
= pow(kfact
, 4.0);
513 reflectmap
[y
][x
][0] = (GLubyte
) r
;
514 reflectmap
[y
][x
][1] = (GLubyte
) g
;
515 reflectmap
[y
][x
][2] = (GLubyte
) b
;
518 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0, slot
* TEX_REFLECT_SLOT_SIZE
,
519 TEX_REFLECT_WIDTH
, TEX_REFLECT_SLOT_SIZE
, GL_RGB
,
521 &reflectmap
[slot
* TEX_REFLECT_SLOT_SIZE
][0][0]);
527 glColor3f(0.0, 0.0, 0.0);
528 glBindTexture(GL_TEXTURE_2D
, checkid
);
529 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
532 glTexCoord2f(0.0f
, 0.0f
);
533 glVertex3f(-BASESIZE
/ 2.0f
, -BASESIZE
/ 2.0f
, 0.0f
);
535 glTexCoord2f(1.0f
, 0.0f
);
536 glVertex3f(BASESIZE
/ 2.0f
, -BASESIZE
/ 2.0f
, 0.0f
);
538 glTexCoord2f(1.0f
, 1.0f
);
539 glVertex3f(BASESIZE
/ 2.0f
, BASESIZE
/ 2.0f
, 0.0f
);
541 glTexCoord2f(0.0f
, 1.0f
);
542 glVertex3f(-BASESIZE
/ 2.0f
, BASESIZE
/ 2.0f
, 0.0f
);
550 glColor3f(0.0, 0.0, 0.0);
551 glBindTexture(GL_TEXTURE_2D
, reflectid
);
552 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
555 glTranslatef(objpos
[0], objpos
[1], objpos
[2]);
556 glCallList(objdlist
);
564 static UINT max
[2] = { 0, 0 };
565 static UINT min
[2] = { 0xffffffff, 0xffffffff }, center
[2];
569 res
= joyGetPos(JOYSTICKID1
, &joy
);
571 if (res
== JOYERR_NOERROR
) {
574 if (max
[0] < joy
.wXpos
)
576 if (min
[0] > joy
.wXpos
)
578 center
[0] = (max
[0] + min
[0]) / 2;
580 if (max
[1] < joy
.wYpos
)
582 if (min
[1] > joy
.wYpos
)
584 center
[1] = (max
[1] + min
[1]) / 2;
587 if (fabs(center
[0] - (float) joy
.wXpos
) > 0.1 * (max
[0] - min
[0]))
589 2.5 * (center
[0] - (float) joy
.wXpos
) / (max
[0] - min
[0]);
590 if (fabs(center
[1] - (float) joy
.wYpos
) > 0.1 * (max
[1] - min
[1]))
591 beta
+= 2.5 * (center
[1] - (float) joy
.wYpos
) / (max
[1] - min
[1]);
593 if (joy
.wButtons
& JOY_BUTTON1
)
595 if (joy
.wButtons
& JOY_BUTTON2
)
607 updatecheckmap(checkmap_currentslot
);
608 checkmap_currentslot
= (checkmap_currentslot
+ 1) % TEX_CHECK_NUMSLOT
;
610 updatereflectmap(reflectmap_currentslot
);
611 reflectmap_currentslot
=
612 (reflectmap_currentslot
+ 1) % TEX_REFLECT_NUMSLOT
;
618 static char frbuf
[80] = "";
622 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
624 glEnable(GL_TEXTURE_2D
);
625 glEnable(GL_DEPTH_TEST
);
634 gluLookAt(obs
[0], obs
[1], obs
[2],
635 obs
[0] + dir
[0], obs
[1] + dir
[1], obs
[2] + dir
[2],
641 glColor3f(1.0, 1.0, 1.0);
642 glDisable(GL_TEXTURE_2D
);
645 glTranslatef(lightpos
[0], lightpos
[1], lightpos
[2]);
646 glCallList(lightdlist
);
651 glDisable(GL_DEPTH_TEST
);
654 glMatrixMode(GL_PROJECTION
);
657 glOrtho(-0.5, 639.5, -0.5, 479.5, -1.0, 1.0);
658 glMatrixMode(GL_MODELVIEW
);
660 glColor3f(0.0f
, 0.3f
, 1.0f
);
663 glEnable(GL_TEXTURE_2D
);
664 glBindTexture(GL_TEXTURE_2D
, checkid
);
665 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
668 glTexCoord2f(1.0f
, 0.0f
);
670 glTexCoord2f(1.0f
, 1.0f
);
671 glVertex2i(10 + 90, 30);
672 glTexCoord2f(0.0f
, 1.0f
);
673 glVertex2i(10 + 90, 30 + 90);
674 glTexCoord2f(0.0f
, 0.0f
);
675 glVertex2i(10, 30 + 90);
678 glDisable(GL_TEXTURE_2D
);
679 glBegin(GL_LINE_LOOP
);
681 glVertex2i(10 + 90, 30);
682 glVertex2i(10 + 90, 30 + 90);
683 glVertex2i(10, 30 + 90);
685 glRasterPos2i(105, 65);
686 printstring(GLUT_BITMAP_HELVETICA_18
, "Plane Texture Map");
689 if (showreflectmap
) {
690 glEnable(GL_TEXTURE_2D
);
691 glBindTexture(GL_TEXTURE_2D
, reflectid
);
692 glTexEnvf(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
695 glTexCoord2f(1.0f
, 0.0f
);
697 glTexCoord2f(1.0f
, 1.0f
);
698 glVertex2i(540 + 90, 30);
699 glTexCoord2f(0.0f
, 1.0f
);
700 glVertex2i(540 + 90, 30 + 90);
701 glTexCoord2f(0.0f
, 0.0f
);
702 glVertex2i(540, 30 + 90);
705 glDisable(GL_TEXTURE_2D
);
706 glBegin(GL_LINE_LOOP
);
708 glVertex2i(540 + 90, 30);
709 glVertex2i(540 + 90, 30 + 90);
710 glVertex2i(540, 30 + 90);
712 glRasterPos2i(360, 65);
713 printstring(GLUT_BITMAP_HELVETICA_18
, "Sphere Texture Map");
716 glDisable(GL_TEXTURE_2D
);
718 glRasterPos2i(10, 10);
719 printstring(GLUT_BITMAP_HELVETICA_18
, frbuf
);
720 glRasterPos2i(360, 470);
721 printstring(GLUT_BITMAP_HELVETICA_10
,
722 "Ray V1.0 Written by David Bucciarelli (tech.hmw@plus.it)");
727 glMatrixMode(GL_PROJECTION
);
729 glMatrixMode(GL_MODELVIEW
);
737 GLint t
= glutGet(GLUT_ELAPSED_TIME
);
738 if (t
- T0
>= 2000) {
739 GLfloat seconds
= (t
- T0
) / 1000.0;
740 GLfloat fps
= Frames
/ seconds
;
741 sprintf(frbuf
, "Frame rate: %f", fps
);
742 printf("%s\n", frbuf
);
754 glGenTextures(1, &checkid
);
755 glBindTexture(GL_TEXTURE_2D
, checkid
);
757 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
758 glTexImage2D(GL_TEXTURE_2D
, 0, 3, TEX_CHECK_WIDTH
, TEX_CHECK_HEIGHT
,
759 0, GL_RGB
, GL_UNSIGNED_BYTE
, checkmap
);
761 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
762 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
764 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
765 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
767 for (y
= 0; y
< TEX_CHECK_NUMSLOT
; y
++)
772 glGenTextures(1, &reflectid
);
773 glBindTexture(GL_TEXTURE_2D
, reflectid
);
775 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
776 glTexImage2D(GL_TEXTURE_2D
, 0, 3, TEX_REFLECT_WIDTH
, TEX_REFLECT_HEIGHT
,
777 0, GL_RGB
, GL_UNSIGNED_BYTE
, reflectmap
);
779 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
780 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
782 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
783 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
785 for (y
= 0; y
< TEX_REFLECT_NUMSLOT
; y
++)
794 float alpha
, beta
, sa
, ca
, sb
, cb
;
797 for (y
= 0; y
< TEX_REFLECT_HEIGHT
; y
++) {
798 beta
= M_PI
- y
* (M_PI
/ TEX_REFLECT_HEIGHT
);
800 for (x
= 0; x
< TEX_REFLECT_WIDTH
; x
++) {
801 alpha
= -x
* (2.0f
* M_PI
/ TEX_REFLECT_WIDTH
);
809 sphere_pos
[y
][x
][0] = SPHERE_RADIUS
* sa
* sb
;
810 sphere_pos
[y
][x
][1] = SPHERE_RADIUS
* ca
* sb
;
811 sphere_pos
[y
][x
][2] = SPHERE_RADIUS
* cb
;
821 obj
= gluNewQuadric();
823 lightdlist
= glGenLists(1);
824 glNewList(lightdlist
, GL_COMPILE
);
825 gluQuadricDrawStyle(obj
, GLU_FILL
);
826 gluQuadricNormals(obj
, GLU_NONE
);
827 gluQuadricTexture(obj
, GL_TRUE
);
828 gluSphere(obj
, 0.25f
, 6, 6);
831 objdlist
= glGenLists(1);
832 glNewList(objdlist
, GL_COMPILE
);
833 gluQuadricDrawStyle(obj
, GLU_FILL
);
834 gluQuadricNormals(obj
, GLU_NONE
);
835 gluQuadricTexture(obj
, GL_TRUE
);
836 gluSphere(obj
, SPHERE_RADIUS
, 16, 16);
839 gluDeleteQuadric(obj
);
843 main(int ac
, char **av
)
846 "Ray V1.0\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
849 if(!SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS)) {
850 fprintf(stderr,"Error setting the process class.\n");
854 if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL)) {
855 fprintf(stderr,"Error setting the process priority.\n");
860 glutInitWindowSize(WIDTH
, HEIGHT
);
863 glutInitDisplayMode(GLUT_RGB
| GLUT_DEPTH
| GLUT_DOUBLE
);
865 if (!(win
= glutCreateWindow("Ray"))) {
866 fprintf(stderr
, "Error, couldn't open window\n");
870 reshape(WIDTH
, HEIGHT
);
872 glShadeModel(GL_FLAT
);
873 glEnable(GL_DEPTH_TEST
);
874 glDepthFunc(GL_LEQUAL
);
875 glEnable(GL_CULL_FACE
);
876 glEnable(GL_TEXTURE_2D
);
877 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
880 glFogi(GL_FOG_MODE
, GL_EXP2
);
881 glFogfv(GL_FOG_COLOR
, fogcolor
);
883 glFogf(GL_FOG_DENSITY
, 0.01);
885 glHint(GL_FOG_HINT
, GL_NICEST
);
895 glClearColor(fogcolor
[0], fogcolor
[1], fogcolor
[2], fogcolor
[3]);
897 glutReshapeFunc(reshape
);
898 glutDisplayFunc(draw
);
899 glutKeyboardFunc(key
);
900 glutSpecialFunc(special
);