mesa: new mipmap generation, lod bias demo
Show each of the mipmap levels side-by-side. Press 's' to toggle quad scaling to see mipmap level at actual size.
This commit is contained in:
@@ -51,6 +51,7 @@ SOURCES = \
|
||||
manytex.c \
|
||||
minmag.c \
|
||||
mipmap_limits.c \
|
||||
mipmap_view.c \
|
||||
multipal.c \
|
||||
no_s3tc.c \
|
||||
packedpixels.c \
|
||||
@@ -158,6 +159,14 @@ invert: invert.o readtex.o
|
||||
invert.o: invert.c readtex.h
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
|
||||
|
||||
mipmap_view: mipmap_view.o readtex.o
|
||||
$(CC) $(CFLAGS) mipmap_view.o readtex.o $(LIBS) -o $@
|
||||
|
||||
mipmap_view.o: mipmap_view.c readtex.h
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
|
||||
|
||||
|
||||
|
||||
readtex.o: readtex.c
|
||||
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
|
||||
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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/glut.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include "readtex.h"
|
||||
|
||||
#define TEXTURE_FILE "../images/arch.rgb"
|
||||
|
||||
static int TexWidth = 256, TexHeight = 256;
|
||||
static int WinWidth = 1044, WinHeight = 900;
|
||||
static GLfloat Bias = 0.0;
|
||||
static GLboolean ScaleQuads = GL_FALSE;
|
||||
|
||||
|
||||
static void
|
||||
PrintString(const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
Display(void)
|
||||
{
|
||||
int x, y, bias;
|
||||
char str[100];
|
||||
int texWidth = TexWidth, texHeight = TexHeight;
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, WinWidth, 0, WinHeight, -1, 1);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glColor3f(1,1,1);
|
||||
|
||||
y = WinHeight - 300;
|
||||
x = 4;
|
||||
|
||||
for (bias = -1; bias < 11; bias++) {
|
||||
|
||||
glRasterPos2f(x, y + TexHeight + 5);
|
||||
sprintf(str, "Texture LOD Bias = %d", bias);
|
||||
PrintString(str);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, 0);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
if (ScaleQuads) {
|
||||
if (bias > 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
glViewport(0, 0, width, 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 '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 27:
|
||||
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);
|
||||
|
||||
if (1) {
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
|
||||
printf("Using gluBuildMipmaps()\n");
|
||||
}
|
||||
else {
|
||||
printf("Error: could not load texture image %s\n", TEXTURE_FILE);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* mipmapping required for this extension */
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
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);
|
||||
glutCreateWindow(argv[0]);
|
||||
glutReshapeFunc(Reshape);
|
||||
glutKeyboardFunc(Key);
|
||||
glutDisplayFunc(Display);
|
||||
Init();
|
||||
glutMainLoop();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user