<OpenGL> Texture Mapping
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了<OpenGL> Texture Mapping相关的知识,希望对你有一定的参考价值。
I. Steps in Texture Mapping
To use texture mapping, you perform these steps.
1. Create a texture object and specify a texture for that object.
2. Indicate how the texture is to be applied to each pixel.
3. Enable texture mapping.
4. Draw the scene, supplying both texture and geometric coordinates.
ps. Keep in mind that texture mapping works only in RGBA mode. Texture mapping results in color-index mode are undefined.
Simple example:
1 #include <stdlib.h> 2 #include <stdio.h> 3 #include <GL/gl.h> 4 #include <GL/glu.h> 5 #include <GL/glut.h> 6 7 /* Create checkerboard texture */ 8 #define checkImageWidth 64 9 #define checkImageHeight 64 10 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; 11 12 static GLuint texName; 13 14 /* Generate a texture */ 15 void makeCheckImage(void) 16 { 17 int i, j, c; 18 19 for (i = 0; i < checkImageHeight; i++) { 20 for (j = 0; j < checkImageWidth; j++) { 21 c = ((((i&0x8)==0)^((j&0x8))==0))*255; 22 checkImage[i][j][0] = (GLubyte) c; 23 checkImage[i][j][1] = (GLubyte) c; 24 checkImage[i][j][2] = (GLubyte) c; 25 checkImage[i][j][3] = (GLubyte) 255; 26 } 27 } 28 } 29 30 void init(void) 31 { 32 glClearColor (0.0, 0.0, 0.0, 0.0); 33 glShadeModel(GL_FLAT); 34 glEnable(GL_DEPTH_TEST); 35 36 makeCheckImage(); 37 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 38 39 // Generate texture buffer 40 glGenTextures(1, &texName); 41 42 // (*must be put here) Bind the texture ID "texName" to current texture being modified & applied 43 glBindTexture(GL_TEXTURE_2D, texName); 44 45 // specify texture parameters 46 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // Wrapping by horizontal direction 47 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Wrapping by vertical direction 48 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // Aliasing method when magnify the image 49 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Aliasing method when minify the image 50 51 // Generate the texture from pixel buffer "checkImage" 52 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, 53 checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 54 checkImage); 55 } 56 57 void display(void) 58 { 59 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 60 61 // Enable texture 62 glEnable(GL_TEXTURE_2D); 63 64 // How the texture mix up with the material and lighting 65 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 66 67 // Apply the texture by referring to its ID "texName" 68 glBindTexture(GL_TEXTURE_2D, texName); 69 70 // Use glTexCoord2f(x, y) to specify the border which defines the part of texture that are being used 71 glBegin(GL_QUADS); 72 glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); 73 glTexCoord2f(0.0, 1.0); glVertex3f(-2.0, 1.0, 0.0); 74 glTexCoord2f(1.0, 1.0); glVertex3f(0.0, 1.0, 0.0); 75 glTexCoord2f(1.0, 0.0); glVertex3f(0.0, -1.0, 0.0); 76 77 glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0); 78 glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 0.0); 79 glTexCoord2f(1.0, 1.0); glVertex3f(2.41421, 1.0, -1.41421); 80 glTexCoord2f(1.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); 81 82 glEnd(); 83 glFlush(); 84 85 // Disable texture mapping 86 glDisable(GL_TEXTURE_2D); 87 } 88 89 void reshape(int w, int h) 90 { 91 glViewport(0, 0, (GLsizei) w, (GLsizei) h); 92 glMatrixMode(GL_PROJECTION); 93 glLoadIdentity(); 94 gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 30.0); 95 glMatrixMode(GL_MODELVIEW); 96 glLoadIdentity(); 97 glTranslatef(0.0, 0.0, -3.6); 98 } 99 100 void keyboard (unsigned char key, int x, int y) 101 { 102 switch (key) { 103 case 27: 104 exit(0); 105 break; 106 default: 107 break; 108 } 109 } 110 111 int main(int argc, char** argv) 112 { 113 glutInit(&argc, argv); 114 glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); 115 glutInitWindowSize(250, 250); 116 glutInitWindowPosition(100, 100); 117 glutCreateWindow(argv[0]); 118 init(); 119 glutDisplayFunc(display); 120 glutReshapeFunc(reshape); 121 glutKeyboardFunc(keyboard); 122 glutMainLoop(); 123 return 0; 124 }
II. Specifying the texture
The command glTexImage2D() defines a two-dimensional texture. It takes several arguments, which are described briefly here and in more detail in the subsections that follow.
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
III. Filtering
Texture maps are square or rectangular, but after being mapped to a polygon or surface and transformed into screen coordinates, the individual texels of a texture rarely correspond to individual pixels of the final screen image. Depending on the transformations used and the texture mapping applied, a single pixel on the screen can correspond to anything from a tiny portion of a texel (magnification) to a large collection of texels (minification). In either case, it‘s unclear exactly which texel values should be used and how they should be averaged or interpolated. Consequently, OpenGL allows you to specify any of several filtering options to determine these calculations. The options provide different trade-offs between speed and image quality. Also, you can specify independently the filtering methods for magnification and minification.
The following lines are examples of how to use glTexParameter*() to specify the magnification and minification filtering methods:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
The first argument to glTexParameter*() is either GL_TEXTURE_2D or GL_TEXTURE_1D, depending on whether you‘re working with two- or one-dimensional textures. For the purposes of this discussion, the second argument is either GL_TEXTURE_MAG_FILTER or GL_TEXTURE_MIN_FILTER to indicate whether you‘re specifying the filtering method for magnification or minification. The third argument specifies the filtering method; Table 9-1 lists the possible values.
If you choose GL_NEAREST, the texel with coordinates nearest the center of the pixel is used for both magnification and minification. This can result in aliasing artifacts (sometimes severe). If you choose GL_LINEAR, a weighted linear average of the 2 ´ 2 array of texels that lie nearest to the center of the pixel is used, again for both magnification and minification. When the texture coordinates are near the edge of the texture map, the nearest 2 ´ 2 array of texels might include some that are outside the texture map. In these cases, the texel values used depend on whether GL_REPEAT or GL_CLAMP is in effect and whether you‘ve assigned a border for the texture.
IV. Texture Objects
Texture objects are an important new feature in release 1.1 of OpenGL. A texture object stores texture data and makes it readily available. You can now control many textures and go back to textures that have been previously loaded into your texture resources. Using texture objects is usually the fastest way to apply textures, resulting in big performance gains, because it is almost always much faster to bind (reuse) an existing texture object than it is to reload a texture image using glTexImage*D().
Also, some implementations support a limited working set of high-performance textures. You can use texture objects to load your most often used textures into this limited area.
To use texture objects for your texture data, take these steps.
1. Generate texture names.
2. Initially bind (create) texture objects to texture data, including the image arrays and texture properties.
3. Bind and rebind texture objects, making their data currently available for rendering textured models.
i. Naming A Texture Object
Any nonzero unsigned integer may be used as a texture name. To avoid accidentally reusing names, consistently useglGenTextures() to provide unused texture names.
void glGenTextures(GLsizei n, GLuint *textureNames); /* Returns n currently unused names for texture objects in the array textureNames. The names returned in textureNames do not have to be a contiguous set of integers. The names in textureNames are marked as used, but they acquire texture state and dimensionality (1D or 2D) only when they are first bound. Zero is a reserved texture name and is never returned as a texture name by glGenTextures(). */
glIsTexture() determines if a texture name is actually in use. If a texture name was returned by glGenTextures() but has not yet been bound (calling glBindTexture() with the name at least once), then glIsTexture() returns GL_FALSE.
ii. Creating and Using Texture Objects
The same routine, glBindTexture(), both creates and uses texture objects. When a texture name is initially bound (used withglBindTexture()), a new texture object is created with default values for the texture image and texture properties. Subsequent calls to glTexImage*(), glTexSubImage*(), glCopyTexImage*(), glCopyTexSubImage*(), glTexParameter*(), andglPrioritizeTextures() store data in the texture object. The texture object may contain a texture image and associated mipmap images (if any), including associated data such as width, height, border width, internal format, resolution of components, and texture properties. Saved texture properties include minification and magnification filters, wrapping modes, border color, and texture priority.
When a texture object is subsequently bound once again, its data becomes the current texture state. (The state of the previously bound texture is replaced.)
void glBindTexture(GLenum target, GLuint textureName); /* glBindTexture() does three things. When using textureName of an unsigned integer other than zero for the first time, a new texture object is created and assigned that name. When binding to a previously created texture object, that texture object becomes active. When binding to a textureName value of zero, OpenGL stops using texture objects and returns to the unnamed default texture. When a texture object is initially bound (that is, created), it assumes the dimensionality of target, which is either GL_TEXTURE_1D or GL_TEXTURE_2D. Immediately upon its initial binding, the state of texture object is equivalent to the state of the default GL_TEXTURE_1D or GL_TEXTURE_2D (depending upon its dimensionality) at the initialization of OpenGL. In this initial state, texture properties such as minification and magnification filters, wrapping modes, border color, and texture priority are set to their default values. */
iii. Cleaning Up Texture Objects
As you bind and unbind texture objects, their data still sits around somewhere among your texture resources. If texture resources are limited, deleting textures may be one way to free up resources.
void glDeleteTextures(GLsizei n, const GLuint *textureNames); /* Deletes n texture objects, named by elements in the array textureNames. The freed texture names may now be reused (for example, by glGenTextures()) If a texture that is currently bound is deleted, the binding reverts to the default texture, as if glBindTexture() were called with zero for the value of textureName. Attempts to delete nonexistent texture names or the texture name of zero are ignored without generating an error. */
V. Texture Functions
In all the examples so far in this chapter, the values in the texture map have been used directly as colors to be painted on the surface being rendered. You can also use the values in the texture map to modulate the color that the surface would be rendered without texturing, or to blend the color in the texture map with the original color of the surface. You choose one of four texturing functions by supplying the appropriate arguments to glTexEnv*().
void glTexEnv{if}(GLenum target, GLenum pname, TYPEparam); void glTexEnv{if}v(GLenum target, GLenum pname, TYPE *param); /* Sets the current texturing function. target must be GL_TEXTURE_ENV. If pname is GL_TEXTURE_ENV_MODE, param can be GL_DECAL, GL_REPLACE, GL_MODULATE, or GL_BLEND, to specify how texture values are to be combined with the color values of the fragment being processed. If pname is GL_TEXTURE_ENV_COLOR, param is an array of four floating-point values representing R, G, B, and A components. These values are used only if the GL_BLEND texture function has been specified as well. */
VI. Assigning Texture Coordinates
As you draw your texture-mapped scene, you must provide both object coordinates and texture coordinates for each vertex. After transformation, the object coordinates determine where on the screen that particular vertex is rendered. The texture coordinates determine which texel in the texture map is assigned to that vertex. In exactly the same way that colors are interpolated between two vertices of shaded polygons and lines, texture coordinates are also interpolated between vertices. (Remember that textures are rectangular arrays of data.)
Texture coordinates can comprise one, two, three, or four coordinates. They‘re usually referred to as the s, t, r, and qcoordinates to distinguish them from object coordinates (x, y, z, and w) and from evaluator coordinates (u and v). For one-dimensional textures, you use the s coordinate; for two-dimensional textures, you use s and t. In Release 1.1, the r coordinate is ignored. (Some implementations have 3D texture mapping as an extension, and that extension uses the r coordinate.) The command to specify texture coordinates, glTexCoord*(), is similar to glVertex*(), glColor*(), and glNormal*() - it comes in similar variations and is used the same way between glBegin() andglEnd() pairs. Usually, texture-coordinate values range from 0 to 1;
void glTexCoord{1234}{sifd}(TYPEcoords); void glTexCoord{1234}{sifd}v(TYPE *coords); /* Sets the current texture coordinates (s, t, r, q). Subsequent calls to glVertex*() result in those vertices being assigned the current texture coordinates. With glTexCoord1*(), the s coordinate is set to the specified value, t and r are set to 0, and q is set to 1. Using glTexCoord2*() allows you to specify s and t; r and q are set to 0 and 1, respectively. With glTexCoord3*(), q is set to 1 and the other coordinates are set as specified. You can specify all coordinates with glTexCoord4*(). Use the appropriate suffix (s, i, f, or d) and the corresponding value for TYPE (GLshort, GLint, GLfloat, or GLdouble) to specify the coordinates‘ data type. You can supply the coordinates individually, or you can use the vector version of the command to supply them in a single array. Texture coordinates are multiplied by the 4 ´ 4 texture matrix before any texture mapping occurs. (See "The Texture Matrix Stack.") Note that integer texture coordinates are interpreted directly rather than being mapped to the range [-1,1] as normal coordinates are. */
VII. Repeating and Clamping Textures
You can assign texture coordinates outside the range [0,1] and have them either clamp or repeat in the texture map. With repeating textures, if you have a large plane with texture coordinates running from 0.0 to 10.0 in both directions, for example, you‘ll get 100 copies of the texture tiled together on the screen. During repeating, the integer part of texture coordinates is ignored, and copies of the texture map tile the surface. For most applications where the texture is to be repeated, the texels at the top of the texture should match those at the bottom, and similarly for the left and right edges.
To see the effects of wrapping, you must have texture coordinates that venture beyond [0.0, 1.0]. Start with Example 9-1, and modify the texture coordinates for the squares by mapping the texture coordinates from 0.0 to 3.0 as follows:
1 glBegin(GL_QUADS); 2 glTexCoord2f(0.0, 0.0); glVertex3f(-2.0, -1.0, 0.0); 3 glTexCoord2f(0.0, 3.0); glVertex3f(-2.0, 1.0, 0.0); 4 glTexCoord2f(3.0, 3.0); glVertex3f(0.0, 1.0, 0.0); 5 glTexCoord2f(3.0, 0.0); glVertex3f(0.0, -1.0, 0.0); 6 7 glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 0.0); 8 glTexCoord2f(0.0, 3.0); glVertex3f(1.0, 1.0, 0.0); 9 glTexCoord2f(3.0, 3.0); glVertex3f(2.41421, 1.0, -1.41421); 10 glTexCoord2f(3.0, 0.0); glVertex3f(2.41421, -1.0, -1.41421); glEnd();
With GL_REPEAT wrapping, the result is as shown in Figure 9-7.
Figure 9-7 : Repeating a Texture
In this case, the texture is repeated in both the s and t directions, since the following calls are made to glTexParameter*():
1 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 2 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
If GL_CLAMP is used instead of GL_REPEAT for each direction, you see something similar to Figure 9-8.
Figure 9-8 : Clamping a Texture
You can also clamp in one direction and repeat in the other, as shown in Figure 9-9.
Figure 9-9 : Repeating and Clamping a Texture
You‘ve now seen all the possible arguments for glTexParameter*(), which is summarized here.
void glTexParameter{if}(GLenum target, GLenum pname, TYPE param); void glTexParameter{if}v(GLenum target, GLenum pname, TYPE *param); /* Sets various parameters that control how a texture is treated as it‘s applied to a fragment or stored in a texture object. The target parameter is either GL_TEXTURE_2D or GL_TEXTURE_1D to indicate a two- or one-dimensional texture. The possible values for pname and param are shown in Table 9-4. You can use the vector version of the command to supply an array of values for GL_TEXTURE_BORDER_COLOR, or you can supply individual values for other parameters using the nonvector version. If these values are supplied as integers, they‘re converted to floating-point according to Table 4-1; they‘re also clamped to the range [0,1]. */
Reference: https://www.opengl.org/sdk/docs/man2/xhtml/glLightModel.xml
以上是关于<OpenGL> Texture Mapping的主要内容,如果未能解决你的问题,请参考以下文章
openGL之API学习(二零零)GL_TEXTURE_GEN_S GL_TEXTURE_GEN_T GL_TEXTURE_GEN_R GL_TEXTURE_GEN_Q