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