diff options
Diffstat (limited to 'tests/glean/ttexcube.cpp')
-rw-r--r-- | tests/glean/ttexcube.cpp | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/tests/glean/ttexcube.cpp b/tests/glean/ttexcube.cpp new file mode 100644 index 00000000..1d8ac29f --- /dev/null +++ b/tests/glean/ttexcube.cpp @@ -0,0 +1,426 @@ +// BEGIN_COPYRIGHT -*- glean -*- +// +// Copyright (C) 1999 Allen Akin All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// END_COPYRIGHT + + +// ttexcube.cpp: Test the GL_ARB_texture_cube_map extension +// Author: Brian Paul (brianp@valinux.com) March 2001 +// +// Test procedure: +// We build a 6-sided texture cube map in which each side is a simple 2x2 +// checkboard pattern with known colors. Then we do three sets of tests. +// Each test draws a single quadrilateral. The tests are: +// +// 1. Directly specify texture coordinates. By changing the texture coords +// we can sample specific regions of the cube map. Check the rendered +// quad colors for correctness. +// 2. Use GL_NORMAL_MAP_ARB texgen mode with specific normal vectors to +// sample specific regions of the cube map. Check for correctness. +// 3. Test GL_REFLECTION_MAP_ARB texgen mode by specifying a quad with +// fixed vertices and normals but rotating the texture coordinate +// matrix to select each side of the cube map. Check that the rendered +// quad's four colors match the cube face. +// + +#include "ttexcube.h" +#include <stdio.h> +#include <cmath> + +namespace GLEAN { + + +#define VP_SIZE 20 + +static const char *faceName[6] = { + "POSITIVE_X", + "NEGATIVE_X", + "POSITIVE_Y", + "NEGATIVE_Y", + "POSITIVE_Z", + "NEGATIVE_Z" +}; + + +// +// Test if two colors are close enough to be considered the same +// +bool +TexCubeTest::TestColor(const GLfloat c1[3], const GLfloat c2[3]) { + if (fabs(c1[0] - c2[0]) <= mTolerance[0] && + fabs(c1[1] - c2[1]) <= mTolerance[1] && + fabs(c1[2] - c2[2]) <= mTolerance[2]) + return true; + else + return false; +} + + +// +// Define a 2x2 checkerboard texture image using the given four colors. +// +void +TexCubeTest::BuildTexImage(GLenum target, const GLfloat color[4][3]) { + const GLint w = 8, h = 8; + GLfloat texImage[8][8][4]; + for (int i = 0; i < h; i++) { + const int ibit = (i >= (h / 2)); + for (int j = 0; j < w; j++) { + const int jbit = (j >= (w / 2)); + const int c = ibit * 2 + jbit; + texImage[i][j][0] = color[c][0]; + texImage[i][j][1] = color[c][1]; + texImage[i][j][2] = color[c][2]; + texImage[i][j][3] = 1.0; + } + } + glTexImage2D(target, 0, GL_RGB, w, h, 0, GL_RGBA, GL_FLOAT, texImage); +} + + +// +// Draw a polygon either with texcoords or normal vectors and check that +// we hit the correct quadrant of each of the six cube faces. +// Return: true = pass, false = fail +// +bool +TexCubeTest::TestNormalMap(bool texCoordMode, const char *modeName) { + + // We use the coordinates both directly as texture coordinates + // and as normal vectors for testing NORMAL_MAP_ARB texgen mode). + static const GLfloat coords[6][4][3] = { + // +X + { + { 1.0, 0.5, 0.5 }, + { 1.0, 0.5, -0.5 }, + { 1.0, -0.5, 0.5 }, + { 1.0, -0.5, -0.5 }, + }, + // -X + { + { -1.0, 0.5, -0.5 }, + { -1.0, 0.5, 0.5 }, + { -1.0, -0.5, -0.5 }, + { -1.0, -0.5, 0.5 }, + }, + // +Y + { + { -0.5, 1.0, -0.5 }, + { 0.5, 1.0, -0.5 }, + { -0.5, 1.0, 0.5 }, + { 0.5, 1.0, 0.5 }, + }, + // -Y + { + { -0.5, -1.0, 0.5 }, + { 0.5, -1.0, 0.5 }, + { -0.5, -1.0, -0.5 }, + { 0.5, -1.0, -0.5 }, + }, + // +Z + { + { -0.5, 0.5, 1.0 }, + { 0.5, 0.5, 1.0 }, + { -0.5, -0.5, 1.0 }, + { 0.5, -0.5, 1.0 }, + }, + // -Z + { + { 0.5, 0.5, -1.0 }, + { -0.5, 0.5, -1.0 }, + { 0.5, -0.5, -1.0 }, + { -0.5, -0.5, -1.0 }, + } + }; + + // normal vectors to hit the four colors of each cube face when + + for (int face = 0; face < 6; face++) { + for (int quadrant = 0; quadrant < 4; quadrant++) { + + // draw the test quad + if (texCoordMode) + glTexCoord3fv(coords[face][quadrant]); + else + glNormal3fv(coords[face][quadrant]); + glColor3f(0, 1, 0); + glBegin(GL_POLYGON); + glVertex2f(-1, -1); + glVertex2f( 1, -1); + glVertex2f( 1, 1); + glVertex2f(-1, 1); + glEnd(); + + // check the color + GLfloat result[3]; + glReadPixels(1, 1, 1, 1, GL_RGB, GL_FLOAT, result); + + if (!TestColor(mColors[face][quadrant], result)) { + env->log << name + << ": FAIL: mode='" + << modeName + << "' face=" + << faceName[face] + << " quadrant=" + << quadrant + << " expected=(" + << mColors[face][quadrant][0] << ", " + << mColors[face][quadrant][1] << ", " + << mColors[face][quadrant][2] + << ") measured=(" + << result[0] << ", " + << result[1] << ", " + << result[2] + << ")\n"; + return false; + } + } + } + return true; +} + + +// +// Test GL_REFLECTION_MAP_ARB texgen mode. +// Return: true = pass, false = fail +// +bool +TexCubeTest::TestReflectionMap(const char *modeName) { + +// These are the glReadPixels coords we'll use for pixel testing +#define X0 ((int) (VP_SIZE * 0.25)) +#define X1 ((int) (VP_SIZE * 0.75)) +#define Y0 ((int) (VP_SIZE * 0.25)) +#define Y1 ((int) (VP_SIZE * 0.75)) + + // We'll rotate the texture coordinates to map each cube face + // onto a screen-aligned quad. + static const GLfloat rotation[6][4] = { + { -90, 0, 1, 0 }, // +X + { 90, 0, 1, 0 }, // -X + { 90, 1, 0, 0 }, // +Y + { -90, 1, 0, 0 }, // -Y + { 180, 1, 0, 0 }, // -Z + { 0, 1, 0, 0 } // +Z + }; + + // For each face we'll test the four quadrants to be sure test + // if the expected color is where it should be. + // These are the glReadPixels coordinates at which we should + // find the colors in the mColors[6][4] array. + static const GLint readPos[6][4][2] = { + // +X + { + { X1, Y1 }, { X0, Y1 }, { X1, Y0 }, { X0, Y0 } + }, + // -X + { + { X1, Y1 }, { X0, Y1 }, { X1, Y0 }, { X0, Y0 } + }, + // +Y + { + { X0, Y0 }, { X1, Y0 }, { X0, Y1 }, { X1, Y1 } + }, + // -Y + { + { X0, Y0 }, { X1, Y0 }, { X0, Y1 }, { X1, Y1 } + }, + // +Z + { + { X0, Y0 }, { X1, Y0 }, { X0, Y1 }, { X1, Y1 } + }, + // -Z + { + { X1, Y1 }, { X0, Y1 }, { X1, Y0 }, { X0, Y0 } + } + }; + + for (int face = 0; face < 6; face++) { + + // Draw the test quad. + // It'll be textured with one face of the cube map texture. + glMatrixMode(GL_TEXTURE); + glPushMatrix(); + glRotatef(rotation[face][0], rotation[face][1], + rotation[face][2], rotation[face][3]); + glNormal3f(0, 0, 1); + glColor3f(0, 1, 0); + glBegin(GL_POLYGON); + glVertex3f(-1, -1, 1); + glVertex3f( 1, -1, 1); + glVertex3f( 1, 1, 1); + glVertex3f(-1, 1, 1); + glEnd(); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + // Verify the colors + for (int quadrant = 0; quadrant < 4; quadrant++) { + + GLfloat result[3]; + glReadPixels(readPos[face][quadrant][0], + readPos[face][quadrant][1], + 1, 1, GL_RGB, GL_FLOAT, result); + + if (!TestColor(mColors[face][quadrant], result)) { + env->log << name + << ": FAIL: mode='" + << modeName + << "' face=" + << faceName[face] + << " quadrant=" + << quadrant + << " expected=(" + << mColors[face][quadrant][0] << ", " + << mColors[face][quadrant][1] << ", " + << mColors[face][quadrant][2] + << ") measured=(" + << result[0] << ", " + << result[1] << ", " + << result[2] + << ")\n"; + return false; + } + } + } + return true; +} + + +void +TexCubeTest::runOne(BasicResult& r, Window& w) { + + (void) w; + + // each of six faces needs four test colors + for (int i = 0; i < 6 * 4; i++) { + GLint r = i % 3; + GLint g = (i / 3) % 3; + GLint b = (i / 9) % 3; + mColors[i / 4][i % 4][0] = r * 0.5; + mColors[i / 4][i % 4][1] = g * 0.5; + mColors[i / 4][i % 4][2] = b * 0.5; + //printf("mColors[%d][%d] = %g %g %g\n", i/4, i%4, + // mColors[i/4][i%4][0], + // mColors[i/4][i%4][1], + // mColors[i/4][i%4][2]); + } + + glDrawBuffer(GL_FRONT); + glReadBuffer(GL_FRONT); + + BuildTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, mColors[0]); + BuildTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, mColors[1]); + BuildTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, mColors[2]); + BuildTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, mColors[3]); + BuildTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, mColors[4]); + BuildTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, mColors[5]); + + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glEnable(GL_TEXTURE_CUBE_MAP_ARB); + + // compute RGB error tolerance + { + GLint rBits, gBits, bBits; + GLint rTexBits, gTexBits, bTexBits; + glGetIntegerv(GL_RED_BITS, &rBits); + glGetIntegerv(GL_GREEN_BITS, &gBits); + glGetIntegerv(GL_BLUE_BITS, &bBits); + glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + 0, GL_TEXTURE_RED_SIZE, &rTexBits); + glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + 0, GL_TEXTURE_GREEN_SIZE, &gTexBits); + glGetTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + 0, GL_TEXTURE_BLUE_SIZE, &bTexBits); + // find smaller of frame buffer and texture bits + rBits = (rBits < rTexBits) ? rBits : rTexBits; + gBits = (gBits < gTexBits) ? gBits : gTexBits; + bBits = (bBits < bTexBits) ? bBits : bTexBits; + mTolerance[0] = 2.0 / (1 << rBits); + mTolerance[1] = 2.0 / (1 << gBits); + mTolerance[2] = 2.0 / (1 << bBits); + } + + glViewport(0, 0, VP_SIZE, VP_SIZE); + + bool passed = true; + + if (passed) { + // Test directly specifying texture coords + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + passed = TestNormalMap(true, + "Direct specification of texture coordinates"); + } + + if (passed) { + // Test GL_NORMAL_MAP_ARB mode + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + passed = TestNormalMap(false, "GL_NORMAL_MAP_ARB texgen"); + } + + if (passed) { + // Test GL_REFLECTION_MAP_ARB mode + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); + glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB); + glEnable(GL_TEXTURE_GEN_S); + glEnable(GL_TEXTURE_GEN_T); + glEnable(GL_TEXTURE_GEN_R); + glEnable(GL_NORMALIZE); + passed = TestReflectionMap("GL_REFLECTION_MAP_ARB texgen"); + } + + r.pass = passed; +} // TexCubeTest::runOne + + +void +TexCubeTest::logOne(BasicResult& r) { + logPassFail(r); + logConcise(r); +} // TexCubeTest::logOne + + +/////////////////////////////////////////////////////////////////////////////// +// The test object itself: +/////////////////////////////////////////////////////////////////////////////// +TexCubeTest texCubeTest("texCube", "window, rgb", + + "GL_ARB_texture_cube_map verification test.\n"); + + +} // namespace GLEAN |