2 * (C) Copyright IBM Corporation 2005
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
33 const GLenum filter_modes
[] = {
36 GL_NEAREST_MIPMAP_NEAREST
,
37 GL_NEAREST_MIPMAP_LINEAR
,
38 GL_LINEAR_MIPMAP_NEAREST
,
39 GL_LINEAR_MIPMAP_LINEAR
,
42 static GLenum min_filter
= GL_LINEAR_MIPMAP_LINEAR
;
43 static GLenum mag_filter
= GL_LINEAR
;
45 static unsigned segments
= 64;
46 static GLfloat
* position_data
= NULL
;
47 static GLfloat
* texcoord_data
= NULL
;
48 static GLfloat max_anisotropy
= 0.0;
49 static GLfloat anisotropy
= 1.0;
51 static void generate_tunnel( unsigned num_segs
, GLfloat
** pos_data
,
52 GLfloat
** tex_data
);
53 static void generate_textures( unsigned mode
);
55 #define min(a,b) ( (a) < (b) ) ? (a) : (b)
56 #define max(a,b) ( (a) > (b) ) ? (a) : (b)
59 static void Display( void )
61 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, min_filter
);
62 glTexParameteri( GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, mag_filter
);
64 if ( max_anisotropy
> 0.0 ) {
65 glTexParameterf( GL_TEXTURE_2D
, GL_TEXTURE_MAX_ANISOTROPY_EXT
,
69 glClear( GL_COLOR_BUFFER_BIT
);
71 glTranslatef( 0.0f
, 0.0f
, -19.0f
);
73 glVertexPointer( 4, GL_FLOAT
, 0, position_data
);
74 glTexCoordPointer( 2, GL_FLOAT
, 0, texcoord_data
);
75 glEnableClientState( GL_VERTEX_ARRAY
);
76 glEnableClientState( GL_TEXTURE_COORD_ARRAY
);
77 glDrawArrays( GL_QUADS
, 0, 4 * segments
);
82 static void Reshape( int width
, int height
)
84 glViewport(0, 0, width
, height
);
85 glMatrixMode(GL_PROJECTION
);
87 gluPerspective(45.0f
, (GLfloat
)(width
)/(GLfloat
)(height
), 0.1f
, 100.0f
);
88 glMatrixMode(GL_MODELVIEW
);
93 static void Key( unsigned char key
, int x
, int y
)
95 GLfloat new_anisotropy
= anisotropy
;
103 new_anisotropy
= anisotropy
- 1.0;
108 new_anisotropy
= anisotropy
+ 1.0;
114 if ( segments
< 3 ) {
117 generate_tunnel( segments
, & position_data
, & texcoord_data
);
123 if ( segments
> 128 ) {
126 generate_tunnel( segments
, & position_data
, & texcoord_data
);
136 new_anisotropy
= max( new_anisotropy
, 1.0 );
137 new_anisotropy
= min( new_anisotropy
, max_anisotropy
);
138 if ( new_anisotropy
!= anisotropy
) {
139 anisotropy
= new_anisotropy
;
140 printf( "Texture anisotropy: %f%s\n", anisotropy
,
141 (anisotropy
== 1.0) ? " (disabled)" : "" );
148 static void SpecialKey( int key
, int x
, int y
)
157 static void menu_handler( int selection
)
159 switch( selection
>> 3 ) {
161 glBindTexture( GL_TEXTURE_2D
, selection
);
165 min_filter
= filter_modes
[ selection
& 7 ];
169 mag_filter
= filter_modes
[ selection
& 7 ];
177 static void Init( void )
179 glDisable(GL_CULL_FACE
);
180 glEnable(GL_TEXTURE_2D
);
181 glClearColor(0.0f
, 0.0f
, 0.4f
, 0.0f
);
182 glShadeModel(GL_SMOOTH
);
183 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_NICEST
);
185 generate_tunnel( segments
, & position_data
, & texcoord_data
);
187 glBindTexture( GL_TEXTURE_2D
, 1 );
188 generate_textures(1);
190 glBindTexture( GL_TEXTURE_2D
, 2 );
191 generate_textures(2);
193 glBindTexture( GL_TEXTURE_2D
, 3 );
194 generate_textures(3);
196 if ( glutExtensionSupported( "GL_EXT_texture_filter_anisotropic" ) ) {
197 glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
, & max_anisotropy
);
200 printf("Maximum texture anisotropy: %f\n", max_anisotropy
);
202 /* Create the menus. */
204 glutCreateMenu( menu_handler
);
205 glutAddMenuEntry( "Min filter: GL_NEAREST", 8 + 0 );
206 glutAddMenuEntry( "Min filter: GL_LINEAR", 8 + 1 );
207 glutAddMenuEntry( "Min filter: GL_NEAREST_MIMMAP_NEAREST", 8 + 2 );
208 glutAddMenuEntry( "Min filter: GL_NEAREST_MIMMAP_LINEAR", 8 + 3 );
209 glutAddMenuEntry( "Min filter: GL_LINEAR_MIMMAP_NEAREST", 8 + 4 );
210 glutAddMenuEntry( "Min filter: GL_LINEAR_MIMMAP_LINEAR", 8 + 5 );
211 glutAddMenuEntry( "Mag filter: GL_NEAREST", 16 + 0 );
212 glutAddMenuEntry( "Mag filter: GL_LINEAR", 16 + 1 );
213 glutAddMenuEntry( "Texture: regular mipmaps", 1 );
214 glutAddMenuEntry( "Texture: blended mipmaps", 2 );
215 glutAddMenuEntry( "Texture: color mipmaps", 3 );
216 glutAttachMenu( GLUT_RIGHT_BUTTON
);
220 static void generate_tunnel( unsigned num_segs
, GLfloat
** pos_data
,
221 GLfloat
** tex_data
)
223 const GLfloat far_distance
= 20.0f
;
224 const GLfloat near_distance
= -90.0f
;
225 const GLfloat far_tex
= 30.0f
;
226 const GLfloat near_tex
= 0.0f
;
227 const GLfloat angle_step
= (2 * M_PI
) / num_segs
;
228 const GLfloat tex_coord_step
= 2.0 / num_segs
;
229 GLfloat angle
= 0.0f
;
230 GLfloat tex_coord
= 0.0f
;
236 position
= realloc( *pos_data
, sizeof( GLfloat
) * num_segs
* 4 * 4 );
237 texture
= realloc( *tex_data
, sizeof( GLfloat
) * num_segs
* 4 * 2 );
239 *pos_data
= position
;
242 for ( i
= 0 ; i
< num_segs
; i
++ ) {
243 position
[0] = 2.5 * sinf( angle
);
244 position
[1] = 2.5 * cosf( angle
);
245 position
[2] = (i
& 1) ? far_distance
: near_distance
;
248 position
[4] = position
[0];
249 position
[5] = position
[1];
250 position
[6] = (i
& 1) ? near_distance
: far_distance
;
255 texture
[0] = tex_coord
;
256 texture
[1] = (i
& 1) ? far_tex
: near_tex
;
259 texture
[0] = tex_coord
;
260 texture
[1] = (i
& 1) ? near_tex
: far_tex
;
264 tex_coord
+= tex_coord_step
;
266 position
[0] = 2.5 * sinf( angle
);
267 position
[1] = 2.5 * cosf( angle
);
268 position
[2] = (i
& 1) ? near_distance
: far_distance
;
271 position
[4] = position
[0];
272 position
[5] = position
[1];
273 position
[6] = (i
& 1) ? far_distance
: near_distance
;
278 texture
[0] = tex_coord
;
279 texture
[1] = (i
& 1) ? near_tex
: far_tex
;
282 texture
[0] = tex_coord
;
283 texture
[1] = (i
& 1) ? far_tex
: near_tex
;
289 static void generate_textures( unsigned mode
)
291 #define LEVEL_COLORS 6
292 const GLfloat colors
[LEVEL_COLORS
][3] = {
293 { 1.0, 0.0, 0.0 }, /* 32 x 32 */
294 { 0.0, 1.0, 0.0 }, /* 16 x 16 */
295 { 0.0, 0.0, 1.0 }, /* 8 x 8 */
296 { 1.0, 0.0, 1.0 }, /* 4 x 4 */
297 { 1.0, 1.0, 1.0 }, /* 2 x 2 */
298 { 1.0, 1.0, 0.0 } /* 1 x 1 */
300 const unsigned checkers_per_level
= 2;
307 glGetIntegerv( GL_MAX_TEXTURE_SIZE
, & max_size
);
308 if ( max_size
> 512 ) {
312 tex
= malloc( sizeof( GLfloat
) * 3 * max_size
* max_size
);
315 for ( size
= max_size
; size
> 0 ; size
>>= 1 ) {
316 unsigned divisor
= size
/ checkers_per_level
;
319 GLfloat checkers
[2][3];
322 if ((level
== 0) || (mode
== 1)) {
323 checkers
[0][0] = 1.0;
324 checkers
[0][1] = 1.0;
325 checkers
[0][2] = 1.0;
326 checkers
[1][0] = 0.0;
327 checkers
[1][1] = 0.0;
328 checkers
[1][2] = 0.0;
330 else if (mode
== 2) {
331 checkers
[0][0] = colors
[level
% LEVEL_COLORS
][0];
332 checkers
[0][1] = colors
[level
% LEVEL_COLORS
][1];
333 checkers
[0][2] = colors
[level
% LEVEL_COLORS
][2];
334 checkers
[1][0] = colors
[level
% LEVEL_COLORS
][0] * 0.5;
335 checkers
[1][1] = colors
[level
% LEVEL_COLORS
][1] * 0.5;
336 checkers
[1][2] = colors
[level
% LEVEL_COLORS
][2] * 0.5;
339 checkers
[0][0] = colors
[level
% LEVEL_COLORS
][0];
340 checkers
[0][1] = colors
[level
% LEVEL_COLORS
][1];
341 checkers
[0][2] = colors
[level
% LEVEL_COLORS
][2];
342 checkers
[1][0] = colors
[level
% LEVEL_COLORS
][0];
343 checkers
[1][1] = colors
[level
% LEVEL_COLORS
][1];
344 checkers
[1][2] = colors
[level
% LEVEL_COLORS
][2];
347 if ( divisor
== 0 ) {
350 checkers
[0][0] = (checkers
[0][0] + checkers
[1][0]) / 2;
351 checkers
[0][1] = (checkers
[0][0] + checkers
[1][0]) / 2;
352 checkers
[0][2] = (checkers
[0][0] + checkers
[1][0]) / 2;
353 checkers
[1][0] = checkers
[0][0];
354 checkers
[1][1] = checkers
[0][1];
355 checkers
[1][2] = checkers
[0][2];
359 for ( i
= 0 ; i
< size
; i
++ ) {
360 for ( j
= 0 ; j
< size
; j
++ ) {
361 const unsigned idx
= ((i
^ j
) / divisor
) & 1;
363 tex
[ ((i
* size
) + j
) * 3 + 0] = checkers
[ idx
][0];
364 tex
[ ((i
* size
) + j
) * 3 + 1] = checkers
[ idx
][1];
365 tex
[ ((i
* size
) + j
) * 3 + 2] = checkers
[ idx
][2];
369 glTexImage2D( GL_TEXTURE_2D
, level
, GL_RGB
, size
, size
, 0,
370 GL_RGB
, GL_FLOAT
, tex
);
378 int main( int argc
, char ** argv
)
380 glutInit( &argc
, argv
);
381 glutInitWindowPosition( 0, 0 );
382 glutInitWindowSize( 800, 600 );
383 glutInitDisplayMode( GLUT_RGB
| GLUT_DOUBLE
);
384 glutCreateWindow( "Texture Filter Test" );
386 glutReshapeFunc( Reshape
);
387 glutKeyboardFunc( Key
);
388 glutSpecialFunc( SpecialKey
);
389 glutDisplayFunc( Display
);
393 printf("\nUse the right-button menu to select the texture and filter mode.\n");
394 printf("Use 'A' and 'a' to increase and decrease the aniotropy.\n");
395 printf("Use 'S' and 's' to increase and decrease the number of cylinder segments.\n");
396 printf("Use 'q' to exit.\n\n");