blob: 75a0835d4fe0de31a44fa0462fa843f01142490b [file] [log] [blame]
Daniel Borcaa49a08d2004-02-16 07:31:29 +00001/*
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
11#include <stdio.h>
12#include <stdlib.h>
13#include <math.h>
14#include <GL/glut.h>
15
16#include "readtex.c" /* the compulsory hack */
17
18#define TEXTURE_FILE "../images/bw.rgb"
19
20#define ARRAYS 0 /* use glDrawElements */
21
22#define VERBOSE 1 /* tell me what happens */
23
24#define DEPTH 15.0f
Daniel Borcaa49a08d2004-02-16 07:31:29 +000025
26typedef void (GLAPIENTRYP GLFOGCOORDFEXTPROC) (GLfloat f);
27typedef void (GLAPIENTRYP GLFOGCOORDPOINTEREXTPROC) (GLenum, GLsizei, const GLvoid *);
28
29static GLFOGCOORDFEXTPROC glFogCoordf_ext;
Brian Paul37c04972004-09-16 19:39:04 +000030#if ARRAYS
Daniel Borcaa49a08d2004-02-16 07:31:29 +000031static GLFOGCOORDPOINTEREXTPROC glFogCoordPointer_ext;
Brian Paul37c04972004-09-16 19:39:04 +000032#endif
Daniel Borcaa49a08d2004-02-16 07:31:29 +000033static GLboolean have_fog_coord;
34
35static GLfloat camz;
36static GLuint texture[1];
37
38static GLint fogMode;
39static GLboolean fogCoord;
40static GLfloat fogDensity = 0.75;
Daniel Borca2c161cf2004-06-07 06:03:08 +000041static GLfloat fogStart = 1.0, fogEnd = 40.0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +000042static GLfloat fogColor[4] = {0.6f, 0.3f, 0.0f, 1.0f};
43
44
Brian Paul37c04972004-09-16 19:39:04 +000045static void APIENTRY glFogCoordf_nop (GLfloat f)
Daniel Borcaa49a08d2004-02-16 07:31:29 +000046{
Brian Paul37c04972004-09-16 19:39:04 +000047 (void)f;
Daniel Borcaa49a08d2004-02-16 07:31:29 +000048}
49
50
51static int BuildTexture (const char *filename, GLuint texid[])
52{
Brian Paul37c04972004-09-16 19:39:04 +000053 GLubyte *tex_data;
54 GLenum tex_format;
55 GLint tex_width, tex_height;
Daniel Borcaa49a08d2004-02-16 07:31:29 +000056
Brian Paul37c04972004-09-16 19:39:04 +000057 tex_data = LoadRGBImage(filename, &tex_width, &tex_height, &tex_format);
58 if (tex_data == NULL) {
59 return -1;
60 }
Daniel Borcaa49a08d2004-02-16 07:31:29 +000061
Brian Paul37c04972004-09-16 19:39:04 +000062 {
63 GLint tex_max;
64 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tex_max);
65 if ((tex_width > tex_max) || (tex_height > tex_max)) {
66 return -1;
67 }
68 }
Daniel Borcaa49a08d2004-02-16 07:31:29 +000069
Brian Paul37c04972004-09-16 19:39:04 +000070 glGenTextures(1, texid);
71
72 glBindTexture(GL_TEXTURE_2D, texid[0]);
73 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
74 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
Daniel Borcaa49a08d2004-02-16 07:31:29 +000075
Brian Paul37c04972004-09-16 19:39:04 +000076 glTexImage2D(GL_TEXTURE_2D, 0, tex_format, tex_width, tex_height, 0,
77 tex_format, GL_UNSIGNED_BYTE, tex_data);
Daniel Borcaa49a08d2004-02-16 07:31:29 +000078
Brian Paul37c04972004-09-16 19:39:04 +000079 return 0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +000080}
81
82
83static int SetFogMode (GLint fogMode)
84{
Brian Paul37c04972004-09-16 19:39:04 +000085 fogMode &= 3;
86 switch (fogMode) {
87 case 0:
88 glDisable(GL_FOG);
Daniel Borcaa49a08d2004-02-16 07:31:29 +000089#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +000090 printf("fog(disable)\n");
Daniel Borcaa49a08d2004-02-16 07:31:29 +000091#endif
Brian Paul37c04972004-09-16 19:39:04 +000092 break;
93 case 1:
94 glEnable(GL_FOG);
95 glFogi(GL_FOG_MODE, GL_LINEAR);
96 glFogf(GL_FOG_START, fogStart);
97 glFogf(GL_FOG_END, fogEnd);
Daniel Borcaa49a08d2004-02-16 07:31:29 +000098#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +000099 printf("fog(GL_LINEAR, %.2f, %.2f)\n", fogStart, fogEnd);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000100#endif
Brian Paul37c04972004-09-16 19:39:04 +0000101 break;
102 case 2:
103 glEnable(GL_FOG);
104 glFogi(GL_FOG_MODE, GL_EXP);
105 glFogf(GL_FOG_DENSITY, fogDensity);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000106#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +0000107 printf("fog(GL_EXP, %.2f)\n", fogDensity);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000108#endif
Brian Paul37c04972004-09-16 19:39:04 +0000109 break;
110 case 3:
111 glEnable(GL_FOG);
112 glFogi(GL_FOG_MODE, GL_EXP2);
113 glFogf(GL_FOG_DENSITY, fogDensity);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000114#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +0000115 printf("fog(GL_EXP2, %.2f)\n", fogDensity);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000116#endif
Brian Paul37c04972004-09-16 19:39:04 +0000117 break;
118 }
119 return fogMode;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000120}
121
122
123static GLboolean SetFogCoord (GLboolean fogCoord)
124{
Brian Paul37c04972004-09-16 19:39:04 +0000125 glFogCoordf_ext = glFogCoordf_nop;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000126
Brian Paul37c04972004-09-16 19:39:04 +0000127 if (!have_fog_coord) {
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000128#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +0000129 printf("fog(GL_FRAGMENT_DEPTH_EXT)%s\n", fogCoord ? " EXT_fog_coord not available!" : "");
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000130#endif
Brian Paul37c04972004-09-16 19:39:04 +0000131 return GL_FALSE;
132 }
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000133
Brian Paul37c04972004-09-16 19:39:04 +0000134 if (fogCoord) {
135 glFogCoordf_ext = (GLFOGCOORDFEXTPROC)glutGetProcAddress("glFogCoordfEXT");
136 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000137#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +0000138 printf("fog(GL_FOG_COORDINATE_EXT)\n");
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000139#endif
Brian Paul37c04972004-09-16 19:39:04 +0000140 } else {
141 glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000142#if VERBOSE
Brian Paul37c04972004-09-16 19:39:04 +0000143 printf("fog(GL_FRAGMENT_DEPTH_EXT)\n");
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000144#endif
Brian Paul37c04972004-09-16 19:39:04 +0000145 }
146 return fogCoord;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000147}
148
149
150#if ARRAYS
151/* could reuse vertices */
152static GLuint vertex_index[] = {
153 /* Back */
154 0, 1, 2, 3,
155
156 /* Floor */
157 4, 5, 6, 7,
158
159 /* Roof */
160 8, 9, 10, 11,
161
162 /* Right */
163 12, 13, 14, 15,
164
165 /* Left */
166 16, 17, 18, 19
167};
168
169static GLfloat vertex_pointer[][3] = {
170 /* Back */
171 {-2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH}, { 2.5f, 2.5f,-DEPTH}, {-2.5f, 2.5f,-DEPTH},
172
173 /* Floor */
174 {-2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f, DEPTH}, {-2.5f,-2.5f, DEPTH},
175
176 /* Roof */
177 {-2.5f, 2.5f,-DEPTH}, { 2.5f, 2.5f,-DEPTH}, { 2.5f, 2.5f, DEPTH}, {-2.5f, 2.5f, DEPTH},
178
179 /* Right */
180 { 2.5f,-2.5f, DEPTH}, { 2.5f, 2.5f, DEPTH}, { 2.5f, 2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH},
181
182 /* Left */
183 {-2.5f,-2.5f, DEPTH}, {-2.5f, 2.5f, DEPTH}, {-2.5f, 2.5f,-DEPTH}, {-2.5f,-2.5f,-DEPTH}
184};
185
186static GLfloat texcoord_pointer[][2] = {
187 /* Back */
188 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
189
190 /* Floor */
191 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
192
193 /* Roof */
194 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f},
195
196 /* Right */
197 {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f},
198
199 /* Left */
200 {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}
201};
202
203static GLfloat fogcoord_pointer[][1] = {
204 /* Back */
205 {1.0f}, {1.0f}, {1.0f}, {1.0f},
206
207 /* Floor */
208 {1.0f}, {1.0f}, {0.0f}, {0.0f},
209
210 /* Roof */
211 {1.0f}, {1.0f}, {0.0f}, {0.0f},
212
213 /* Right */
214 {0.0f}, {0.0f}, {1.0f}, {1.0f},
215
216 /* Left */
217 {0.0f}, {0.0f}, {1.0f}, {1.0f}
218};
219#endif
220
221
222static void Display( void )
223{
224 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
225 glLoadIdentity ();
226
227 glTranslatef(0.0f, 0.0f, camz);
228
229#if ARRAYS
230 glDrawElements(GL_QUADS, sizeof(vertex_index) / sizeof(vertex_index[0]), GL_UNSIGNED_INT, vertex_index);
231#else
232 /* Back */
233 glBegin(GL_QUADS);
234 glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH);
235 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH);
236 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-DEPTH);
237 glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-DEPTH);
238 glEnd();
239
240 /* Floor */
241 glBegin(GL_QUADS);
242 glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH);
243 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH);
244 glFogCoordf_ext(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f,-2.5f, DEPTH);
245 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f,-2.5f, DEPTH);
246 glEnd();
247
248 /* Roof */
249 glBegin(GL_QUADS);
250 glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f, 2.5f,-DEPTH);
251 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f, 2.5f,-DEPTH);
252 glFogCoordf_ext(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f, DEPTH);
253 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, DEPTH);
254 glEnd();
255
256 /* Right */
257 glBegin(GL_QUADS);
258 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 2.5f,-2.5f, DEPTH);
259 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 2.5f, 2.5f, DEPTH);
260 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-DEPTH);
261 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH);
262 glEnd();
263
264 /* Left */
265 glBegin(GL_QUADS);
266 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f, DEPTH);
267 glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, DEPTH);
268 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-DEPTH);
269 glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH);
270 glEnd();
271#endif
272
273 glutSwapBuffers();
274}
275
276
277static void Reshape( int width, int height )
278{
279 glViewport(0, 0, width, height);
280 glMatrixMode(GL_PROJECTION);
281 glLoadIdentity();
282 gluPerspective(45.0f, (GLfloat)(width)/(GLfloat)(height), 0.1f, 100.0f);
283 glMatrixMode(GL_MODELVIEW);
284 glLoadIdentity();
285}
286
287
288static void Key( unsigned char key, int x, int y )
289{
290 (void) x;
291 (void) y;
292 switch (key) {
293 case 'f':
294 fogMode = SetFogMode(fogMode + 1);
295 break;
296 case '+':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000297 if (fogDensity < 1.0) {
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000298 fogDensity += 0.05;
299 }
300 SetFogMode(fogMode);
301 break;
302 case '-':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000303 if (fogDensity > 0.0) {
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000304 fogDensity -= 0.05;
305 }
306 SetFogMode(fogMode);
307 break;
308 case 's':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000309 if (fogStart > 0.0) {
310 fogStart -= 1.0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000311 }
312 SetFogMode(fogMode);
313 break;
314 case 'S':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000315 if (fogStart < fogEnd) {
316 fogStart += 1.0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000317 }
318 SetFogMode(fogMode);
319 break;
320 case 'e':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000321 if (fogEnd > fogStart) {
322 fogEnd -= 1.0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000323 }
324 SetFogMode(fogMode);
325 break;
326 case 'E':
Daniel Borca2c161cf2004-06-07 06:03:08 +0000327 if (fogEnd < 100.0) {
328 fogEnd += 1.0;
Daniel Borcaa49a08d2004-02-16 07:31:29 +0000329 }
330 SetFogMode(fogMode);
331 break;
332 case 'c':
333 fogCoord = SetFogCoord(fogCoord ^ GL_TRUE);
334 break;
335 case 27:
336 exit(0);
337 break;
338 }
339 glutPostRedisplay();
340}
341
342
343static void SpecialKey( int key, int x, int y )
344{
345 (void) x;
346 (void) y;
347 switch (key) {
348 case GLUT_KEY_UP:
349 if (camz < (DEPTH - 1.0)) {
350 camz += 1.0f;
351 }
352 break;
353 case GLUT_KEY_DOWN:
354 if (camz > -19.0) {
355 camz -= 1.0f;
356 }
357 break;
358 }
359 glutPostRedisplay();
360}
361
362
363static void Init( void )
364{
365 have_fog_coord = glutExtensionSupported("GL_EXT_fog_coord");
366
367 if (BuildTexture(TEXTURE_FILE, texture) == -1) {
368 exit(1);
369 }
370
371 glEnable(GL_TEXTURE_2D);
372 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
373 glClearDepth(1.0f);
374 glDepthFunc(GL_LEQUAL);
375 glEnable(GL_DEPTH_TEST);
376 glShadeModel(GL_SMOOTH);
377 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
378
379 glFogfv(GL_FOG_COLOR, fogColor);
380 glHint(GL_FOG_HINT, GL_NICEST);
381 fogCoord = SetFogCoord(GL_TRUE); /* try to enable fog_coord */
382 fogMode = SetFogMode(2); /* GL_EXP */
383
384 camz = -19.0f;
385
386#if ARRAYS
387 glEnableClientState(GL_VERTEX_ARRAY);
388 glVertexPointer(3, GL_FLOAT, 0, vertex_pointer);
389
390 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
391 glTexCoordPointer(2, GL_FLOAT, 0, texcoord_pointer);
392
393 if (have_fog_coord) {
394 glFogCoordPointer_ext = (GLFOGCOORDPOINTEREXTPROC)glutGetProcAddress("glFogCoordPointerEXT");
395 glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT);
396 glFogCoordPointer_ext(GL_FLOAT, 0, fogcoord_pointer);
397 }
398#endif
399}
400
401
402int main( int argc, char *argv[] )
403{
404 glutInit( &argc, argv );
405 glutInitWindowPosition( 0, 0 );
406 glutInitWindowSize( 640, 480 );
407 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
408 glutCreateWindow(argv[0]);
409 glutReshapeFunc( Reshape );
410 glutKeyboardFunc( Key );
411 glutSpecialFunc( SpecialKey );
412 glutDisplayFunc( Display );
413 Init();
414 glutMainLoop();
415 return 0;
416}