132001f49Smrg/* 232001f49Smrg * (C) Copyright IBM Corporation 2005 332001f49Smrg * All Rights Reserved. 432001f49Smrg * 532001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a 632001f49Smrg * copy of this software and associated documentation files (the "Software"), 732001f49Smrg * to deal in the Software without restriction, including without limitation 832001f49Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub 932001f49Smrg * license, and/or sell copies of the Software, and to permit persons to whom 1032001f49Smrg * the Software is furnished to do so, subject to the following conditions: 1132001f49Smrg * 1232001f49Smrg * The above copyright notice and this permission notice (including the next 1332001f49Smrg * paragraph) shall be included in all copies or substantial portions of the 1432001f49Smrg * Software. 1532001f49Smrg * 1632001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1732001f49Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 1932001f49Smrg * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 2032001f49Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 2132001f49Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 2232001f49Smrg * USE OR OTHER DEALINGS IN THE SOFTWARE. 2332001f49Smrg */ 2432001f49Smrg 2532001f49Smrg 2632001f49Smrg#include <stdio.h> 2732001f49Smrg#include <stdlib.h> 2832001f49Smrg#include <string.h> 2932001f49Smrg#include <math.h> 3032001f49Smrg#include <GL/glew.h> 3132001f49Smrg#include "glut_wrap.h" 3232001f49Smrg 3332001f49Smrgconst GLenum filter_modes[] = { 3432001f49Smrg GL_NEAREST, 3532001f49Smrg GL_LINEAR, 3632001f49Smrg GL_NEAREST_MIPMAP_NEAREST, 3732001f49Smrg GL_NEAREST_MIPMAP_LINEAR, 3832001f49Smrg GL_LINEAR_MIPMAP_NEAREST, 3932001f49Smrg GL_LINEAR_MIPMAP_LINEAR, 4032001f49Smrg}; 4132001f49Smrg 4232001f49Smrgstatic GLenum min_filter = GL_LINEAR_MIPMAP_LINEAR; 4332001f49Smrgstatic GLenum mag_filter = GL_LINEAR; 4432001f49Smrg 4532001f49Smrgstatic unsigned segments = 64; 4632001f49Smrgstatic GLfloat * position_data = NULL; 4732001f49Smrgstatic GLfloat * texcoord_data = NULL; 4832001f49Smrgstatic GLfloat max_anisotropy = 0.0; 4932001f49Smrgstatic GLfloat anisotropy = 1.0; 5032001f49Smrg 5132001f49Smrgstatic void generate_tunnel( unsigned num_segs, GLfloat ** pos_data, 5232001f49Smrg GLfloat ** tex_data ); 5332001f49Smrgstatic void generate_textures( unsigned mode ); 5432001f49Smrg 5532001f49Smrg#define min(a,b) ( (a) < (b) ) ? (a) : (b) 5632001f49Smrg#define max(a,b) ( (a) > (b) ) ? (a) : (b) 5732001f49Smrg 5832001f49Smrg 5932001f49Smrgstatic void Display( void ) 6032001f49Smrg{ 6132001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter ); 6232001f49Smrg glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter ); 6332001f49Smrg 6432001f49Smrg if ( max_anisotropy > 0.0 ) { 6532001f49Smrg glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 6632001f49Smrg anisotropy ); 6732001f49Smrg } 6832001f49Smrg 6932001f49Smrg glClear( GL_COLOR_BUFFER_BIT ); 7032001f49Smrg glLoadIdentity(); 7132001f49Smrg glTranslatef( 0.0f, 0.0f, -19.0f ); 7232001f49Smrg 7332001f49Smrg glVertexPointer( 4, GL_FLOAT, 0, position_data ); 7432001f49Smrg glTexCoordPointer( 2, GL_FLOAT, 0, texcoord_data ); 7532001f49Smrg glEnableClientState( GL_VERTEX_ARRAY ); 7632001f49Smrg glEnableClientState( GL_TEXTURE_COORD_ARRAY ); 7732001f49Smrg glDrawArrays( GL_QUADS, 0, 4 * segments ); 7832001f49Smrg glutSwapBuffers(); 7932001f49Smrg} 8032001f49Smrg 8132001f49Smrg 8232001f49Smrgstatic void Reshape( int width, int height ) 8332001f49Smrg{ 8432001f49Smrg glViewport(0, 0, width, height); 8532001f49Smrg glMatrixMode(GL_PROJECTION); 8632001f49Smrg glLoadIdentity(); 8732001f49Smrg gluPerspective(45.0f, (GLfloat)(width)/(GLfloat)(height), 0.1f, 100.0f); 8832001f49Smrg glMatrixMode(GL_MODELVIEW); 8932001f49Smrg glLoadIdentity(); 9032001f49Smrg} 9132001f49Smrg 9232001f49Smrg 9332001f49Smrgstatic void Key( unsigned char key, int x, int y ) 9432001f49Smrg{ 9532001f49Smrg GLfloat new_anisotropy = anisotropy; 9632001f49Smrg 9732001f49Smrg (void) x; 9832001f49Smrg (void) y; 9932001f49Smrg 10032001f49Smrg 10132001f49Smrg switch( key ) { 10232001f49Smrg case 'a': { 10332001f49Smrg new_anisotropy = anisotropy - 1.0; 10432001f49Smrg break; 10532001f49Smrg } 10632001f49Smrg 10732001f49Smrg case 'A': { 10832001f49Smrg new_anisotropy = anisotropy + 1.0; 10932001f49Smrg break; 11032001f49Smrg } 11132001f49Smrg 11232001f49Smrg case 's': { 11332001f49Smrg segments--; 11432001f49Smrg if ( segments < 3 ) { 11532001f49Smrg segments = 3; 11632001f49Smrg } 11732001f49Smrg generate_tunnel( segments, & position_data, & texcoord_data ); 11832001f49Smrg break; 11932001f49Smrg } 12032001f49Smrg 12132001f49Smrg case 'S': { 12232001f49Smrg segments++; 12332001f49Smrg if ( segments > 128 ) { 12432001f49Smrg segments = 128; 12532001f49Smrg } 12632001f49Smrg generate_tunnel( segments, & position_data, & texcoord_data ); 12732001f49Smrg break; 12832001f49Smrg } 12932001f49Smrg case 'q': 13032001f49Smrg case 'Q': 13132001f49Smrg case 27: 13232001f49Smrg exit(0); 13332001f49Smrg break; 13432001f49Smrg } 13532001f49Smrg 13632001f49Smrg new_anisotropy = max( new_anisotropy, 1.0 ); 13732001f49Smrg new_anisotropy = min( new_anisotropy, max_anisotropy ); 13832001f49Smrg if ( new_anisotropy != anisotropy ) { 13932001f49Smrg anisotropy = new_anisotropy; 14032001f49Smrg printf( "Texture anisotropy: %f%s\n", anisotropy, 14132001f49Smrg (anisotropy == 1.0) ? " (disabled)" : "" ); 14232001f49Smrg } 14332001f49Smrg 14432001f49Smrg glutPostRedisplay(); 14532001f49Smrg} 14632001f49Smrg 14732001f49Smrg 14832001f49Smrgstatic void SpecialKey( int key, int x, int y ) 14932001f49Smrg{ 15032001f49Smrg (void) x; 15132001f49Smrg (void) y; 15232001f49Smrg (void) key; 15332001f49Smrg glutPostRedisplay(); 15432001f49Smrg} 15532001f49Smrg 15632001f49Smrg 15732001f49Smrgstatic void menu_handler( int selection ) 15832001f49Smrg{ 15932001f49Smrg switch( selection >> 3 ) { 16032001f49Smrg case 0: 16132001f49Smrg glBindTexture( GL_TEXTURE_2D, selection ); 16232001f49Smrg break; 16332001f49Smrg 16432001f49Smrg case 1: 16532001f49Smrg min_filter = filter_modes[ selection & 7 ]; 16632001f49Smrg break; 16732001f49Smrg 16832001f49Smrg case 2: 16932001f49Smrg mag_filter = filter_modes[ selection & 7 ]; 17032001f49Smrg break; 17132001f49Smrg } 17232001f49Smrg 17332001f49Smrg glutPostRedisplay(); 17432001f49Smrg} 17532001f49Smrg 17632001f49Smrg 17732001f49Smrgstatic void Init( void ) 17832001f49Smrg{ 17932001f49Smrg glDisable(GL_CULL_FACE); 18032001f49Smrg glEnable(GL_TEXTURE_2D); 18132001f49Smrg glClearColor(0.0f, 0.0f, 0.4f, 0.0f); 18232001f49Smrg glShadeModel(GL_SMOOTH); 18332001f49Smrg glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 18432001f49Smrg 18532001f49Smrg generate_tunnel( segments, & position_data, & texcoord_data ); 18632001f49Smrg 18732001f49Smrg glBindTexture( GL_TEXTURE_2D, 1 ); 18832001f49Smrg generate_textures(1); 18932001f49Smrg 19032001f49Smrg glBindTexture( GL_TEXTURE_2D, 2 ); 19132001f49Smrg generate_textures(2); 19232001f49Smrg 19332001f49Smrg glBindTexture( GL_TEXTURE_2D, 3 ); 19432001f49Smrg generate_textures(3); 19532001f49Smrg 19632001f49Smrg if ( glutExtensionSupported( "GL_EXT_texture_filter_anisotropic" ) ) { 19732001f49Smrg glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, & max_anisotropy ); 19832001f49Smrg } 19932001f49Smrg 20032001f49Smrg printf("Maximum texture anisotropy: %f\n", max_anisotropy ); 20132001f49Smrg 20232001f49Smrg /* Create the menus. */ 20332001f49Smrg 20432001f49Smrg glutCreateMenu( menu_handler ); 20532001f49Smrg glutAddMenuEntry( "Min filter: GL_NEAREST", 8 + 0 ); 20632001f49Smrg glutAddMenuEntry( "Min filter: GL_LINEAR", 8 + 1 ); 20732001f49Smrg glutAddMenuEntry( "Min filter: GL_NEAREST_MIMMAP_NEAREST", 8 + 2 ); 20832001f49Smrg glutAddMenuEntry( "Min filter: GL_NEAREST_MIMMAP_LINEAR", 8 + 3 ); 20932001f49Smrg glutAddMenuEntry( "Min filter: GL_LINEAR_MIMMAP_NEAREST", 8 + 4 ); 21032001f49Smrg glutAddMenuEntry( "Min filter: GL_LINEAR_MIMMAP_LINEAR", 8 + 5 ); 21132001f49Smrg glutAddMenuEntry( "Mag filter: GL_NEAREST", 16 + 0 ); 21232001f49Smrg glutAddMenuEntry( "Mag filter: GL_LINEAR", 16 + 1 ); 21332001f49Smrg glutAddMenuEntry( "Texture: regular mipmaps", 1 ); 21432001f49Smrg glutAddMenuEntry( "Texture: blended mipmaps", 2 ); 21532001f49Smrg glutAddMenuEntry( "Texture: color mipmaps", 3 ); 21632001f49Smrg glutAttachMenu( GLUT_RIGHT_BUTTON ); 21732001f49Smrg} 21832001f49Smrg 21932001f49Smrg 22032001f49Smrgstatic void generate_tunnel( unsigned num_segs, GLfloat ** pos_data, 22132001f49Smrg GLfloat ** tex_data ) 22232001f49Smrg{ 22332001f49Smrg const GLfloat far_distance = 20.0f; 22432001f49Smrg const GLfloat near_distance = -90.0f; 22532001f49Smrg const GLfloat far_tex = 30.0f; 22632001f49Smrg const GLfloat near_tex = 0.0f; 22732001f49Smrg const GLfloat angle_step = (2 * M_PI) / num_segs; 22832001f49Smrg const GLfloat tex_coord_step = 2.0 / num_segs; 22932001f49Smrg GLfloat angle = 0.0f; 23032001f49Smrg GLfloat tex_coord = 0.0f; 23132001f49Smrg unsigned i; 23232001f49Smrg GLfloat * position; 23332001f49Smrg GLfloat * texture; 23432001f49Smrg 23532001f49Smrg 23632001f49Smrg position = realloc( *pos_data, sizeof( GLfloat ) * num_segs * 4 * 4 ); 23732001f49Smrg texture = realloc( *tex_data, sizeof( GLfloat ) * num_segs * 4 * 2 ); 23832001f49Smrg 23932001f49Smrg *pos_data = position; 24032001f49Smrg *tex_data = texture; 24132001f49Smrg 24232001f49Smrg for ( i = 0 ; i < num_segs ; i++ ) { 24332001f49Smrg position[0] = 2.5 * sinf( angle ); 24432001f49Smrg position[1] = 2.5 * cosf( angle ); 24532001f49Smrg position[2] = (i & 1) ? far_distance : near_distance; 24632001f49Smrg position[3] = 1.0f; 24732001f49Smrg 24832001f49Smrg position[4] = position[0]; 24932001f49Smrg position[5] = position[1]; 25032001f49Smrg position[6] = (i & 1) ? near_distance : far_distance; 25132001f49Smrg position[7] = 1.0f; 25232001f49Smrg 25332001f49Smrg position += 8; 25432001f49Smrg 25532001f49Smrg texture[0] = tex_coord; 25632001f49Smrg texture[1] = (i & 1) ? far_tex : near_tex; 25732001f49Smrg texture += 2; 25832001f49Smrg 25932001f49Smrg texture[0] = tex_coord; 26032001f49Smrg texture[1] = (i & 1) ? near_tex : far_tex; 26132001f49Smrg texture += 2; 26232001f49Smrg 26332001f49Smrg angle += angle_step; 26432001f49Smrg tex_coord += tex_coord_step; 26532001f49Smrg 26632001f49Smrg position[0] = 2.5 * sinf( angle ); 26732001f49Smrg position[1] = 2.5 * cosf( angle ); 26832001f49Smrg position[2] = (i & 1) ? near_distance : far_distance; 26932001f49Smrg position[3] = 1.0f; 27032001f49Smrg 27132001f49Smrg position[4] = position[0]; 27232001f49Smrg position[5] = position[1]; 27332001f49Smrg position[6] = (i & 1) ? far_distance : near_distance; 27432001f49Smrg position[7] = 1.0f; 27532001f49Smrg 27632001f49Smrg position += 8; 27732001f49Smrg 27832001f49Smrg texture[0] = tex_coord; 27932001f49Smrg texture[1] = (i & 1) ? near_tex : far_tex; 28032001f49Smrg texture += 2; 28132001f49Smrg 28232001f49Smrg texture[0] = tex_coord; 28332001f49Smrg texture[1] = (i & 1) ? far_tex : near_tex; 28432001f49Smrg texture += 2; 28532001f49Smrg } 28632001f49Smrg} 28732001f49Smrg 28832001f49Smrg 28932001f49Smrgstatic void generate_textures( unsigned mode ) 29032001f49Smrg{ 29132001f49Smrg#define LEVEL_COLORS 6 29232001f49Smrg const GLfloat colors[LEVEL_COLORS][3] = { 29332001f49Smrg { 1.0, 0.0, 0.0 }, /* 32 x 32 */ 29432001f49Smrg { 0.0, 1.0, 0.0 }, /* 16 x 16 */ 29532001f49Smrg { 0.0, 0.0, 1.0 }, /* 8 x 8 */ 29632001f49Smrg { 1.0, 0.0, 1.0 }, /* 4 x 4 */ 29732001f49Smrg { 1.0, 1.0, 1.0 }, /* 2 x 2 */ 29832001f49Smrg { 1.0, 1.0, 0.0 } /* 1 x 1 */ 29932001f49Smrg }; 30032001f49Smrg const unsigned checkers_per_level = 2; 30132001f49Smrg GLfloat * tex; 30232001f49Smrg unsigned level; 30332001f49Smrg unsigned size; 30432001f49Smrg GLint max_size; 30532001f49Smrg 30632001f49Smrg 30732001f49Smrg glGetIntegerv( GL_MAX_TEXTURE_SIZE, & max_size ); 30832001f49Smrg if ( max_size > 512 ) { 30932001f49Smrg max_size = 512; 31032001f49Smrg } 31132001f49Smrg 31232001f49Smrg tex = malloc( sizeof( GLfloat ) * 3 * max_size * max_size ); 31332001f49Smrg 31432001f49Smrg level = 0; 31532001f49Smrg for ( size = max_size ; size > 0 ; size >>= 1 ) { 31632001f49Smrg unsigned divisor = size / checkers_per_level; 31732001f49Smrg unsigned i; 31832001f49Smrg unsigned j; 31932001f49Smrg GLfloat checkers[2][3]; 32032001f49Smrg 32132001f49Smrg 32232001f49Smrg if ((level == 0) || (mode == 1)) { 32332001f49Smrg checkers[0][0] = 1.0; 32432001f49Smrg checkers[0][1] = 1.0; 32532001f49Smrg checkers[0][2] = 1.0; 32632001f49Smrg checkers[1][0] = 0.0; 32732001f49Smrg checkers[1][1] = 0.0; 32832001f49Smrg checkers[1][2] = 0.0; 32932001f49Smrg } 33032001f49Smrg else if (mode == 2) { 33132001f49Smrg checkers[0][0] = colors[level % LEVEL_COLORS][0]; 33232001f49Smrg checkers[0][1] = colors[level % LEVEL_COLORS][1]; 33332001f49Smrg checkers[0][2] = colors[level % LEVEL_COLORS][2]; 33432001f49Smrg checkers[1][0] = colors[level % LEVEL_COLORS][0] * 0.5; 33532001f49Smrg checkers[1][1] = colors[level % LEVEL_COLORS][1] * 0.5; 33632001f49Smrg checkers[1][2] = colors[level % LEVEL_COLORS][2] * 0.5; 33732001f49Smrg } 33832001f49Smrg else { 33932001f49Smrg checkers[0][0] = colors[level % LEVEL_COLORS][0]; 34032001f49Smrg checkers[0][1] = colors[level % LEVEL_COLORS][1]; 34132001f49Smrg checkers[0][2] = colors[level % LEVEL_COLORS][2]; 34232001f49Smrg checkers[1][0] = colors[level % LEVEL_COLORS][0]; 34332001f49Smrg checkers[1][1] = colors[level % LEVEL_COLORS][1]; 34432001f49Smrg checkers[1][2] = colors[level % LEVEL_COLORS][2]; 34532001f49Smrg } 34632001f49Smrg 34732001f49Smrg if ( divisor == 0 ) { 34832001f49Smrg divisor = 1; 34932001f49Smrg 35032001f49Smrg checkers[0][0] = (checkers[0][0] + checkers[1][0]) / 2; 35132001f49Smrg checkers[0][1] = (checkers[0][0] + checkers[1][0]) / 2; 35232001f49Smrg checkers[0][2] = (checkers[0][0] + checkers[1][0]) / 2; 35332001f49Smrg checkers[1][0] = checkers[0][0]; 35432001f49Smrg checkers[1][1] = checkers[0][1]; 35532001f49Smrg checkers[1][2] = checkers[0][2]; 35632001f49Smrg } 35732001f49Smrg 35832001f49Smrg 35932001f49Smrg for ( i = 0 ; i < size ; i++ ) { 36032001f49Smrg for ( j = 0 ; j < size ; j++ ) { 36132001f49Smrg const unsigned idx = ((i ^ j) / divisor) & 1; 36232001f49Smrg 36332001f49Smrg tex[ ((i * size) + j) * 3 + 0] = checkers[ idx ][0]; 36432001f49Smrg tex[ ((i * size) + j) * 3 + 1] = checkers[ idx ][1]; 36532001f49Smrg tex[ ((i * size) + j) * 3 + 2] = checkers[ idx ][2]; 36632001f49Smrg } 36732001f49Smrg } 36832001f49Smrg 36932001f49Smrg glTexImage2D( GL_TEXTURE_2D, level, GL_RGB, size, size, 0, 37032001f49Smrg GL_RGB, GL_FLOAT, tex ); 37132001f49Smrg level++; 37232001f49Smrg } 37332001f49Smrg 37432001f49Smrg free( tex ); 37532001f49Smrg} 37632001f49Smrg 37732001f49Smrg 37832001f49Smrgint main( int argc, char ** argv ) 37932001f49Smrg{ 38032001f49Smrg glutInit( &argc, argv ); 38132001f49Smrg glutInitWindowPosition( 0, 0 ); 38232001f49Smrg glutInitWindowSize( 800, 600 ); 38332001f49Smrg glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE ); 38432001f49Smrg glutCreateWindow( "Texture Filter Test" ); 38532001f49Smrg glewInit(); 38632001f49Smrg glutReshapeFunc( Reshape ); 38732001f49Smrg glutKeyboardFunc( Key ); 38832001f49Smrg glutSpecialFunc( SpecialKey ); 38932001f49Smrg glutDisplayFunc( Display ); 39032001f49Smrg 39132001f49Smrg Init(); 39232001f49Smrg 39332001f49Smrg printf("\nUse the right-button menu to select the texture and filter mode.\n"); 39432001f49Smrg printf("Use 'A' and 'a' to increase and decrease the aniotropy.\n"); 39532001f49Smrg printf("Use 'S' and 's' to increase and decrease the number of cylinder segments.\n"); 39632001f49Smrg printf("Use 'q' to exit.\n\n"); 39732001f49Smrg 39832001f49Smrg glutMainLoop(); 39932001f49Smrg return 0; 40032001f49Smrg} 401