diff options
Diffstat (limited to 'progs/tests/mipmap_view.c')
-rw-r--r-- | progs/tests/mipmap_view.c | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/progs/tests/mipmap_view.c b/progs/tests/mipmap_view.c new file mode 100644 index 0000000000..808d348699 --- /dev/null +++ b/progs/tests/mipmap_view.c @@ -0,0 +1,435 @@ +/* + * Test mipmap generation and lod bias. + * + * Brian Paul + * 17 March 2008 + */ + + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include <GL/glew.h> +#include <GL/glut.h> +#include <GL/glext.h> + +#include "readtex.h" + +#define TEXTURE_FILE "../images/arch.rgb" + +#define LEVELS 8 +#define SIZE (1<<LEVELS) +static int TexWidth = SIZE, TexHeight = SIZE; +static int WinWidth = 1044, WinHeight = 900; +static GLfloat Bias = 0.0; +static GLboolean ScaleQuads = GL_FALSE; +static GLboolean Linear = GL_FALSE; +static GLint Win = 0; +static GLint RenderTextureLevel = 0; +static GLuint TexObj; + + + +static void +CheckError(int line) +{ + GLenum err = glGetError(); + if (err) { + printf("GL Error 0x%x at line %d\n", (int) err, line); + } +} + + + +static void +PrintString(const char *s) +{ + while (*s) { + glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s); + s++; + } +} + + + + +static void +MipGenTexture( void ) +{ + /* test auto mipmap generation */ + GLint width, height, i; + GLenum format; + GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format); + if (!image) { + printf("Error: could not load texture image %s\n", TEXTURE_FILE); + exit(1); + } + /* resize to TexWidth x TexHeight */ + if (width != TexWidth || height != TexHeight) { + GLubyte *newImage = malloc(TexWidth * TexHeight * 4); + + fprintf(stderr, "rescale %d %d to %d %d\n", width, height, + TexWidth, TexHeight); + fflush(stderr); + + gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image, + TexWidth, TexHeight, GL_UNSIGNED_BYTE, newImage); + free(image); + image = newImage; + } + printf("Using GL_SGIS_generate_mipmap\n"); + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, format, TexWidth, TexHeight, 0, + format, GL_UNSIGNED_BYTE, image); + free(image); + + /* make sure mipmap was really generated correctly */ + width = TexWidth; + height = TexHeight; + for (i = 0; i < 9; i++) { + GLint w, h; + glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h); + printf("Level %d size: %d x %d\n", i, w, h); + assert(w == width); + assert(h == height); + width /= 2; + height /= 2; + } + + + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); +} + + + +static void +ResetTextureLevel( int i ) +{ + GLubyte tex2d[SIZE*SIZE][4]; + + { + GLint Width = TexWidth / (1 << i); + GLint Height = TexHeight / (1 << i); + GLint s, t; + + for (s = 0; s < Width; s++) { + for (t = 0; t < Height; t++) { + tex2d[t*Width+s][0] = ((s / 16) % 2) ? 0 : 255; + tex2d[t*Width+s][1] = ((t / 16) % 2) ? 0 : 255; + tex2d[t*Width+s][2] = 128; + tex2d[t*Width+s][3] = 255; + } + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGB, Width, Height, 0, + GL_RGBA, GL_UNSIGNED_BYTE, tex2d); + } +} + + +static void +ResetTexture( void ) +{ +#if 0 + /* This doesn't work so well as the arch texture is 512x512. + */ + LoadRGBMipmaps(TEXTURE_FILE, GL_RGB); +#else + { + int i; + + for (i = 0; i <= LEVELS; i++) + { + ResetTextureLevel(i); + } + } +#endif +} + + + + + + + +static void +RenderTexture( void ) +{ + GLenum status; + GLuint MyFB; + + fprintf(stderr, "RenderTextureLevel %d\n", RenderTextureLevel); + fflush(stderr); + + /* gen framebuffer id, delete it, do some assertions, just for testing */ + glGenFramebuffersEXT(1, &MyFB); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, MyFB); + assert(glIsFramebufferEXT(MyFB)); + + CheckError(__LINE__); + + /* Render color to texture */ + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, TexObj, + RenderTextureLevel); + + + + CheckError(__LINE__); + + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -15.0); + + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + printf("Framebuffer incomplete!!!\n"); + } + + glViewport(0, 0, + TexWidth / (1 << RenderTextureLevel), + TexHeight / (1 << RenderTextureLevel)); + + glClearColor(0.5, 0.5, 1.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + CheckError(__LINE__); + + glBegin(GL_POLYGON); + glColor3f(1, 0, 0); + glVertex2f(-1, -1); + glColor3f(0, 1, 0); + glVertex2f(1, -1); + glColor3f(0, 0, 1); + glVertex2f(0, 1); + glEnd(); + + + /* Bind normal framebuffer */ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + CheckError(__LINE__); + + glDeleteFramebuffersEXT(1, &MyFB); + CheckError(__LINE__); + + glClearColor(0, 0, 0, 0); +} + +static void +Display(void) +{ + int x, y, bias; + char str[100]; + int texWidth = TexWidth, texHeight = TexHeight; + + glViewport(0, 0, WinHeight, WinHeight); + + glClear(GL_COLOR_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, WinWidth, 0, WinHeight, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glColor3f(1,1,1); + + if (Linear) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + y = WinHeight - 300; + x = 4; + + for (bias = -1; bias < 11; bias++) { + + if (ScaleQuads) { + if (bias > 0) { + if (texWidth == 1 && texHeight == 1) + break; + texWidth = TexWidth >> bias; + texHeight = TexHeight >> bias; + if (texWidth < 1) + texWidth = 1; + if (texHeight < 1) + texHeight = 1; + } + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.0); + } + else { + glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, bias); + } + + glRasterPos2f(x, y + TexHeight + 5); + if (ScaleQuads) + sprintf(str, "Texture Level %d: %d x %d", + (bias < 0 ? 0 : bias), + texWidth, texHeight); + else + sprintf(str, "Texture LOD Bias = %d", bias); + PrintString(str); + + glPushMatrix(); + glTranslatef(x, y, 0); + + glEnable(GL_TEXTURE_2D); + + glBegin(GL_POLYGON); + glTexCoord2f(0, 0); glVertex2f(0, 0); + glTexCoord2f(1, 0); glVertex2f(texWidth, 0); + glTexCoord2f(1, 1); glVertex2f(texWidth, texHeight); + glTexCoord2f(0, 1); glVertex2f(0, texHeight); + glEnd(); + + glPopMatrix(); + + glDisable(GL_TEXTURE_2D); + + x += TexWidth + 4; + if (x >= WinWidth) { + x = 4; + y -= 300; + } + } + + glutSwapBuffers(); +} + + +static void +Reshape(int width, int height) +{ + WinWidth = width; + WinHeight = height; +} + + +static void +Key(unsigned char key, int x, int y) +{ + (void) x; + (void) y; + switch (key) { + case 'b': + Bias -= 10; + break; + case 'B': + Bias += 10; + break; + case 'l': + Linear = !Linear; + break; + case 'v': + RenderTextureLevel++; + break; + case 'V': + RenderTextureLevel--; + break; + case 'r': + RenderTexture(); + break; + case 'X': + ResetTexture(); + break; + case 'x': + ResetTextureLevel(RenderTextureLevel); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Bias = 100.0 * (key - '0'); + break; + case 's': + ScaleQuads = !ScaleQuads; + break; + case ' ': + MipGenTexture(); + Bias = 0; + Linear = 0; + RenderTextureLevel = 0; + ScaleQuads = 0; + break; + + case 27: + glutDestroyWindow(Win); + exit(0); + break; + } + glutPostRedisplay(); +} + + +static void +Init(void) +{ + GLfloat maxBias; + + if (!glutExtensionSupported("GL_EXT_texture_lod_bias")) { + printf("Sorry, GL_EXT_texture_lod_bias not supported by this renderer.\n"); + exit(1); + } + + if (!glutExtensionSupported("GL_SGIS_generate_mipmap")) { + printf("Sorry, GL_SGIS_generate_mipmap not supported by this renderer.\n"); + exit(1); + } + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glGenTextures(1, &TexObj); + glBindTexture(GL_TEXTURE_2D, TexObj); + + if (1) + MipGenTexture(); + else + ResetTexture(); + + /* mipmapping required for this extension */ + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &maxBias); + + printf("GL_RENDERER: %s\n", (char*) glGetString(GL_RENDERER)); + printf("LOD bias range: [%g, %g]\n", -maxBias, maxBias); + + printf("Press 's' to toggle quad scaling\n"); +} + + +int +main(int argc, char *argv[]) +{ + glutInit(&argc, argv); + glutInitWindowPosition(0, 0); + glutInitWindowSize(WinWidth, WinHeight); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); + Win = glutCreateWindow(argv[0]); + glewInit(); + glutReshapeFunc(Reshape); + glutKeyboardFunc(Key); + glutDisplayFunc(Display); + Init(); + glutMainLoop(); + return 0; +} |