1/*
2 * EXT_fog_coord.
3 *
4 * Based on glutskel.c by Brian Paul
5 * and NeHe's Volumetric fog tutorial!
6 *
7 * Daniel Borca
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <GL/glew.h>
14#include "glut_wrap.h"
15
16#define DEPTH 5.0f
17
18static GLfloat camz;
19
20static GLint fogMode;
21static GLboolean fogCoord;
22static GLfloat fogDensity = 0.75;
23static GLfloat fogStart = 1.0, fogEnd = DEPTH;
24static GLfloat fogColor[4] = {0.6f, 0.3f, 0.0f, 1.0f};
25static const char *ModeStr = NULL;
26static GLboolean Arrays = GL_FALSE;
27static GLboolean Texture = GL_TRUE;
28
29
30static void
31Reset(void)
32{
33   fogMode = 1;
34   fogCoord = 1;
35   fogDensity = 0.75;
36   fogStart = 1.0;
37   fogEnd = DEPTH;
38   Arrays = GL_FALSE;
39   Texture = GL_TRUE;
40}
41
42
43static void
44glFogCoordf_ext (GLfloat f)
45{
46   if (fogCoord)
47      glFogCoordfEXT(f);
48}
49
50
51static void
52PrintString(const char *s)
53{
54   while (*s) {
55      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
56      s++;
57   }
58}
59
60
61static void
62PrintInfo(void)
63{
64   char s[100];
65
66   glDisable(GL_FOG);
67   glColor3f(0, 1, 1);
68
69   sprintf(s, "Mode(m): %s  Start(s/S): %g  End(e/E): %g  Density(d/D): %g",
70           ModeStr, fogStart, fogEnd, fogDensity);
71   glWindowPos2iARB(5, 20);
72   PrintString(s);
73
74   sprintf(s, "Arrays(a): %s  glFogCoord(c): %s  EyeZ(z/z): %g",
75           (Arrays ? "Yes" : "No"),
76           (fogCoord ? "Yes" : "No"),
77           camz);
78   glWindowPos2iARB(5, 5);
79   PrintString(s);
80}
81
82
83static int
84SetFogMode(GLint fogMode)
85{
86   fogMode &= 3;
87   switch (fogMode) {
88   case 0:
89      ModeStr = "Off";
90      glDisable(GL_FOG);
91      break;
92   case 1:
93      ModeStr = "GL_LINEAR";
94      glEnable(GL_FOG);
95      glFogi(GL_FOG_MODE, GL_LINEAR);
96      glFogf(GL_FOG_START, fogStart);
97      glFogf(GL_FOG_END, fogEnd);
98      break;
99   case 2:
100      ModeStr = "GL_EXP";
101      glEnable(GL_FOG);
102      glFogi(GL_FOG_MODE, GL_EXP);
103      glFogf(GL_FOG_DENSITY, fogDensity);
104      break;
105   case 3:
106      ModeStr = "GL_EXP2";
107      glEnable(GL_FOG);
108      glFogi(GL_FOG_MODE, GL_EXP2);
109      glFogf(GL_FOG_DENSITY, fogDensity);
110      break;
111   }
112   return fogMode;
113}
114
115
116static GLboolean
117SetFogCoord(GLboolean fogCoord)
118{
119   if (!GLEW_EXT_fog_coord) {
120      return GL_FALSE;
121   }
122
123   if (fogCoord) {
124      glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
125   }
126   else {
127      glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
128   }
129   return fogCoord;
130}
131
132
133/* could reuse vertices */
134static GLuint vertex_index[] = {
135   /* Back */
136   0, 1, 2, 3,
137
138   /* Floor */
139   4, 5, 6, 7,
140
141   /* Roof */
142   8, 9, 10, 11,
143
144   /* Right */
145   12, 13, 14, 15,
146
147   /* Left */
148   16, 17, 18, 19
149};
150
151static GLfloat vertex_pointer[][3] = {
152   /* Back */
153   {-1.0f,-1.0f,-DEPTH}, { 1.0f,-1.0f,-DEPTH}, { 1.0f, 1.0f,-DEPTH}, {-1.0f, 1.0f,-DEPTH},
154
155   /* Floor */
156   {-1.0f,-1.0f,-DEPTH}, { 1.0f,-1.0f,-DEPTH}, { 1.0f,-1.0f, 0.0}, {-1.0f,-1.0f, 0.0},
157
158   /* Roof */
159   {-1.0f, 1.0f,-DEPTH}, { 1.0f, 1.0f,-DEPTH}, { 1.0f, 1.0f, 0.0}, {-1.0f, 1.0f, 0.0},
160
161   /* Right */
162   { 1.0f,-1.0f, 0.0}, { 1.0f, 1.0f, 0.0}, { 1.0f, 1.0f,-DEPTH}, { 1.0f,-1.0f,-DEPTH},
163
164   /* Left */
165   {-1.0f,-1.0f, 0.0}, {-1.0f, 1.0f, 0.0}, {-1.0f, 1.0f,-DEPTH}, {-1.0f,-1.0f,-DEPTH}
166};
167
168static GLfloat texcoord_pointer[][2] = {
169   /* Back */
170   {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
171
172   /* Floor */
173   {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, DEPTH}, {0.0f, DEPTH},
174
175   /* Roof */
176   {1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, DEPTH}, {1.0f, DEPTH},
177
178   /* Right */
179   {0.0f, 1.0f}, {0.0f, 0.0f}, {DEPTH, 0.0f}, {DEPTH, 1.0f},
180
181   /* Left */
182   {0.0f, 0.0f}, {0.0f, 1.0f}, {DEPTH, 1.0f}, {DEPTH, 0.0f}
183};
184
185static GLfloat fogcoord_pointer[] = {
186   /* Back */
187   DEPTH, DEPTH, DEPTH, DEPTH,
188
189   /* Floor */
190   DEPTH, DEPTH, 0.0, 0.0,
191
192   /* Roof */
193   DEPTH, DEPTH, 0.0, 0.0,
194
195   /* Right */
196   0.0, 0.0, DEPTH, DEPTH,
197
198   /* Left */
199   0.0, 0.0, DEPTH, DEPTH
200};
201
202
203static void
204Display( void )
205{
206   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
207   glLoadIdentity ();
208
209   glTranslatef(0.0f, 0.0f, -camz);
210
211   SetFogMode(fogMode);
212
213   glColor3f(1, 1, 1);
214
215   if (Texture)
216      glEnable(GL_TEXTURE_2D);
217
218   if (Arrays) {
219      glEnableClientState(GL_VERTEX_ARRAY);
220      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
221      glDrawElements(GL_QUADS, sizeof(vertex_index) / sizeof(vertex_index[0]),
222                     GL_UNSIGNED_INT, vertex_index);
223      glDisableClientState(GL_VERTEX_ARRAY);
224      glDisableClientState(GL_TEXTURE_COORD_ARRAY);
225   }
226   else {
227      /* Back */
228      glBegin(GL_QUADS);
229      glFogCoordf_ext(DEPTH); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-DEPTH);
230      glFogCoordf_ext(DEPTH); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f,-DEPTH);
231      glFogCoordf_ext(DEPTH); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-DEPTH);
232      glFogCoordf_ext(DEPTH); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-DEPTH);
233      glEnd();
234
235      /* Floor */
236      glBegin(GL_QUADS);
237      glFogCoordf_ext(DEPTH); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f,-DEPTH);
238      glFogCoordf_ext(DEPTH); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f,-DEPTH);
239      glFogCoordf_ext(0.0f); glTexCoord2f(1.0f,  DEPTH); glVertex3f( 1.0f,-1.0f,0.0);
240      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f,  DEPTH); glVertex3f(-1.0f,-1.0f,0.0);
241      glEnd();
242
243      /* Roof */
244      glBegin(GL_QUADS);
245      glFogCoordf_ext(DEPTH); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, 1.0f,-DEPTH);
246      glFogCoordf_ext(DEPTH); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f,-DEPTH);
247      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, DEPTH); glVertex3f( 1.0f, 1.0f,0.0);
248      glFogCoordf_ext(0.0f); glTexCoord2f(1.0f, DEPTH); glVertex3f(-1.0f, 1.0f,0.0);
249      glEnd();
250
251      /* Right */
252      glBegin(GL_QUADS);
253      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,-1.0f,0.0);
254      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, 1.0f,0.0);
255      glFogCoordf_ext(DEPTH); glTexCoord2f(DEPTH, 0.0f); glVertex3f( 1.0f, 1.0f,-DEPTH);
256      glFogCoordf_ext(DEPTH); glTexCoord2f(DEPTH, 1.0f); glVertex3f( 1.0f,-1.0f,-DEPTH);
257      glEnd();
258
259      /* Left */
260      glBegin(GL_QUADS);
261      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f,0.0);
262      glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f,0.0);
263      glFogCoordf_ext(DEPTH); glTexCoord2f(DEPTH, 1.0f); glVertex3f(-1.0f, 1.0f,-DEPTH);
264      glFogCoordf_ext(DEPTH); glTexCoord2f(DEPTH, 0.0f); glVertex3f(-1.0f,-1.0f,-DEPTH);
265      glEnd();
266   }
267
268   glDisable(GL_TEXTURE_2D);
269
270   PrintInfo();
271
272   glutSwapBuffers();
273}
274
275
276static void
277Reshape( int width, int height )
278{
279   glViewport(0, 0, width, height);
280   glMatrixMode(GL_PROJECTION);
281   glLoadIdentity();
282   glFrustum(-1, 1, -1, 1, 1.0, 100);
283   glMatrixMode(GL_MODELVIEW);
284   glLoadIdentity();
285}
286
287
288static void
289Key( unsigned char key, int x, int y )
290{
291   (void) x;
292   (void) y;
293   switch (key) {
294      case 'a':
295         Arrays = !Arrays;
296         break;
297      case 'f':
298      case 'm':
299         fogMode = SetFogMode(fogMode + 1);
300         break;
301      case 'D':
302         fogDensity += 0.05;
303         SetFogMode(fogMode);
304         break;
305      case 'd':
306         if (fogDensity > 0.0) {
307            fogDensity -= 0.05;
308         }
309         SetFogMode(fogMode);
310         break;
311      case 's':
312         if (fogStart > 0.0) {
313            fogStart -= 0.25;
314         }
315         SetFogMode(fogMode);
316         break;
317      case 'S':
318         if (fogStart < 100.0) {
319            fogStart += 0.25;
320         }
321         SetFogMode(fogMode);
322         break;
323      case 'e':
324         if (fogEnd > 0.0) {
325            fogEnd -= 0.25;
326         }
327         SetFogMode(fogMode);
328         break;
329      case 'E':
330         if (fogEnd < 100.0) {
331            fogEnd += 0.25;
332         }
333         SetFogMode(fogMode);
334         break;
335      case 'c':
336	 fogCoord = SetFogCoord(fogCoord ^ GL_TRUE);
337         break;
338      case 't':
339         Texture = !Texture;
340         break;
341      case 'z':
342         camz -= 0.1;
343         break;
344      case 'Z':
345         camz += 0.1;
346         break;
347      case 'r':
348         Reset();
349         break;
350      case 27:
351         exit(0);
352         break;
353   }
354   glutPostRedisplay();
355}
356
357
358static void
359Init(void)
360{
361   static const GLubyte teximage[2][2][4] = {
362      { { 255, 255, 255, 255}, { 128, 128, 128, 255} },
363      { { 128, 128, 128, 255}, { 255, 255, 255, 255} }
364   };
365
366   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
367
368   if (!GLEW_EXT_fog_coord) {
369      printf("GL_EXT_fog_coord not supported!\n");
370   }
371
372   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0,
373                GL_RGBA, GL_UNSIGNED_BYTE, teximage);
374   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
375   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
376
377   glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
378
379   glDepthFunc(GL_LEQUAL);
380   glEnable(GL_DEPTH_TEST);
381   glShadeModel(GL_SMOOTH);
382   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
383
384   glFogfv(GL_FOG_COLOR, fogColor);
385   glHint(GL_FOG_HINT, GL_NICEST);
386   fogCoord = SetFogCoord(GL_TRUE); /* try to enable fog_coord */
387   fogMode = SetFogMode(1);
388
389   glEnableClientState(GL_VERTEX_ARRAY);
390   glVertexPointer(3, GL_FLOAT, 0, vertex_pointer);
391
392   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
393   glTexCoordPointer(2, GL_FLOAT, 0, texcoord_pointer);
394
395   if (GLEW_EXT_fog_coord) {
396      glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
397      glFogCoordPointerEXT(GL_FLOAT, 0, fogcoord_pointer);
398   }
399
400   Reset();
401}
402
403
404int
405main( int argc, char *argv[] )
406{
407   glutInitWindowSize( 600, 600 );
408   glutInit( &argc, argv );
409   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
410   glutCreateWindow(argv[0]);
411   glewInit();
412   glutReshapeFunc( Reshape );
413   glutKeyboardFunc( Key );
414   glutDisplayFunc( Display );
415   Init();
416   glutMainLoop();
417   return 0;
418}
419