132001f49Smrg/* 232001f49Smrg * GL_ARB_texture_cube_map demo 332001f49Smrg * 432001f49Smrg * Brian Paul 532001f49Smrg * May 2000 632001f49Smrg * 732001f49Smrg * 832001f49Smrg * Copyright (C) 2000 Brian Paul All Rights Reserved. 932001f49Smrg * 1032001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 1132001f49Smrg * copy of this software and associated documentation files (the "Software"), 1232001f49Smrg * to deal in the Software without restriction, including without limitation 1332001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1432001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the 1532001f49Smrg * Software is furnished to do so, subject to the following conditions: 1632001f49Smrg * 1732001f49Smrg * The above copyright notice and this permission notice shall be included 1832001f49Smrg * in all copies or substantial portions of the Software. 1932001f49Smrg * 2032001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2132001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2232001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2332001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2432001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2532001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2632001f49Smrg */ 2732001f49Smrg 2832001f49Smrg 2932001f49Smrg/* 3032001f49Smrg * This is a pretty minimalistic demo for now. Eventually, use some 3132001f49Smrg * interesting cube map textures and 3D objects. 3232001f49Smrg * For now, we use 6 checkerboard "walls" and a sphere (good for 3332001f49Smrg * verification purposes). 3432001f49Smrg */ 3532001f49Smrg 3632001f49Smrg 3732001f49Smrg#include <assert.h> 3832001f49Smrg#include <math.h> 3932001f49Smrg#include <stdio.h> 4032001f49Smrg#include <stdlib.h> 4132001f49Smrg#include <string.h> 4232001f49Smrg#include <GL/glew.h> 4332001f49Smrg#include "glut_wrap.h" 4432001f49Smrg#include "readtex.h" 4532001f49Smrg 4632001f49Smrg#ifndef GL_TEXTURE_CUBE_MAP_SEAMLESS 4732001f49Smrg#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F 4832001f49Smrg#endif 4932001f49Smrg 5032001f49Smrgstatic GLfloat Xrot = 0, Yrot = 0; 5132001f49Smrgstatic GLfloat EyeDist = 10; 5232001f49Smrgstatic GLboolean use_vertex_arrays = GL_FALSE; 5332001f49Smrgstatic GLboolean anim = GL_TRUE; 5432001f49Smrgstatic GLboolean NoClear = GL_FALSE; 5532001f49Smrgstatic GLint FrameParity = 0; 5632001f49Smrgstatic GLenum FilterIndex = 0; 5732001f49Smrgstatic GLint ClampIndex = 0; 5832001f49Smrgstatic GLboolean supportFBO = GL_FALSE; 5932001f49Smrgstatic GLboolean supportSeamless = GL_FALSE; 6032001f49Smrgstatic GLboolean seamless = GL_FALSE; 6132001f49Smrgstatic GLuint TexObj = 0; 6232001f49Smrgstatic GLint T0 = 0; 6332001f49Smrgstatic GLint Frames = 0; 6432001f49Smrg 6532001f49Smrg 6632001f49Smrgstatic struct { 6732001f49Smrg GLenum mode; 6832001f49Smrg const char *name; 6932001f49Smrg} ClampModes[] = { 7032001f49Smrg { GL_CLAMP_TO_EDGE, "GL_CLAMP_TO_EDGE" }, 7132001f49Smrg { GL_CLAMP_TO_BORDER, "GL_CLAMP_TO_BORDER" }, 7232001f49Smrg { GL_CLAMP, "GL_CLAMP" }, 7332001f49Smrg { GL_REPEAT, "GL_REPEAT" } 7432001f49Smrg}; 7532001f49Smrg 7632001f49Smrg#define NUM_CLAMP_MODES (sizeof(ClampModes) / sizeof(ClampModes[0])) 7732001f49Smrg 7832001f49Smrg 7932001f49Smrgstatic struct { 8032001f49Smrg GLenum mag_mode, min_mode; 8132001f49Smrg const char *name; 8232001f49Smrg} FilterModes[] = { 8332001f49Smrg { GL_NEAREST, GL_NEAREST, "GL_NEAREST, GL_NEAREST" }, 8432001f49Smrg { GL_NEAREST, GL_LINEAR, "GL_NEAREST, GL_LINEAR" }, 8532001f49Smrg { GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST, "GL_NEAREST, GL_NEAREST_MIPMAP_NEAREST" }, 8632001f49Smrg { GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR, "GL_NEAREST, GL_NEAREST_MIPMAP_LINEAR" }, 8732001f49Smrg { GL_NEAREST, GL_LINEAR_MIPMAP_NEAREST, "GL_NEAREST, GL_LINEAR_MIPMAP_NEAREST" }, 8832001f49Smrg { GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR, "GL_NEAREST, GL_LINEAR_MIPMAP_LINEAR" }, 8932001f49Smrg 9032001f49Smrg { GL_LINEAR, GL_NEAREST, "GL_LINEAR, GL_NEAREST" }, 9132001f49Smrg { GL_LINEAR, GL_LINEAR, "GL_LINEAR, GL_LINEAR" }, 9232001f49Smrg { GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, "GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST" }, 9332001f49Smrg { GL_LINEAR, GL_NEAREST_MIPMAP_LINEAR, "GL_LINEAR, GL_NEAREST_MIPMAP_LINEAR" }, 9432001f49Smrg { GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST, "GL_LINEAR, GL_LINEAR_MIPMAP_NEAREST" }, 9532001f49Smrg { GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, "GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR" } 9632001f49Smrg}; 9732001f49Smrg 9832001f49Smrg#define NUM_FILTER_MODES (sizeof(FilterModes) / sizeof(FilterModes[0])) 9932001f49Smrg 10032001f49Smrg 10132001f49Smrg 10232001f49Smrg/* The effects of GL_ARB_seamless_cube_map don't show up unless eps1 is 1.0. 10332001f49Smrg */ 10432001f49Smrg#define eps1 1.0 /*0.99*/ 10532001f49Smrg#define br 20.0 /* box radius */ 10632001f49Smrg 10732001f49Smrgstatic const GLfloat tex_coords[] = { 10832001f49Smrg /* +X side */ 10932001f49Smrg 1.0, -eps1, -eps1, 11032001f49Smrg 1.0, -eps1, eps1, 11132001f49Smrg 1.0, eps1, eps1, 11232001f49Smrg 1.0, eps1, -eps1, 11332001f49Smrg 11432001f49Smrg /* -X side */ 11532001f49Smrg -1.0, eps1, -eps1, 11632001f49Smrg -1.0, eps1, eps1, 11732001f49Smrg -1.0, -eps1, eps1, 11832001f49Smrg -1.0, -eps1, -eps1, 11932001f49Smrg 12032001f49Smrg /* +Y side */ 12132001f49Smrg -eps1, 1.0, -eps1, 12232001f49Smrg -eps1, 1.0, eps1, 12332001f49Smrg eps1, 1.0, eps1, 12432001f49Smrg eps1, 1.0, -eps1, 12532001f49Smrg 12632001f49Smrg /* -Y side */ 12732001f49Smrg -eps1, -1.0, -eps1, 12832001f49Smrg -eps1, -1.0, eps1, 12932001f49Smrg eps1, -1.0, eps1, 13032001f49Smrg eps1, -1.0, -eps1, 13132001f49Smrg 13232001f49Smrg /* +Z side */ 13332001f49Smrg eps1, -eps1, 1.0, 13432001f49Smrg -eps1, -eps1, 1.0, 13532001f49Smrg -eps1, eps1, 1.0, 13632001f49Smrg eps1, eps1, 1.0, 13732001f49Smrg 13832001f49Smrg /* -Z side */ 13932001f49Smrg eps1, eps1, -1.0, 14032001f49Smrg -eps1, eps1, -1.0, 14132001f49Smrg -eps1, -eps1, -1.0, 14232001f49Smrg eps1, -eps1, -1.0, 14332001f49Smrg}; 14432001f49Smrg 14532001f49Smrgstatic const GLfloat vtx_coords[] = { 14632001f49Smrg /* +X side */ 14732001f49Smrg br, -br, -br, 14832001f49Smrg br, -br, br, 14932001f49Smrg br, br, br, 15032001f49Smrg br, br, -br, 15132001f49Smrg 15232001f49Smrg /* -X side */ 15332001f49Smrg -br, br, -br, 15432001f49Smrg -br, br, br, 15532001f49Smrg -br, -br, br, 15632001f49Smrg -br, -br, -br, 15732001f49Smrg 15832001f49Smrg /* +Y side */ 15932001f49Smrg -br, br, -br, 16032001f49Smrg -br, br, br, 16132001f49Smrg br, br, br, 16232001f49Smrg br, br, -br, 16332001f49Smrg 16432001f49Smrg /* -Y side */ 16532001f49Smrg -br, -br, -br, 16632001f49Smrg -br, -br, br, 16732001f49Smrg br, -br, br, 16832001f49Smrg br, -br, -br, 16932001f49Smrg 17032001f49Smrg /* +Z side */ 17132001f49Smrg br, -br, br, 17232001f49Smrg -br, -br, br, 17332001f49Smrg -br, br, br, 17432001f49Smrg br, br, br, 17532001f49Smrg 17632001f49Smrg /* -Z side */ 17732001f49Smrg br, br, -br, 17832001f49Smrg -br, br, -br, 17932001f49Smrg -br, -br, -br, 18032001f49Smrg br, -br, -br, 18132001f49Smrg}; 18232001f49Smrg 18332001f49Smrgstatic void draw_skybox( void ) 18432001f49Smrg{ 18532001f49Smrg if ( use_vertex_arrays ) { 18632001f49Smrg glTexCoordPointer( 3, GL_FLOAT, 0, tex_coords ); 18732001f49Smrg glVertexPointer( 3, GL_FLOAT, 0, vtx_coords ); 18832001f49Smrg 18932001f49Smrg glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 19032001f49Smrg glEnableClientState( GL_VERTEX_ARRAY ); 19132001f49Smrg 19232001f49Smrg glDrawArrays( GL_QUADS, 0, 24 ); 19332001f49Smrg 19432001f49Smrg glDisableClientState( GL_TEXTURE_COORD_ARRAY ); 19532001f49Smrg glDisableClientState( GL_VERTEX_ARRAY ); 19632001f49Smrg } 19732001f49Smrg else { 19832001f49Smrg unsigned i; 19932001f49Smrg 20032001f49Smrg glBegin(GL_QUADS); 20132001f49Smrg for ( i = 0 ; i < 24 ; i++ ) { 20232001f49Smrg glTexCoord3fv( & tex_coords[ i * 3 ] ); 20332001f49Smrg glVertex3fv ( & vtx_coords[ i * 3 ] ); 20432001f49Smrg } 20532001f49Smrg glEnd(); 20632001f49Smrg } 20732001f49Smrg} 20832001f49Smrg 20932001f49Smrg 21032001f49Smrgstatic void draw( void ) 21132001f49Smrg{ 21232001f49Smrg GLenum wrap; 21332001f49Smrg 21432001f49Smrg if (NoClear) { 21532001f49Smrg /* This demonstrates how we can avoid calling glClear. 21632001f49Smrg * This method only works if every pixel in the window is painted for 21732001f49Smrg * every frame. 21832001f49Smrg * We can simply skip clearing of the color buffer in this case. 21932001f49Smrg * For the depth buffer, we alternately use a different subrange of 22032001f49Smrg * the depth buffer for each frame. For the odd frame use the range 22132001f49Smrg * [0, 0.5] with GL_LESS. For the even frames, use the range [1, 0.5] 22232001f49Smrg * with GL_GREATER. 22332001f49Smrg */ 22432001f49Smrg FrameParity = 1 - FrameParity; 22532001f49Smrg if (FrameParity) { 22632001f49Smrg glDepthRange(0.0, 0.5); 22732001f49Smrg glDepthFunc(GL_LESS); 22832001f49Smrg } 22932001f49Smrg else { 23032001f49Smrg glDepthRange(1.0, 0.5); 23132001f49Smrg glDepthFunc(GL_GREATER); 23232001f49Smrg } 23332001f49Smrg } 23432001f49Smrg else { 23532001f49Smrg /* ordinary clearing */ 23632001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 23732001f49Smrg } 23832001f49Smrg 23932001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, 24032001f49Smrg FilterModes[FilterIndex].min_mode); 24132001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, 24232001f49Smrg FilterModes[FilterIndex].mag_mode); 24332001f49Smrg 24432001f49Smrg if (supportSeamless) { 24532001f49Smrg if (seamless) { 24632001f49Smrg glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 24732001f49Smrg } else { 24832001f49Smrg glDisable(GL_TEXTURE_CUBE_MAP_SEAMLESS); 24932001f49Smrg } 25032001f49Smrg } 25132001f49Smrg wrap = ClampModes[ClampIndex].mode; 25232001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, wrap); 25332001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, wrap); 25432001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_R, wrap); 25532001f49Smrg 25632001f49Smrg glPushMatrix(); /*MODELVIEW*/ 25732001f49Smrg glTranslatef( 0.0, 0.0, -EyeDist ); 25832001f49Smrg 25932001f49Smrg /* skybox */ 26032001f49Smrg glDisable(GL_TEXTURE_GEN_S); 26132001f49Smrg glDisable(GL_TEXTURE_GEN_T); 26232001f49Smrg glDisable(GL_TEXTURE_GEN_R); 26332001f49Smrg 26432001f49Smrg glMatrixMode(GL_MODELVIEW); 26532001f49Smrg glPushMatrix(); 26632001f49Smrg glRotatef(Xrot, 1, 0, 0); 26732001f49Smrg glRotatef(Yrot, 0, 1, 0); 26832001f49Smrg draw_skybox(); 26932001f49Smrg glPopMatrix(); 27032001f49Smrg 27132001f49Smrg /* sphere */ 27232001f49Smrg glMatrixMode(GL_TEXTURE); 27332001f49Smrg glLoadIdentity(); 27432001f49Smrg glRotatef(-Yrot, 0, 1, 0); 27532001f49Smrg glRotatef(-Xrot, 1, 0, 0); 27632001f49Smrg 27732001f49Smrg glEnable(GL_TEXTURE_GEN_S); 27832001f49Smrg glEnable(GL_TEXTURE_GEN_T); 27932001f49Smrg glEnable(GL_TEXTURE_GEN_R); 28032001f49Smrg glutSolidSphere(2.0, 20, 20); 28132001f49Smrg 28232001f49Smrg glLoadIdentity(); /* texture */ 28332001f49Smrg 28432001f49Smrg glMatrixMode(GL_MODELVIEW); 28532001f49Smrg glPopMatrix(); 28632001f49Smrg 28732001f49Smrg glutSwapBuffers(); 28832001f49Smrg 28932001f49Smrg Frames++; 29032001f49Smrg 29132001f49Smrg { 29232001f49Smrg GLint t = glutGet(GLUT_ELAPSED_TIME); 29332001f49Smrg if (t - T0 >= 5000) { 29432001f49Smrg GLfloat seconds = (t - T0) / 1000.0; 29532001f49Smrg GLfloat fps = Frames / seconds; 29632001f49Smrg printf("%d frames in %6.3f seconds = %6.3f FPS\n", Frames, seconds, fps); 29732001f49Smrg fflush(stdout); 29832001f49Smrg T0 = t; 29932001f49Smrg Frames = 0; 30032001f49Smrg } 30132001f49Smrg } 30232001f49Smrg} 30332001f49Smrg 30432001f49Smrg 30532001f49Smrgstatic void idle(void) 30632001f49Smrg{ 30732001f49Smrg GLfloat t = 0.05 * glutGet(GLUT_ELAPSED_TIME); 30832001f49Smrg Yrot = t; 30932001f49Smrg glutPostRedisplay(); 31032001f49Smrg} 31132001f49Smrg 31232001f49Smrg 31332001f49Smrgstatic void set_mode(GLuint mode) 31432001f49Smrg{ 31532001f49Smrg if (mode == 0) { 31632001f49Smrg glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); 31732001f49Smrg glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); 31832001f49Smrg glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); 31932001f49Smrg printf("GL_REFLECTION_MAP_ARB mode\n"); 32032001f49Smrg } 32132001f49Smrg else if (mode == 1) { 32232001f49Smrg glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); 32332001f49Smrg glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); 32432001f49Smrg glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); 32532001f49Smrg printf("GL_NORMAL_MAP_ARB mode\n"); 32632001f49Smrg } 32732001f49Smrg} 32832001f49Smrg 32932001f49Smrg 33032001f49Smrgstatic void key(unsigned char k, int x, int y) 33132001f49Smrg{ 33232001f49Smrg static GLuint mode = 0; 33332001f49Smrg (void) x; 33432001f49Smrg (void) y; 33532001f49Smrg switch (k) { 33632001f49Smrg case ' ': 33732001f49Smrg anim = !anim; 33832001f49Smrg if (anim) 33932001f49Smrg glutIdleFunc(idle); 34032001f49Smrg else 34132001f49Smrg glutIdleFunc(NULL); 34232001f49Smrg break; 34332001f49Smrg case 'f': 34432001f49Smrg FilterIndex = (FilterIndex + 1) % NUM_FILTER_MODES; 34532001f49Smrg printf("Tex filter: %s\n", FilterModes[FilterIndex].name); 34632001f49Smrg break; 34732001f49Smrg case 'c': 34832001f49Smrg ClampIndex = (ClampIndex + 1) % NUM_CLAMP_MODES; 34932001f49Smrg printf("Tex wrap mode: %s\n", ClampModes[ClampIndex].name); 35032001f49Smrg break; 35132001f49Smrg case 'm': 35232001f49Smrg mode = !mode; 35332001f49Smrg set_mode(mode); 35432001f49Smrg break; 35532001f49Smrg case 's': 35632001f49Smrg seamless = ! seamless; 35732001f49Smrg printf("Seamless cube map filtering is %sabled\n", 35832001f49Smrg (seamless) ? "en" : "dis" ); 35932001f49Smrg break; 36032001f49Smrg case 'v': 36132001f49Smrg use_vertex_arrays = ! use_vertex_arrays; 36232001f49Smrg printf( "Vertex arrays are %sabled\n", 36332001f49Smrg (use_vertex_arrays) ? "en" : "dis" ); 36432001f49Smrg break; 36532001f49Smrg case 'z': 36632001f49Smrg EyeDist -= 0.5; 36732001f49Smrg if (EyeDist < 6.0) 36832001f49Smrg EyeDist = 6.0; 36932001f49Smrg break; 37032001f49Smrg case 'Z': 37132001f49Smrg EyeDist += 0.5; 37232001f49Smrg if (EyeDist > 90.0) 37332001f49Smrg EyeDist = 90; 37432001f49Smrg break; 37532001f49Smrg case 27: 37632001f49Smrg exit(0); 37732001f49Smrg } 37832001f49Smrg fflush(stdout); 37932001f49Smrg glutPostRedisplay(); 38032001f49Smrg} 38132001f49Smrg 38232001f49Smrg 38332001f49Smrgstatic void specialkey(int key, int x, int y) 38432001f49Smrg{ 38532001f49Smrg GLfloat step = 5; 38632001f49Smrg (void) x; 38732001f49Smrg (void) y; 38832001f49Smrg switch (key) { 38932001f49Smrg case GLUT_KEY_UP: 39032001f49Smrg Xrot += step; 39132001f49Smrg break; 39232001f49Smrg case GLUT_KEY_DOWN: 39332001f49Smrg Xrot -= step; 39432001f49Smrg break; 39532001f49Smrg case GLUT_KEY_LEFT: 39632001f49Smrg Yrot -= step; 39732001f49Smrg break; 39832001f49Smrg case GLUT_KEY_RIGHT: 39932001f49Smrg Yrot += step; 40032001f49Smrg break; 40132001f49Smrg } 40232001f49Smrg glutPostRedisplay(); 40332001f49Smrg} 40432001f49Smrg 40532001f49Smrg 40632001f49Smrg/* new window size or exposure */ 40732001f49Smrgstatic void reshape(int width, int height) 40832001f49Smrg{ 40932001f49Smrg GLfloat ar = (float) width / (float) height; 41032001f49Smrg glViewport(0, 0, (GLint)width, (GLint)height); 41132001f49Smrg glMatrixMode(GL_PROJECTION); 41232001f49Smrg glLoadIdentity(); 41332001f49Smrg glFrustum( -2.0*ar, 2.0*ar, -2.0, 2.0, 4.0, 100.0 ); 41432001f49Smrg glMatrixMode(GL_MODELVIEW); 41532001f49Smrg glLoadIdentity(); 41632001f49Smrg} 41732001f49Smrg 41832001f49Smrg 41932001f49Smrgstatic void init_checkers( void ) 42032001f49Smrg{ 42132001f49Smrg#define CUBE_TEX_SIZE 64 42232001f49Smrg GLubyte image[CUBE_TEX_SIZE][CUBE_TEX_SIZE][4]; 42332001f49Smrg static const GLubyte colors[6][3] = { 42432001f49Smrg { 255, 0, 0 }, /* face 0 - red */ 42532001f49Smrg { 0, 255, 255 }, /* face 1 - cyan */ 42632001f49Smrg { 0, 255, 0 }, /* face 2 - green */ 42732001f49Smrg { 255, 0, 255 }, /* face 3 - purple */ 42832001f49Smrg { 0, 0, 255 }, /* face 4 - blue */ 42932001f49Smrg { 255, 255, 0 } /* face 5 - yellow */ 43032001f49Smrg }; 43132001f49Smrg static const GLenum targets[6] = { 43232001f49Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 43332001f49Smrg GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 43432001f49Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 43532001f49Smrg GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 43632001f49Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 43732001f49Smrg GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 43832001f49Smrg }; 43932001f49Smrg 44032001f49Smrg GLint i, j, f; 44132001f49Smrg 44232001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 44332001f49Smrg 44432001f49Smrg if (!supportFBO) 44532001f49Smrg glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 44632001f49Smrg 44732001f49Smrg 44832001f49Smrg /* make colored checkerboard cube faces */ 44932001f49Smrg for (f = 0; f < 6; f++) { 45032001f49Smrg for (i = 0; i < CUBE_TEX_SIZE; i++) { 45132001f49Smrg for (j = 0; j < CUBE_TEX_SIZE; j++) { 45232001f49Smrg if ((i/4 + j/4) & 1) { 45332001f49Smrg image[i][j][0] = colors[f][2]; 45432001f49Smrg image[i][j][1] = colors[f][1]; 45532001f49Smrg image[i][j][2] = colors[f][0]; 45632001f49Smrg image[i][j][3] = 255; 45732001f49Smrg } 45832001f49Smrg else { 45932001f49Smrg image[i][j][0] = 255; 46032001f49Smrg image[i][j][1] = 255; 46132001f49Smrg image[i][j][2] = 255; 46232001f49Smrg image[i][j][3] = 255; 46332001f49Smrg } 46432001f49Smrg } 46532001f49Smrg } 46632001f49Smrg 46732001f49Smrg glTexImage2D(targets[f], 0, GL_RGBA8, CUBE_TEX_SIZE, CUBE_TEX_SIZE, 0, 46832001f49Smrg GL_BGRA, GL_UNSIGNED_BYTE, image); 46932001f49Smrg } 47032001f49Smrg 47132001f49Smrg if (supportFBO) 47232001f49Smrg glGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP_ARB); 47332001f49Smrg} 47432001f49Smrg 47532001f49Smrg 47632001f49Smrgstatic void load(GLenum target, const char *filename, 47732001f49Smrg GLboolean flipTB, GLboolean flipLR) 47832001f49Smrg{ 47932001f49Smrg GLint w, h; 48032001f49Smrg GLenum format; 48132001f49Smrg GLubyte *img = LoadRGBImage( filename, &w, &h, &format ); 48232001f49Smrg if (!img) { 48332001f49Smrg printf("Error: couldn't load texture image %s\n", filename); 48432001f49Smrg exit(1); 48532001f49Smrg } 48632001f49Smrg assert(format == GL_RGB); 48732001f49Smrg 48832001f49Smrg /* <sigh> the way the texture cube mapping works, we have to flip 48932001f49Smrg * images to make things look right. 49032001f49Smrg */ 49132001f49Smrg if (flipTB) { 49232001f49Smrg const int stride = 3 * w; 49332001f49Smrg GLubyte temp[3*1024]; 49432001f49Smrg int i; 49532001f49Smrg for (i = 0; i < h / 2; i++) { 49632001f49Smrg memcpy(temp, img + i * stride, stride); 49732001f49Smrg memcpy(img + i * stride, img + (h - i - 1) * stride, stride); 49832001f49Smrg memcpy(img + (h - i - 1) * stride, temp, stride); 49932001f49Smrg } 50032001f49Smrg } 50132001f49Smrg if (flipLR) { 50232001f49Smrg const int stride = 3 * w; 50332001f49Smrg GLubyte temp[3]; 50432001f49Smrg GLubyte *row; 50532001f49Smrg int i, j; 50632001f49Smrg for (i = 0; i < h; i++) { 50732001f49Smrg row = img + i * stride; 50832001f49Smrg for (j = 0; j < w / 2; j++) { 50932001f49Smrg int k = w - j - 1; 51032001f49Smrg temp[0] = row[j*3+0]; 51132001f49Smrg temp[1] = row[j*3+1]; 51232001f49Smrg temp[2] = row[j*3+2]; 51332001f49Smrg row[j*3+0] = row[k*3+0]; 51432001f49Smrg row[j*3+1] = row[k*3+1]; 51532001f49Smrg row[j*3+2] = row[k*3+2]; 51632001f49Smrg row[k*3+0] = temp[0]; 51732001f49Smrg row[k*3+1] = temp[1]; 51832001f49Smrg row[k*3+2] = temp[2]; 51932001f49Smrg } 52032001f49Smrg } 52132001f49Smrg } 52232001f49Smrg 52332001f49Smrg gluBuild2DMipmaps(target, GL_RGB, w, h, format, GL_UNSIGNED_BYTE, img); 52432001f49Smrg free(img); 52532001f49Smrg} 52632001f49Smrg 52732001f49Smrg 52832001f49Smrgstatic void load_envmaps(void) 52932001f49Smrg{ 53032001f49Smrg load(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, "right.rgb", GL_TRUE, GL_FALSE); 53132001f49Smrg load(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, "left.rgb", GL_TRUE, GL_FALSE); 53232001f49Smrg load(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, "top.rgb", GL_FALSE, GL_TRUE); 53332001f49Smrg load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, "bottom.rgb", GL_FALSE, GL_TRUE); 53432001f49Smrg load(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, "front.rgb", GL_TRUE, GL_FALSE); 53532001f49Smrg load(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, "back.rgb", GL_TRUE, GL_FALSE); 53632001f49Smrg} 53732001f49Smrg 53832001f49Smrg 53932001f49Smrgstatic void init( GLboolean useImageFiles ) 54032001f49Smrg{ 54132001f49Smrg /* check for extensions */ 54232001f49Smrg if (!GLEW_ARB_texture_cube_map) { 54332001f49Smrg printf("Sorry, this demo requires GL_ARB_texture_cube_map\n"); 54432001f49Smrg exit(0); 54532001f49Smrg } 54632001f49Smrg 54732001f49Smrg /* Needed for glGenerateMipmapEXT / auto mipmapping 54832001f49Smrg */ 54932001f49Smrg supportFBO = GLEW_EXT_framebuffer_object; 55032001f49Smrg 55132001f49Smrg if (!supportFBO && !GLEW_SGIS_generate_mipmap) { 55232001f49Smrg printf("Sorry, this demo requires GL_EXT_framebuffer_object or " 55332001f49Smrg "GL_SGIS_generate_mipmap\n"); 55432001f49Smrg exit(0); 55532001f49Smrg } 55632001f49Smrg 55732001f49Smrg /* GLEW doesn't know about this extension yet, so use the old GLUT function 55832001f49Smrg * to check for availability. 55932001f49Smrg */ 56032001f49Smrg supportSeamless = glutExtensionSupported("GL_ARB_seamless_cube_map"); 56132001f49Smrg 56232001f49Smrg printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); 56332001f49Smrg 56432001f49Smrg 56532001f49Smrg glGenTextures(1, &TexObj); 56632001f49Smrg glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, TexObj); 56732001f49Smrg 56832001f49Smrg if (useImageFiles) { 56932001f49Smrg load_envmaps(); 57032001f49Smrg } 57132001f49Smrg else { 57232001f49Smrg init_checkers(); 57332001f49Smrg } 57432001f49Smrg 57532001f49Smrg glEnable(GL_TEXTURE_CUBE_MAP_ARB); 57632001f49Smrg glEnable(GL_DEPTH_TEST); 57732001f49Smrg 57832001f49Smrg glClearColor(.3, .3, .3, 0); 57932001f49Smrg glColor3f( 1.0, 1.0, 1.0 ); 58032001f49Smrg 58132001f49Smrg set_mode(0); 58232001f49Smrg} 58332001f49Smrg 58432001f49Smrg 58532001f49Smrgstatic void usage(void) 58632001f49Smrg{ 58732001f49Smrg printf("keys:\n"); 58832001f49Smrg printf(" SPACE - toggle animation\n"); 58932001f49Smrg printf(" CURSOR KEYS - rotation\n"); 59032001f49Smrg printf(" c - toggle texture clamp/wrap mode\n"); 59132001f49Smrg printf(" f - toggle texture filter mode\n"); 59232001f49Smrg printf(" m - toggle texgen reflection mode\n"); 59332001f49Smrg printf(" z/Z - change viewing distance\n"); 59432001f49Smrg fflush(stdout); 59532001f49Smrg} 59632001f49Smrg 59732001f49Smrg 59832001f49Smrgstatic void parse_args(int argc, char *argv[]) 59932001f49Smrg{ 60032001f49Smrg int initFlag = 0; 60132001f49Smrg int i; 60232001f49Smrg 60332001f49Smrg for (i = 1; i < argc; i++) { 60432001f49Smrg if (strcmp(argv[i], "-i") == 0) 60532001f49Smrg initFlag = 1; 60632001f49Smrg else if (strcmp(argv[i], "--noclear") == 0) 60732001f49Smrg NoClear = GL_TRUE; 60832001f49Smrg else { 60932001f49Smrg fprintf(stderr, "Bad option: %s\n", argv[i]); 61032001f49Smrg exit(1); 61132001f49Smrg } 61232001f49Smrg } 61332001f49Smrg init (initFlag); 61432001f49Smrg} 61532001f49Smrg 61632001f49Smrgint main( int argc, char *argv[] ) 61732001f49Smrg{ 61832001f49Smrg glutInitWindowSize(600, 500); 61932001f49Smrg glutInit(&argc, argv); 62032001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ); 62132001f49Smrg glutCreateWindow("Texture Cube Mapping"); 62232001f49Smrg glewInit(); 62332001f49Smrg glutReshapeFunc( reshape ); 62432001f49Smrg glutKeyboardFunc( key ); 62532001f49Smrg glutSpecialFunc( specialkey ); 62632001f49Smrg glutDisplayFunc( draw ); 62732001f49Smrg if (anim) 62832001f49Smrg glutIdleFunc(idle); 62932001f49Smrg parse_args(argc, argv); 63032001f49Smrg usage(); 63132001f49Smrg glutMainLoop(); 63232001f49Smrg return 0; 63332001f49Smrg} 634