/* * EXT_fog_coord. * * Based on glutskel.c by Brian Paul * and NeHe's Volumetric fog tutorial! * * Daniel Borca */ #include #include #include #include #include "readtex.h" #define TEXTURE_FILE "../images/bw.rgb" #define ARRAYS 0 /* use glDrawElements */ #define VERBOSE 1 /* tell me what happens */ #define DEPTH 15.0f #if !defined(GLAPIENTRYP) # define GLAPIENTRYP * #endif typedef void (GLAPIENTRYP GLFOGCOORDFEXTPROC) (GLfloat f); typedef void (GLAPIENTRYP GLFOGCOORDPOINTEREXTPROC) (GLenum, GLsizei, const GLvoid *); static GLFOGCOORDFEXTPROC glFogCoordf_ext; #if ARRAYS static GLFOGCOORDPOINTEREXTPROC glFogCoordPointer_ext; #endif static GLboolean have_fog_coord; static GLfloat camz; static GLuint texture[1]; static GLint fogMode; static GLboolean fogCoord; static GLfloat fogDensity = 0.75; static GLfloat fogStart = 1.0, fogEnd = 40.0; static GLfloat fogColor[4] = {0.6f, 0.3f, 0.0f, 1.0f}; static void APIENTRY glFogCoordf_nop (GLfloat f) { (void)f; } static int BuildTexture (const char *filename, GLuint texid[]) { GLubyte *tex_data; GLenum tex_format; GLint tex_width, tex_height; tex_data = LoadRGBImage(filename, &tex_width, &tex_height, &tex_format); if (tex_data == NULL) { return -1; } { GLint tex_max; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &tex_max); if ((tex_width > tex_max) || (tex_height > tex_max)) { return -1; } } glGenTextures(1, texid); glBindTexture(GL_TEXTURE_2D, texid[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, tex_format, tex_width, tex_height, 0, tex_format, GL_UNSIGNED_BYTE, tex_data); return 0; } static int SetFogMode (GLint fogMode) { fogMode &= 3; switch (fogMode) { case 0: glDisable(GL_FOG); #if VERBOSE printf("fog(disable)\n"); #endif break; case 1: glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_LINEAR); glFogf(GL_FOG_START, fogStart); glFogf(GL_FOG_END, fogEnd); #if VERBOSE printf("fog(GL_LINEAR, %.2f, %.2f)\n", fogStart, fogEnd); #endif break; case 2: glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_EXP); glFogf(GL_FOG_DENSITY, fogDensity); #if VERBOSE printf("fog(GL_EXP, %.2f)\n", fogDensity); #endif break; case 3: glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_EXP2); glFogf(GL_FOG_DENSITY, fogDensity); #if VERBOSE printf("fog(GL_EXP2, %.2f)\n", fogDensity); #endif break; } return fogMode; } static GLboolean SetFogCoord (GLboolean fogCoord) { glFogCoordf_ext = glFogCoordf_nop; if (!have_fog_coord) { #if VERBOSE printf("fog(GL_FRAGMENT_DEPTH_EXT)%s\n", fogCoord ? " EXT_fog_coord not available!" : ""); #endif return GL_FALSE; } if (fogCoord) { glFogCoordf_ext = (GLFOGCOORDFEXTPROC)glutGetProcAddress("glFogCoordfEXT"); glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); #if VERBOSE printf("fog(GL_FOG_COORDINATE_EXT)\n"); #endif } else { glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); #if VERBOSE printf("fog(GL_FRAGMENT_DEPTH_EXT)\n"); #endif } return fogCoord; } #if ARRAYS /* could reuse vertices */ static GLuint vertex_index[] = { /* Back */ 0, 1, 2, 3, /* Floor */ 4, 5, 6, 7, /* Roof */ 8, 9, 10, 11, /* Right */ 12, 13, 14, 15, /* Left */ 16, 17, 18, 19 }; static GLfloat vertex_pointer[][3] = { /* Back */ {-2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH}, { 2.5f, 2.5f,-DEPTH}, {-2.5f, 2.5f,-DEPTH}, /* Floor */ {-2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH}, { 2.5f,-2.5f, DEPTH}, {-2.5f,-2.5f, DEPTH}, /* Roof */ {-2.5f, 2.5f,-DEPTH}, { 2.5f, 2.5f,-DEPTH}, { 2.5f, 2.5f, DEPTH}, {-2.5f, 2.5f, DEPTH}, /* Right */ { 2.5f,-2.5f, DEPTH}, { 2.5f, 2.5f, DEPTH}, { 2.5f, 2.5f,-DEPTH}, { 2.5f,-2.5f,-DEPTH}, /* Left */ {-2.5f,-2.5f, DEPTH}, {-2.5f, 2.5f, DEPTH}, {-2.5f, 2.5f,-DEPTH}, {-2.5f,-2.5f,-DEPTH} }; static GLfloat texcoord_pointer[][2] = { /* Back */ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}, /* Floor */ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}, /* Roof */ {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}, /* Right */ {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f}, /* Left */ {0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; static GLfloat fogcoord_pointer[][1] = { /* Back */ {1.0f}, {1.0f}, {1.0f}, {1.0f}, /* Floor */ {1.0f}, {1.0f}, {0.0f}, {0.0f}, /* Roof */ {1.0f}, {1.0f}, {0.0f}, {0.0f}, /* Right */ {0.0f}, {0.0f}, {1.0f}, {1.0f}, /* Left */ {0.0f}, {0.0f}, {1.0f}, {1.0f} }; #endif static void Display( void ) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glTranslatef(0.0f, 0.0f, camz); #if ARRAYS glDrawElements(GL_QUADS, sizeof(vertex_index) / sizeof(vertex_index[0]), GL_UNSIGNED_INT, vertex_index); #else /* Back */ glBegin(GL_QUADS); glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-DEPTH); glEnd(); /* Floor */ glBegin(GL_QUADS); glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f,-2.5f, DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f,-2.5f, DEPTH); glEnd(); /* Roof */ glBegin(GL_QUADS); glFogCoordf_ext(1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f, 2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f, 2.5f,-DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f, DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, DEPTH); glEnd(); /* Right */ glBegin(GL_QUADS); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 2.5f,-2.5f, DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 2.5f, 2.5f, DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 2.5f, 2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 2.5f,-2.5f,-DEPTH); glEnd(); /* Left */ glBegin(GL_QUADS); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-2.5f,-2.5f, DEPTH); glFogCoordf_ext(0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-2.5f, 2.5f, DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-2.5f, 2.5f,-DEPTH); glFogCoordf_ext(1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-2.5f,-2.5f,-DEPTH); glEnd(); #endif glutSwapBuffers(); } static void Reshape( int width, int height ) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)(width)/(GLfloat)(height), 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } static void Key( unsigned char key, int x, int y ) { (void) x; (void) y; switch (key) { case 'f': fogMode = SetFogMode(fogMode + 1); break; case '+': if (fogDensity < 1.0) { fogDensity += 0.05; } SetFogMode(fogMode); break; case '-': if (fogDensity > 0.0) { fogDensity -= 0.05; } SetFogMode(fogMode); break; case 's': if (fogStart > 0.0) { fogStart -= 1.0; } SetFogMode(fogMode); break; case 'S': if (fogStart < fogEnd) { fogStart += 1.0; } SetFogMode(fogMode); break; case 'e': if (fogEnd > fogStart) { fogEnd -= 1.0; } SetFogMode(fogMode); break; case 'E': if (fogEnd < 100.0) { fogEnd += 1.0; } SetFogMode(fogMode); break; case 'c': fogCoord = SetFogCoord(fogCoord ^ GL_TRUE); break; case 27: exit(0); break; } glutPostRedisplay(); } static void SpecialKey( int key, int x, int y ) { (void) x; (void) y; switch (key) { case GLUT_KEY_UP: if (camz < (DEPTH - 1.0)) { camz += 1.0f; } break; case GLUT_KEY_DOWN: if (camz > -19.0) { camz -= 1.0f; } break; } glutPostRedisplay(); } static void Init( void ) { have_fog_coord = glutExtensionSupported("GL_EXT_fog_coord"); if (BuildTexture(TEXTURE_FILE, texture) == -1) { exit(1); } glEnable(GL_TEXTURE_2D); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glFogfv(GL_FOG_COLOR, fogColor); glHint(GL_FOG_HINT, GL_NICEST); fogCoord = SetFogCoord(GL_TRUE); /* try to enable fog_coord */ fogMode = SetFogMode(2); /* GL_EXP */ camz = -19.0f; #if ARRAYS glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertex_pointer); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texcoord_pointer); if (have_fog_coord) { glFogCoordPointer_ext = (GLFOGCOORDPOINTEREXTPROC)glutGetProcAddress("glFogCoordPointerEXT"); glEnableClientState(GL_FOG_COORDINATE_ARRAY_EXT); glFogCoordPointer_ext(GL_FLOAT, 0, fogcoord_pointer); } #endif } int main( int argc, char *argv[] ) { glutInit( &argc, argv ); glutInitWindowPosition( 0, 0 ); glutInitWindowSize( 640, 480 ); glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH ); glutCreateWindow(argv[0]); glutReshapeFunc( Reshape ); glutKeyboardFunc( Key ); glutSpecialFunc( SpecialKey ); glutDisplayFunc( Display ); Init(); glutMainLoop(); return 0; }