mipmap_view.c revision 32001f49
132001f49Smrg/* 232001f49Smrg * Test mipmap generation and lod bias. 332001f49Smrg * 432001f49Smrg * Brian Paul 532001f49Smrg * 17 March 2008 632001f49Smrg */ 732001f49Smrg 832001f49Smrg 932001f49Smrg#include <assert.h> 1032001f49Smrg#include <stdlib.h> 1132001f49Smrg#include <stdio.h> 1232001f49Smrg#include <math.h> 1332001f49Smrg#include <GL/glew.h> 1432001f49Smrg#include "glut_wrap.h" 1532001f49Smrg 1632001f49Smrg#include "readtex.h" 1732001f49Smrg 1832001f49Smrg#define TEXTURE_FILE DEMOS_DATA_DIR "arch.rgb" 1932001f49Smrg 2032001f49Smrg#define LEVELS 8 2132001f49Smrg#define SIZE (1<<LEVELS) 2232001f49Smrgstatic int TexWidth = SIZE, TexHeight = SIZE; 2332001f49Smrgstatic int WinWidth = 1044, WinHeight = 900; 2432001f49Smrgstatic GLfloat Bias = 0.0; 2532001f49Smrgstatic GLboolean ScaleQuads = GL_FALSE; 2632001f49Smrgstatic GLboolean Linear = GL_FALSE; 2732001f49Smrgstatic GLint Win = 0; 2832001f49Smrgstatic GLint RenderTextureLevel = 0; 2932001f49Smrgstatic GLuint TexObj; 3032001f49Smrg 3132001f49Smrg 3232001f49Smrg 3332001f49Smrgstatic void 3432001f49SmrgCheckError(int line) 3532001f49Smrg{ 3632001f49Smrg GLenum err = glGetError(); 3732001f49Smrg if (err) { 3832001f49Smrg printf("GL Error 0x%x at line %d\n", (int) err, line); 3932001f49Smrg } 4032001f49Smrg} 4132001f49Smrg 4232001f49Smrg 4332001f49Smrg 4432001f49Smrgstatic void 4532001f49SmrgPrintString(const char *s) 4632001f49Smrg{ 4732001f49Smrg while (*s) { 4832001f49Smrg glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); 4932001f49Smrg s++; 5032001f49Smrg } 5132001f49Smrg} 5232001f49Smrg 5332001f49Smrg 5432001f49Smrg 5532001f49Smrg 5632001f49Smrgstatic void 5732001f49SmrgMipGenTexture( void ) 5832001f49Smrg{ 5932001f49Smrg /* test auto mipmap generation */ 6032001f49Smrg GLint width, height, i; 6132001f49Smrg GLenum format; 6232001f49Smrg GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); 6332001f49Smrg if (!image) { 6432001f49Smrg printf("Error: could not load texture image %s\n", TEXTURE_FILE); 6532001f49Smrg exit(1); 6632001f49Smrg } 6732001f49Smrg /* resize to TexWidth x TexHeight */ 6832001f49Smrg if (width != TexWidth || height != TexHeight) { 6932001f49Smrg GLubyte *newImage = malloc(TexWidth * TexHeight * 4); 7032001f49Smrg 7132001f49Smrg fprintf(stderr, "rescale %d %d to %d %d\n", width, height, 7232001f49Smrg TexWidth, TexHeight); 7332001f49Smrg fflush(stderr); 7432001f49Smrg 7532001f49Smrg gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, 7632001f49Smrg TexWidth, TexHeight, GL_UNSIGNED_BYTE, newImage); 7732001f49Smrg free(image); 7832001f49Smrg image = newImage; 7932001f49Smrg } 8032001f49Smrg printf("Using GL_SGIS_generate_mipmap\n"); 8132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); 8232001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, format, TexWidth, TexHeight, 0, 8332001f49Smrg format, GL_UNSIGNED_BYTE, image); 8432001f49Smrg free(image); 8532001f49Smrg 8632001f49Smrg /* make sure mipmap was really generated correctly */ 8732001f49Smrg width = TexWidth; 8832001f49Smrg height = TexHeight; 8932001f49Smrg for (i = 0; i < 9; i++) { 9032001f49Smrg GLint w, h; 9132001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); 9232001f49Smrg glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); 9332001f49Smrg printf("Level %d size: %d x %d\n", i, w, h); 9432001f49Smrg assert(w == width); 9532001f49Smrg assert(h == height); 9632001f49Smrg width /= 2; 9732001f49Smrg height /= 2; 9832001f49Smrg } 9932001f49Smrg 10032001f49Smrg 10132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); 10232001f49Smrg} 10332001f49Smrg 10432001f49Smrg 10532001f49Smrg 10632001f49Smrgstatic void 10732001f49SmrgResetTextureLevel( int i ) 10832001f49Smrg{ 10932001f49Smrg GLubyte tex2d[SIZE*SIZE][4]; 11032001f49Smrg 11132001f49Smrg { 11232001f49Smrg GLint Width = TexWidth / (1 << i); 11332001f49Smrg GLint Height = TexHeight / (1 << i); 11432001f49Smrg GLint s, t; 11532001f49Smrg 11632001f49Smrg for (s = 0; s < Width; s++) { 11732001f49Smrg for (t = 0; t < Height; t++) { 11832001f49Smrg tex2d[t*Width+s][0] = ((s / 16) % 2) ? 0 : 255; 11932001f49Smrg tex2d[t*Width+s][1] = ((t / 16) % 2) ? 0 : 255; 12032001f49Smrg tex2d[t*Width+s][2] = 128; 12132001f49Smrg tex2d[t*Width+s][3] = 255; 12232001f49Smrg } 12332001f49Smrg } 12432001f49Smrg 12532001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 12632001f49Smrg 12732001f49Smrg glTexImage2D(GL_TEXTURE_2D, i, GL_RGB, Width, Height, 0, 12832001f49Smrg GL_RGBA, GL_UNSIGNED_BYTE, tex2d); 12932001f49Smrg } 13032001f49Smrg} 13132001f49Smrg 13232001f49Smrg 13332001f49Smrgstatic void 13432001f49SmrgResetTexture( void ) 13532001f49Smrg{ 13632001f49Smrg#if 0 13732001f49Smrg /* This doesn't work so well as the arch texture is 512x512. 13832001f49Smrg */ 13932001f49Smrg LoadRGBMipmaps(TEXTURE_FILE, GL_RGB); 14032001f49Smrg#else 14132001f49Smrg { 14232001f49Smrg int i; 14332001f49Smrg 14432001f49Smrg for (i = 0; i <= LEVELS; i++) 14532001f49Smrg { 14632001f49Smrg ResetTextureLevel(i); 14732001f49Smrg } 14832001f49Smrg } 14932001f49Smrg#endif 15032001f49Smrg} 15132001f49Smrg 15232001f49Smrg 15332001f49Smrg 15432001f49Smrg 15532001f49Smrg 15632001f49Smrg 15732001f49Smrg 15832001f49Smrgstatic void 15932001f49SmrgRenderTexture( void ) 16032001f49Smrg{ 16132001f49Smrg GLenum status; 16232001f49Smrg GLuint MyFB; 16332001f49Smrg 16432001f49Smrg fprintf(stderr, "RenderTextureLevel %d\n", RenderTextureLevel); 16532001f49Smrg fflush(stderr); 16632001f49Smrg 16732001f49Smrg /* gen framebuffer id, delete it, do some assertions, just for testing */ 16832001f49Smrg glGenFramebuffersEXT(1, &MyFB); 16932001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); 17032001f49Smrg assert(glIsFramebufferEXT(MyFB)); 17132001f49Smrg 17232001f49Smrg CheckError(__LINE__); 17332001f49Smrg 17432001f49Smrg /* Render color to texture */ 17532001f49Smrg glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 17632001f49Smrg GL_COLOR_ATTACHMENT0_EXT, 17732001f49Smrg GL_TEXTURE_2D, TexObj, 17832001f49Smrg RenderTextureLevel); 17932001f49Smrg 18032001f49Smrg 18132001f49Smrg 18232001f49Smrg CheckError(__LINE__); 18332001f49Smrg 18432001f49Smrg 18532001f49Smrg glMatrixMode(GL_PROJECTION); 18632001f49Smrg glLoadIdentity(); 18732001f49Smrg glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); 18832001f49Smrg glMatrixMode(GL_MODELVIEW); 18932001f49Smrg glLoadIdentity(); 19032001f49Smrg glTranslatef(0.0, 0.0, -15.0); 19132001f49Smrg 19232001f49Smrg status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 19332001f49Smrg if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 19432001f49Smrg printf("Framebuffer incomplete!!!\n"); 19532001f49Smrg } 19632001f49Smrg 19732001f49Smrg glViewport(0, 0, 19832001f49Smrg TexWidth / (1 << RenderTextureLevel), 19932001f49Smrg TexHeight / (1 << RenderTextureLevel)); 20032001f49Smrg 20132001f49Smrg glClearColor(0.5, 0.5, 1.0, 0.0); 20232001f49Smrg glClear(GL_COLOR_BUFFER_BIT); 20332001f49Smrg 20432001f49Smrg CheckError(__LINE__); 20532001f49Smrg 20632001f49Smrg glBegin(GL_POLYGON); 20732001f49Smrg glColor3f(1, 0, 0); 20832001f49Smrg glVertex2f(-1, -1); 20932001f49Smrg glColor3f(0, 1, 0); 21032001f49Smrg glVertex2f(1, -1); 21132001f49Smrg glColor3f(0, 0, 1); 21232001f49Smrg glVertex2f(0, 1); 21332001f49Smrg glEnd(); 21432001f49Smrg 21532001f49Smrg 21632001f49Smrg /* Bind normal framebuffer */ 21732001f49Smrg glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); 21832001f49Smrg CheckError(__LINE__); 21932001f49Smrg 22032001f49Smrg glDeleteFramebuffersEXT(1, &MyFB); 22132001f49Smrg CheckError(__LINE__); 22232001f49Smrg 22332001f49Smrg glClearColor(0, 0, 0, 0); 22432001f49Smrg} 22532001f49Smrg 22632001f49Smrgstatic void 22732001f49SmrgDisplay(void) 22832001f49Smrg{ 22932001f49Smrg int x, y, bias; 23032001f49Smrg char str[100]; 23132001f49Smrg int texWidth = TexWidth, texHeight = TexHeight; 23232001f49Smrg 23332001f49Smrg glViewport(0, 0, WinHeight, WinHeight); 23432001f49Smrg 23532001f49Smrg glClear(GL_COLOR_BUFFER_BIT); 23632001f49Smrg 23732001f49Smrg glMatrixMode(GL_PROJECTION); 23832001f49Smrg glLoadIdentity(); 23932001f49Smrg glOrtho(0, WinWidth, 0, WinHeight, -1, 1); 24032001f49Smrg glMatrixMode(GL_MODELVIEW); 24132001f49Smrg glLoadIdentity(); 24232001f49Smrg 24332001f49Smrg glColor3f(1,1,1); 24432001f49Smrg 24532001f49Smrg if (Linear) { 24632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 24732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 24832001f49Smrg } 24932001f49Smrg else { 25032001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); 25132001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 25232001f49Smrg } 25332001f49Smrg 25432001f49Smrg y = WinHeight - 300; 25532001f49Smrg x = 4; 25632001f49Smrg 25732001f49Smrg for (bias = -1; bias < 11; bias++) { 25832001f49Smrg 25932001f49Smrg if (ScaleQuads) { 26032001f49Smrg if (bias > 0) { 26132001f49Smrg if (texWidth == 1 && texHeight == 1) 26232001f49Smrg break; 26332001f49Smrg texWidth = TexWidth >> bias; 26432001f49Smrg texHeight = TexHeight >> bias; 26532001f49Smrg if (texWidth < 1) 26632001f49Smrg texWidth = 1; 26732001f49Smrg if (texHeight < 1) 26832001f49Smrg texHeight = 1; 26932001f49Smrg } 27032001f49Smrg glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.0); 27132001f49Smrg } 27232001f49Smrg else { 27332001f49Smrg glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias); 27432001f49Smrg } 27532001f49Smrg 27632001f49Smrg glRasterPos2f(x, y + TexHeight + 5); 27732001f49Smrg if (ScaleQuads) 27832001f49Smrg sprintf(str, "Texture Level %d: %d x %d", 27932001f49Smrg (bias < 0 ? 0 : bias), 28032001f49Smrg texWidth, texHeight); 28132001f49Smrg else 28232001f49Smrg sprintf(str, "Texture LOD Bias = %d", bias); 28332001f49Smrg PrintString(str); 28432001f49Smrg 28532001f49Smrg glPushMatrix(); 28632001f49Smrg glTranslatef(x, y, 0); 28732001f49Smrg 28832001f49Smrg glEnable(GL_TEXTURE_2D); 28932001f49Smrg 29032001f49Smrg glBegin(GL_POLYGON); 29132001f49Smrg glTexCoord2f(0, 0); glVertex2f(0, 0); 29232001f49Smrg glTexCoord2f(1, 0); glVertex2f(texWidth, 0); 29332001f49Smrg glTexCoord2f(1, 1); glVertex2f(texWidth, texHeight); 29432001f49Smrg glTexCoord2f(0, 1); glVertex2f(0, texHeight); 29532001f49Smrg glEnd(); 29632001f49Smrg 29732001f49Smrg glPopMatrix(); 29832001f49Smrg 29932001f49Smrg glDisable(GL_TEXTURE_2D); 30032001f49Smrg 30132001f49Smrg x += TexWidth + 4; 30232001f49Smrg if (x >= WinWidth) { 30332001f49Smrg x = 4; 30432001f49Smrg y -= 300; 30532001f49Smrg } 30632001f49Smrg } 30732001f49Smrg 30832001f49Smrg glutSwapBuffers(); 30932001f49Smrg} 31032001f49Smrg 31132001f49Smrg 31232001f49Smrgstatic void 31332001f49SmrgReshape(int width, int height) 31432001f49Smrg{ 31532001f49Smrg WinWidth = width; 31632001f49Smrg WinHeight = height; 31732001f49Smrg} 31832001f49Smrg 31932001f49Smrg 32032001f49Smrgstatic void 32132001f49SmrgKey(unsigned char key, int x, int y) 32232001f49Smrg{ 32332001f49Smrg (void) x; 32432001f49Smrg (void) y; 32532001f49Smrg switch (key) { 32632001f49Smrg case 'b': 32732001f49Smrg Bias -= 10; 32832001f49Smrg break; 32932001f49Smrg case 'B': 33032001f49Smrg Bias += 10; 33132001f49Smrg break; 33232001f49Smrg case 'l': 33332001f49Smrg Linear = !Linear; 33432001f49Smrg break; 33532001f49Smrg case 'v': 33632001f49Smrg RenderTextureLevel++; 33732001f49Smrg break; 33832001f49Smrg case 'V': 33932001f49Smrg RenderTextureLevel--; 34032001f49Smrg break; 34132001f49Smrg case 'r': 34232001f49Smrg RenderTexture(); 34332001f49Smrg break; 34432001f49Smrg case 'X': 34532001f49Smrg ResetTexture(); 34632001f49Smrg break; 34732001f49Smrg case 'x': 34832001f49Smrg ResetTextureLevel(RenderTextureLevel); 34932001f49Smrg break; 35032001f49Smrg case '0': 35132001f49Smrg case '1': 35232001f49Smrg case '2': 35332001f49Smrg case '3': 35432001f49Smrg case '4': 35532001f49Smrg case '5': 35632001f49Smrg case '6': 35732001f49Smrg case '7': 35832001f49Smrg case '8': 35932001f49Smrg case '9': 36032001f49Smrg Bias = 100.0 * (key - '0'); 36132001f49Smrg break; 36232001f49Smrg case 's': 36332001f49Smrg ScaleQuads = !ScaleQuads; 36432001f49Smrg break; 36532001f49Smrg case ' ': 36632001f49Smrg MipGenTexture(); 36732001f49Smrg Bias = 0; 36832001f49Smrg Linear = 0; 36932001f49Smrg RenderTextureLevel = 0; 37032001f49Smrg ScaleQuads = 0; 37132001f49Smrg break; 37232001f49Smrg 37332001f49Smrg case 27: 37432001f49Smrg glutDestroyWindow(Win); 37532001f49Smrg exit(0); 37632001f49Smrg break; 37732001f49Smrg } 37832001f49Smrg glutPostRedisplay(); 37932001f49Smrg} 38032001f49Smrg 38132001f49Smrg 38232001f49Smrgstatic void 38332001f49SmrgInit(void) 38432001f49Smrg{ 38532001f49Smrg GLfloat maxBias; 38632001f49Smrg 38732001f49Smrg if (!glutExtensionSupported("GL_EXT_texture_lod_bias")) { 38832001f49Smrg printf("Sorry, GL_EXT_texture_lod_bias not supported by this renderer.\n"); 38932001f49Smrg exit(1); 39032001f49Smrg } 39132001f49Smrg 39232001f49Smrg if (!glutExtensionSupported("GL_SGIS_generate_mipmap")) { 39332001f49Smrg printf("Sorry, GL_SGIS_generate_mipmap not supported by this renderer.\n"); 39432001f49Smrg exit(1); 39532001f49Smrg } 39632001f49Smrg 39732001f49Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 39832001f49Smrg 39932001f49Smrg glGenTextures(1, &TexObj); 40032001f49Smrg glBindTexture(GL_TEXTURE_2D, TexObj); 40132001f49Smrg 40232001f49Smrg if (1) 40332001f49Smrg MipGenTexture(); 40432001f49Smrg else 40532001f49Smrg ResetTexture(); 40632001f49Smrg 40732001f49Smrg /* mipmapping required for this extension */ 40832001f49Smrg glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 40932001f49Smrg 41032001f49Smrg glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &maxBias); 41132001f49Smrg 41232001f49Smrg printf("GL_RENDERER: %s\n", (char*) glGetString(GL_RENDERER)); 41332001f49Smrg printf("LOD bias range: [%g, %g]\n", -maxBias, maxBias); 41432001f49Smrg 41532001f49Smrg printf("Press 's' to toggle quad scaling\n"); 41632001f49Smrg} 41732001f49Smrg 41832001f49Smrg 41932001f49Smrgint 42032001f49Smrgmain(int argc, char *argv[]) 42132001f49Smrg{ 42232001f49Smrg glutInit(&argc, argv); 42332001f49Smrg glutInitWindowPosition(0, 0); 42432001f49Smrg glutInitWindowSize(WinWidth, WinHeight); 42532001f49Smrg glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 42632001f49Smrg Win = glutCreateWindow(argv[0]); 42732001f49Smrg glewInit(); 42832001f49Smrg glutReshapeFunc(Reshape); 42932001f49Smrg glutKeyboardFunc(Key); 43032001f49Smrg glutDisplayFunc(Display); 43132001f49Smrg Init(); 43232001f49Smrg glutMainLoop(); 43332001f49Smrg return 0; 43432001f49Smrg} 435