mipmap_limits.c revision 32001f49
1/* Test GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL 2 * Brian Paul 3 * 10 May 2006 4 */ 5 6 7/* Copyright (c) Mark J. Kilgard, 1994. */ 8 9/* 10 * (c) Copyright 1993, Silicon Graphics, Inc. 11 * ALL RIGHTS RESERVED 12 * Permission to use, copy, modify, and distribute this software for 13 * any purpose and without fee is hereby granted, provided that the above 14 * copyright notice appear in all copies and that both the copyright notice 15 * and this permission notice appear in supporting documentation, and that 16 * the name of Silicon Graphics, Inc. not be used in advertising 17 * or publicity pertaining to distribution of the software without specific, 18 * written prior permission. 19 * 20 * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" 21 * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, 22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR 23 * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 24 * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, 25 * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY 26 * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, 27 * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF 28 * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN 29 * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON 30 * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE 31 * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. 32 * 33 * US Government Users Restricted Rights 34 * Use, duplication, or disclosure by the Government is subject to 35 * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph 36 * (c)(1)(ii) of the Rights in Technical Data and Computer Software 37 * clause at DFARS 252.227-7013 and/or in similar or successor 38 * clauses in the FAR or the DOD or NASA FAR Supplement. 39 * Unpublished-- rights reserved under the copyright laws of the 40 * United States. Contractor/manufacturer is Silicon Graphics, 41 * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. 42 * 43 * OpenGL(TM) is a trademark of Silicon Graphics, Inc. 44 */ 45/* mipmap.c 46 * This program demonstrates using mipmaps for texture maps. 47 * To overtly show the effect of mipmaps, each mipmap reduction 48 * level has a solidly colored, contrasting texture image. 49 * Thus, the quadrilateral which is drawn is drawn with several 50 * different colors. 51 */ 52#include <stdlib.h> 53#include <stdio.h> 54#include <GL/glew.h> 55#include "glut_wrap.h" 56 57#include "readtex.h" 58 59#define TEXTURE_FILE DEMOS_DATA_DIR "girl.rgb" 60 61static GLint BaseLevel = 0, MaxLevel = 9; 62static GLfloat MinLod = -1, MaxLod = 9; 63static GLfloat LodBias = 0.0; 64static GLuint texImage, texColor, texCurrent; 65static GLboolean MagNearestFilter = GL_TRUE; 66static unsigned int MinFilterIndex = 0; 67static int Width = 600, Height = 600; 68 69static const struct 70{ 71 GLint value; 72 const char *name; 73} 74min_filters[] = 75{ 76 {GL_LINEAR_MIPMAP_LINEAR, "LINEAR_MIPMAP_LINEAR"}, 77 {GL_NEAREST_MIPMAP_LINEAR, "NEAREST_MIPMAP_LINEAR"}, 78 {GL_LINEAR_MIPMAP_NEAREST, "LINEAR_MIPMAP_NEAREST"}, 79 {GL_NEAREST_MIPMAP_NEAREST, "NEAREST_MIPMAP_NEAREST"}, 80 {GL_LINEAR, "LINEAR"}, 81 {GL_NEAREST, "NEAREST"}, 82}; 83 84 85static void 86InitValues(void) 87{ 88 BaseLevel = 0; 89 MaxLevel = 9; 90 MinLod = -1; 91 MaxLod = 9; 92 LodBias = 0.0; 93 MagNearestFilter = GL_TRUE; 94 MinFilterIndex = 0; 95} 96 97 98static void 99MakeImage(int level, int width, int height, const GLubyte color[4]) 100{ 101 const int makeStripes = 0; 102 GLubyte img[512 * 512 * 3]; 103 int i, j; 104 for (i = 0; i < height; i++) { 105 for (j = 0; j < width; j++) { 106 int k = (i * width + j) * 3; 107 int p = (i / 8) & makeStripes; 108 if (p == 0) { 109 img[k + 0] = color[0]; 110 img[k + 1] = color[1]; 111 img[k + 2] = color[2]; 112 } 113 else { 114 img[k + 0] = 0; 115 img[k + 1] = 0; 116 img[k + 2] = 0; 117 } 118 } 119 } 120 121 glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, width, height, 0, 122 GL_RGB, GL_UNSIGNED_BYTE, img); 123} 124 125 126static void 127makeImages(int image) 128{ 129#define WIDTH 512 130#define HEIGHT 512 131 if (glutExtensionSupported("GL_SGIS_generate_mipmap") && image) { 132 /* test auto mipmap generation */ 133 GLint width, height, i; 134 GLenum format; 135 GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); 136 if (!image) { 137 printf("Error: could not load texture image %s\n", TEXTURE_FILE); 138 exit(1); 139 } 140 /* resize */ 141 if (width != WIDTH || height != HEIGHT) { 142 GLubyte *newImage = malloc(WIDTH * HEIGHT * 4); 143 gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, 144 WIDTH, HEIGHT, GL_UNSIGNED_BYTE, newImage); 145 free(image); 146 image = newImage; 147 } 148 printf("Using GL_SGIS_generate_mipmap\n"); 149 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 150 glTexImage2D(GL_TEXTURE_2D, 0, format, WIDTH, HEIGHT, 0, 151 format, GL_UNSIGNED_BYTE, image); 152 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); 153 free(image); 154 155 /* make sure mipmap was really generated correctly */ 156 width = WIDTH; 157 height = HEIGHT; 158 for (i = 0; i < 10; i++) { 159 GLint w, h; 160 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); 161 glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); 162 printf("Level %d size: %d x %d\n", i, w, h); 163 width /= 2; 164 height /= 2; 165 } 166 } 167 else { 168 static const GLubyte colors[10][3] = { 169 {128, 128, 128}, 170 {0, 255, 255}, 171 {255, 255, 0}, 172 {255, 0, 255}, 173 {255, 0, 0}, 174 {0, 255, 0}, 175 {0, 0, 255}, 176 {0, 255, 255}, 177 {255, 255, 0}, 178 {255, 255, 255} 179 }; 180 int i, sz = 512; 181 182 for (i = 0; i < 10; i++) { 183 MakeImage(i, sz, sz, colors[i]); 184 printf("Level %d size: %d x %d\n", i, sz, sz); 185 sz /= 2; 186 } 187 } 188} 189 190static void 191myinit(void) 192{ 193 InitValues(); 194 195 glEnable(GL_DEPTH_TEST); 196 glDepthFunc(GL_LESS); 197 glShadeModel(GL_FLAT); 198 199 glTranslatef(0.0, 0.0, -3.6); 200 201 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 202 glGenTextures(1, &texImage); 203 glBindTexture(GL_TEXTURE_2D, texImage); 204 makeImages(1); 205 glGenTextures(1, &texColor); 206 glBindTexture(GL_TEXTURE_2D, texColor); 207 makeImages(0); 208 209 texCurrent = texImage; 210 211 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 212 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 213 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 214 glEnable(GL_TEXTURE_2D); 215} 216 217static void 218print_string(const char *s) 219{ 220 while (*s) { 221 glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 222 s++; 223 } 224} 225 226static void 227print_info(void) 228{ 229 int dy = 17; 230 int x = Width-320, y = Height - dy; 231 char s[100]; 232 233 glDisable(GL_TEXTURE_2D); 234 glColor3f(1, 1, 1); 235 236 glWindowPos2i(x, y); 237 sprintf(s, "MIN_FILTER (f/F): %s", min_filters[MinFilterIndex].name); 238 print_string(s); 239 y -= dy; 240 241 glWindowPos2i(x, y); 242 sprintf(s, " MAG_FILTER (g): %s", MagNearestFilter ? "NEAREST" : "LINEAR"); 243 print_string(s); 244 y -= dy; 245 246 glWindowPos2i(x, y); 247 sprintf(s, "Toggle Image (t):"); 248 print_string(s); 249 y -= dy; 250 251 glWindowPos2i(x, y); 252 sprintf(s, "BASE_LEVEL (b/B): %d", BaseLevel); 253 print_string(s); 254 y -= dy; 255 256 glWindowPos2i(x, y); 257 sprintf(s, " MAX_LEVEL (m/M): %d", MaxLevel); 258 print_string(s); 259 y -= dy; 260 261 glWindowPos2i(x, y); 262 sprintf(s, " MIN_LOD (n/N): %f", MinLod); 263 print_string(s); 264 y -= dy; 265 266 glWindowPos2i(x, y); 267 sprintf(s, " MAX_LOD (x/X): %f", MaxLod); 268 print_string(s); 269 y -= dy; 270 271 glWindowPos2i(x, y); 272 sprintf(s, " LOD_BIAS (l/L): %f", LodBias); 273 print_string(s); 274 y -= dy; 275 276 glWindowPos2i(x, y); 277 sprintf(s, " RESET (space)"); 278 print_string(s); 279 y -= dy; 280 281 282 glEnable(GL_TEXTURE_2D); 283} 284 285 286static void 287display(void) 288{ 289 GLfloat tcm = 1.0; 290 glBindTexture(GL_TEXTURE_2D, texCurrent); 291 292 printf 293 ("BASE_LEVEL=%d MAX_LEVEL=%d MIN_LOD=%.2g MAX_LOD=%.2g Bias=%.2g Filter=%s/%s\n", 294 BaseLevel, MaxLevel, MinLod, MaxLod, LodBias, min_filters[MinFilterIndex].name, 295 MagNearestFilter ? "NEAREST" : "LINEAR"); 296 fflush(stdout); 297 298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, BaseLevel); 299 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, MaxLevel); 300 301 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, MinLod); 302 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, MaxLod); 303 304 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filters[MinFilterIndex].value); 305 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagNearestFilter ? GL_NEAREST : GL_LINEAR); 306 307 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, LodBias); 308 309 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 310 glBegin(GL_QUADS); 311 glTexCoord2f(0.0, 0.0); 312 glVertex3f(-2.0, -1.0, 0.0); 313 glTexCoord2f(0.0, tcm); 314 glVertex3f(-2.0, 1.0, 0.0); 315 glTexCoord2f(tcm * 3000.0, tcm); 316 glVertex3f(3000.0, 1.0, -6000.0); 317 glTexCoord2f(tcm * 3000.0, 0.0); 318 glVertex3f(3000.0, -1.0, -6000.0); 319 glEnd(); 320 321 print_info(); 322 323 glFlush(); 324} 325 326static void 327myReshape(int w, int h) 328{ 329 Width = w; 330 Height = h; 331 glViewport(0, 0, w, h); 332 glMatrixMode(GL_PROJECTION); 333 glLoadIdentity(); 334 gluPerspective(60.0, 1.0 * (GLfloat) w / (GLfloat) h, 1.0, 30000.0); 335 glMatrixMode(GL_MODELVIEW); 336 glLoadIdentity(); 337} 338 339 340static void 341usage(void) 342{ 343 printf("usage:\n"); 344 printf(" b/B decrease/increase GL_TEXTURE_BASE_LEVEL\n"); 345 printf(" m/M decrease/increase GL_TEXTURE_MAX_LEVEL\n"); 346 printf(" n/N decrease/increase GL_TEXTURE_MIN_LOD\n"); 347 printf(" x/X decrease/increase GL_TEXTURE_MAX_LOD\n"); 348 printf(" l/L decrease/increase GL_TEXTURE_LOD_BIAS\n"); 349 printf(" f/F cycle minification filter\n"); 350 printf(" g toggle nearest/linear magnification filter\n"); 351 printf(" t toggle texture color/image\n"); 352 printf(" SPACE reset values\n"); 353 fflush(stdout); 354} 355 356static void 357key(unsigned char k, int x, int y) 358{ 359 (void) x; 360 (void) y; 361 switch (k) { 362 case 'b': 363 BaseLevel--; 364 if (BaseLevel < 0) 365 BaseLevel = 0; 366 break; 367 case 'B': 368 BaseLevel++; 369 if (BaseLevel > 10) 370 BaseLevel = 10; 371 break; 372 case 'm': 373 MaxLevel--; 374 if (MaxLevel < 0) 375 MaxLevel = 0; 376 break; 377 case 'M': 378 MaxLevel++; 379 if (MaxLevel > 10) 380 MaxLevel = 10; 381 break; 382 case 'l': 383 LodBias -= 0.25; 384 break; 385 case 'L': 386 LodBias += 0.25; 387 break; 388 case 'n': 389 MinLod -= 0.25; 390 break; 391 case 'N': 392 MinLod += 0.25; 393 break; 394 case 'x': 395 MaxLod -= 0.25; 396 break; 397 case 'X': 398 MaxLod += 0.25; 399 break; 400 case 'f': 401 if (MinFilterIndex == 0) 402 MinFilterIndex = sizeof(min_filters) / sizeof(*min_filters); 403 MinFilterIndex--; 404 break; 405 case 'F': 406 MinFilterIndex++; 407 if (MinFilterIndex == sizeof(min_filters) / sizeof(*min_filters)) 408 MinFilterIndex = 0; 409 break; 410 case 'g': 411 MagNearestFilter = !MagNearestFilter; 412 break; 413 case 't': 414 if (texCurrent == texColor) 415 texCurrent = texImage; 416 else 417 texCurrent = texColor; 418 break; 419 case ' ': 420 InitValues(); 421 /* fall-through */ 422 case 'u': 423 usage(); 424 break; 425 case 27: /* Escape */ 426 exit(0); 427 break; 428 default: 429 return; 430 } 431 glutPostRedisplay(); 432} 433 434 435int 436main(int argc, char **argv) 437{ 438 glutInit(&argc, argv); 439 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 440 glutInitWindowSize(Width, Height); 441 glutCreateWindow(argv[0]); 442 glewInit(); 443 myinit(); 444 glutReshapeFunc(myReshape); 445 glutDisplayFunc(display); 446 glutKeyboardFunc(key); 447 usage(); 448 glutMainLoop(); 449 return 0; /* ANSI C requires main to return int. */ 450} 451