6.3. DebuggingSeveral things could cause texture mapping not to work properly, and there are numerous ways to identify the source of the problem. 6.3.1. OpenGL Error CodeCheck for OpenGL errors after creating texture objects and after rendering each frame. When developing a new application, check for OpenGL errors early in development. This helps isolate the cause of the problem, because new errors are usually generated by new code. appendix D, "Troubleshooting and Debugging," describes the OGLDIF_CHECK_ERROR CPP macro, defined and used in the example code, which calls glGetError() without affecting application performance. 6.3.2. Texture StateNew OpenGL programmers frequently confuse texture unit state and texture object state. Some of this confusion stems from OpenGL's history, because many texture state parameters existed in OpenGL version 1.0 before the addition of texture objects in version 1.1 and multitexturing in version 1.3. For a complete enumeration of texture object and texture unit state, refer to Tables 6.15 and 6.16 in The OpenGL Graphics System. The following sections summarize the most essential state items. 6.3.2.1. Texture Object StateOpenGL stores state parameters set by the glTexParameter*() commands in texture objects. Binding a texture object activates these parameter values. For a complete list of state parameters, see "glTexParameter" in OpenGL® Reference Manual. The most common parameters are listed here:
6.3.2.2. Texture Unit StateOpenGL maintains most other texture state parameters on a per-texture-unit basis to allow each texture unit to operate on texture objects in a unique manner. A few of the most common parameters are listed here:
6.3.3. Texture CompletenessIf a texture object isn't complete, OpenGL behaves as though the associated active texture unit is disabled. As a result, OpenGL renders your geometry without texture mapping. A complete texture object meets the following conditions:
6.3.3.1. Mipmap CompleteIf your application specified or changed the base texture image while GL_GENERATE_MIPMAP was set to GL_TRUE, or if you used gluBuild2DMipmaps() to specify your texture images, OpenGL has already created a mipmap-complete texture object. If you're creating a mipmapped texture object manually, however, with individual calls to glTexImage2D() for each mipmap level, see Section 3.8.10, "Texture Completeness," of The OpenGL Graphics System for the list of mipmap-complete criteria. The texture-object state parameter GL_TEXTURE_MIN_FILTER defaults to GL_NEAREST_MIPMAP_LINEAR, which is a mipmap filter mode. Beginners commonly fail to change this parameter from its default value and specify a single texture map without a complete mipmap pyramid. In this case, the texture object isn't mipmap complete. To fix this problem, set the minification filter to a nonmipmapped filter: glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); If the OpenGL version is 1.4 or later, you can also enable mipmap generation before calling glTexImage2D(), so that OpenGL will create a complete mipmap pyramid for you when you specify the base texture image: glTexParameteri( GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE ); 6.3.3.2. Cube CompleteYour application must create cube map texture objects with six consistent images. A cube-complete texture object must meet the following criteria:
6.3.4. Missing TexturesThere are many ways to misconfigure OpenGL accidentally, resulting in missing textures. The following paragraphs describe a few of the most common mistakes. Make sure that you've enabled texture mapping. If the texture object bound to the active texture unit is 2D, call glEnable( GL_TEXTURE_2D ), and if the texture object is a cube map, call glEnable( GL_TEXTURE_CUBE_MAP ). If you're using multitexturing, make sure you enable each texture unit in use (conversely, be sure to disable texture units that are not in use). When you enable texture mapping for a certain mode, disable other texture mapping modes. If the bound texture object contains a 2D texture image, for example, your code should ensure that GL_TEXTURE_1D, GL_TEXTURE_3D, and GL_TEXTURE_CUBE_MAP are all disabled. This is more than just good practice; the texture enumerants specify precedence. If GL_TEXTURE_CUBE_MAP is enabled, for example, but the bound texture object is 2D, OpenGL behaves as though texture mapping is completely disabled. Unfortunately, there's no way to query OpenGL as to whether a texture object meets the texture-completeness criteria described in the section "Texture Completeness" earlier in this chapter. If you've accidentally bound a texture object that isn't texture complete, however, OpenGL will behave as though the active texture unit has texture mapping disabled. Make sure that you set the appropriate texture environment for each enabled texture unit. Suppose that your application set GL_TEXTURE_ENV_MODE to GL_MODULATE for GL_TEXTURE0 and to GL_REPLACE for GL_TEXTURE1. In this case, the texture bound to GL_TEXTURE1 replaces the result from GL_TEXTURE0, and the final rendered image appears as though texture unit GL_TEXTURE0 is disabled. 6.3.5. Inverted TexturesThe OpenGL window-coordinate system follows the Cartesian model of having its origin at the bottom-left corner, with positive x to the right and positive y up. Chapter 3, "Transformation and Viewing," briefly covers how this system clashes with most modern window systems, which have their origin in the top-left corner. This inconsistency causes headaches for most new OpenGL programmersuntil they learn how to address this problem. Similarly, the OpenGL pixel pipeline expects the bottom row of pixels first and the top row last. Many image files, however, store their pixel data inverted from the OpenGL system, with the top row of pixels first and the bottom last. As a result, whether using glDrawPixels() or texture mapping, the pixel data appears upside down in the final rendered image. OpenGL programmers generally use one of two methods to address this issue:
OpenGL implementations typically optimize for an identity texture matrix by eliminating the texture-coordinate transformation. So unless your application already uses the texture matrix, the second option incurs a per-vertex texture-coordinate transformation that could affect application performance. |