Texture Mapping: Painting 2D Textures onto 3D Surfaces, Study notes of Computer Graphics

The concept of texture mapping, a technique used in computer graphics to apply a 2d texture onto a 3d surface. The basics of texture mapping, including how it works, different innovations like bump mapping and environment mapping, and how to implement texture mapping in opengl. It also provides examples and code snippets.

Typology: Study notes

Pre 2010

Uploaded on 08/16/2009

koofers-user-umt
koofers-user-umt 🇺🇸

8 documents

1 / 12

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Lecture on Texture Mapping
Texture mapping is one of the major innovations in CG in the 1990s. It allows us to add a lot of surface detail
without adding a lot of geometric primitives (lines, vertices, faces). Think of how interesting Caroline’s “loadedDemo”
is with all the texture-mapping. Figure 1 contrasts the two.
1 Reading
As with everything in computer graphics, most of what I know about texture mapping I learned from Angel’s book,
so check that chapter first. Unfortunately, it’s one of his weakest chapters, because it doesn’t do a very good job of
connecting the theory with the OpenGL code. A more practical presentation is a chapter of the Red Book (the Red
OpenGL Programming Guide). You’re encouraged to look at both.
2 Conceptual View
Texture mapping paints a picture onto a polygon. Although the name is texture-mapping, the general approach simply
takes an array of pixels and paints them onto the surface. An array of pixels is just a picture. It might be something
your program computes and uses. More likely, it will be something that you load from a file.
Demos: These all live in the ˜cs307/public_html/demos/texture-mapping/ directory.
USFlag: This actually shows two flags: a checkered flag and a US flag. You can switch between two flags
using the “u” key. This is about the simplest texture-mapping code. Please look at it.
LitUSFlag: The US flag texture-mapped with lighting. You have to turn off the wireframe mode (“w”) and
then turn on texture-mapping (“t”). You can also switch between having the texture interact with lighting and
having a “decal.” This code is fairly ambitious, but it shows what we can do with texture-mapping. Don’t look
at it until you’re ready.
Figure 1: Caroline Geiersbach’s loadedDemo with and without textures
1
pf3
pf4
pf5
pf8
pf9
pfa

Partial preview of the text

Download Texture Mapping: Painting 2D Textures onto 3D Surfaces and more Study notes Computer Graphics in PDF only on Docsity!

Lecture on Texture Mapping

Texture mapping is one of the major innovations in CG in the 1990s. It allows us to add a lot of surface detail without adding a lot of geometric primitives (lines, vertices, faces). Think of how interesting Caroline’s “loadedDemo” is with all the texture-mapping. Figure 1 contrasts the two.

1 Reading

As with everything in computer graphics, most of what I know about texture mapping I learned from Angel’s book, so check that chapter first. Unfortunately, it’s one of his weakest chapters, because it doesn’t do a very good job of connecting the theory with the OpenGL code. A more practical presentation is a chapter of the Red Book (the Red OpenGL Programming Guide). You’re encouraged to look at both.

2 Conceptual View

Texture mapping paints a picture onto a polygon. Although the name is texture -mapping, the general approach simply takes an array of pixels and paints them onto the surface. An array of pixels is just a picture. It might be something your program computes and uses. More likely, it will be something that you load from a file. Demos: These all live in the ˜cs307/public_html/demos/texture-mapping/ directory. USFlag: This actually shows two flags: a checkered flag and a US flag. You can switch between two flags using the “u” key. This is about the simplest texture-mapping code. Please look at it. LitUSFlag: The US flag texture-mapped with lighting. You have to turn off the wireframe mode (“w”) and then turn on texture-mapping (“t”). You can also switch between having the texture interact with lighting and having a “decal.” This code is fairly ambitious, but it shows what we can do with texture-mapping. Don’t look at it until you’re ready.

Figure 1: Caroline Geiersbach’s loadedDemo with and without textures

QuadPPM: TW makes it easy to read a texture from a PPM file and texture-map it onto something. The code for this demo is relatively simple and is worth reading. This demo uses a PPM file of the US flag texture as the default, but you can specify your own on the command line. There’s a directory of image files in

˜cs307/public_html/textures

Teapot: The GLUT teapot defines texture coordinates for each B´ezier patch, so we can texture-map stuff onto it easily. This demo is a variation on QuadPPM, but mapping onto the teapot instead of a unit square. Its code is even simpler than QuadPPM.

Conceptually, to use textures, you must do the following: define a texture (a rectangular array of pixels — texels )

specify a pair of texture coordinates ^ for each vertex of your polygon

The graphics system “paints” the texture onto the polygon.

3 How It Works

Texture mapping is a raster operation, unlike any of the other things we’ve looked at. Nevertheless, we apply textures to 2D surfaces in our 3D model, and the graphics system has to figure out how to modify the pixels during rasterizing (AKA scan conversion ). Since texture-mapping happens as part of the rasterizing process, let’s start there.

3.1 Rasterizing

When the graphics card renders a polygon, it (conceptually)

determines the pixel coordinates of each corner.

determines the edge pixels of the polygon, using a line-drawing program (an imporant one is Bresenham’s algorithm, which we won’t have time to study). determines the color of the edge pixels on a single row (by linear interpolation from the vertex colors)

walks down the row coloring each pixel (by linear interpolation from the two edge pixels).

Note: standard terminology is that the polygon is called a fragment (since it might be a fragment of a B´ezier surface or some such). Thus, the graphics card applies a texture to a fragment. This all happens in either in the framebuffer or an array just like it.

3.2 Texture Mapping

To do texture mapping, the graphics card must

compute a texture coordinate for each pixel during the rasterizing process, using bi-linear interpolation

look up the texture coordinates in the array of texels (either using the nearest or a linear interpolation of the four nearest) Either

- Use the color of the texture as the color of the pixel, or - Combine the color of the texture with the color of the pixel

As we go down the first column of the array, until we get to element [ColLength][0], we get to texture coordinates (0,1). Again, this may seem odd, but it’s true. Unsurprisingly, the last element of the texel array is the corner opposite the first element, so array element [ColLength][RowLength] corresponds to texture coordinates (1,1).

Conventionally, the texture coordinates are called

, just as spatial coordinates are called

. Thus, we can say that

goes along the rows of the texture (along the “fly” of the flag). The

coordinate goes along the columns of the texture (along the “hoist” of the flag). Although you will often use the entire texture, so that all your texture coordinates are 0 or 1, that is not necessary. In fact, because the dimensions of texture arrays are required to be powers of two, the actual image that you want is often only a portion of the whole array. The computed US flag array has that property. The array is 256 pixels wide by 128 pixels high, but the flag itself is 198 pixels wide by 104 pixels high. Thus, the maximum texture coordinates are:

Of course, we also need to ensure that the rectangle we are putting the flag on has the same aspect ratio as the US flag, namely: 1.9. See http://cs.wellesley.edu/˜cs307/flagspec.htm.

3.5 Basic Demos

Please look at the code for the following demos. All of them are in ˜cs307/public_html/demos/ texture-mapping/.

SimplestTextures.cc This is a simple example, using very small ( (')^ ) textures. There are actually two

textures: use “u” to switch.

3.6 Texture Mapping in OpenGL

Conceptually, to actually do texture mapping in OpenGL, you have to do all the following steps.

  1. Create or load a 1D or 2D array of texels. All dimensions must be a power of two! Different kinds of data are possible: RGB values RGBA values Luminance (grayscale) ...

Also, the data in the array can be in different formats (unsigned bytes, short floats, etc.). You must tell OpenGL what it is.

  1. Set various modes. These have default values (see the man pages), so they can be skipped in some cases, but I tend to set them all. I copy/paste the code from some working example of texture-mapping, then change the modes as necessary.
  2. Send the texel data to the graphics card.
  3. Enable texture-mapping
  4. Specify a texture coordinate for each vertex. Sometimes this is done automatically (as for the teapot) or is calculated (as for B´ezier surfaces). We’ll get into B´ezier stuff later.

For coding, that means the following steps. We’ll go through these functions in detail.

Figure 3: Demo of how textures can interact with fragment color: TextureParameters

4 Issues

Here are some issues to face and choices to make:

Aspect Ratio: Your texture is always a rectangle. Even if your polygon is one, too, you’ll have to deal with matching aspect ratios if you want the image to be undistorted. With a plain texture (such as grass or wood) this may not matter, but for pictures it may. Wrapping: What happens when your texture parameters fall outside the [0,1] range? We’ll try this with the tutor.

- You can “wrap” around (essentially removing the integer part and using only the fractional part). This repeats the texture. For real textures, you often want to do this. - You can “clamp” the value at the edge pixel. If your texture has a border of some sort, that can work out well. Filter: What to do when the pixel doesn’t exactly match a texel? You get to specify this for both magnification (pixel smaller than texel) and minification (pixel larger than texel), but in practice, I think they are usually set to the same value. - Use the nearest (Manhattan distance) texel to the center of the pixel. - Use a weighted average of the four texels nearest to the center of the pixel.

We’ll look at the LinearNearest demo to understand this. Note: the functions to set the filters appear not to have adequate defaults: if you don’t set them, you won’t get a texture! density of the texture repetition. Too little and it looks badly “stretched.” Too much can squeeze the texture too much. Look at Grass.cc. Try the three different textures. Use the “r” callback to reveal the vertices that are created. Look at the texture “from above,” by using the “Y” callback.

4.1 More Demos

Please look at the code for the following demos. All of them are in ˜cs307/public_html/demos/ texture-mapping/.

Rainbow.cc This is lovely example of a 1D texture. Use the “R” keyboard callback to turn the rainbow on/off. The illusion is much better if you switch to “immerse” mode. Note that another version of this demo that doesn’t use TW, called RainbowSweet, looks better because the illusion is much better if you’re inside the scene. Original code from Michael Sweet. TextureParameters.cc This demonstrates uses of texture parameters, such as decal vs blending. It gen- erates figure 3. LinearNearest.cc This demonstrates the difference between LINEAR and NEAREST for magnifica- tion/minification. You can see screen shots in figure 4. LitUSFlag.cc This demonstrates how to combine B´ezier surfaces and texture mapping. Lighting, too.

˜/pub/Tutors/texture. An OpenGL tutor I got online. Pretty slick, but I don’t understand everything, so experiment with it.

Figure 4: Both figures are checkerboard textures, stretched over a large number of pixels. Consequently, the texture coordinate values for many pixels fall “between” texel values. In the picture on the left, we use a “linear” interpolation between the texel values. In the picture on the right, we use the “nearest” texel value.

5 Images and File Formats

Images come in dozens of formats, with different kinds of compression techniques and so forth. We will look at the following kinds:

BMP (MS-Windows Bitmap format): this is an uncompressed Windows format. It has a simple format, but the files are very large. Note Flick’s campaign to stamp them out: http://www.wellesley.edu/ Chemistry/Flick/hsobu.html TIFF (Tag Image File Format): an industry standard pixmap file format. File sizes are large, but file format is fairly simple. Some digital cameras produce this. GIF (Graphic Interchange Format): a compressed (loss-less) format limited to 256 colors and encumbered with a patent. Allows index transparency. Viewable by all web browsers. JPG (Joint Photographic Experts Group): a compressed (lossy) format that can handle full RGB color (millions of different colors in an image). Because of the fancy compression algorithm, the file format is complex. No transparency. Viewable by all web browsers. PNG (Portable Network Graphics): an open-source, compressed (loss-less) format that removes some restric- tions of GIF. Supported by all modern browsers. The file format also stores orginal “vector” information. Fireworks uses this format as its native format. (Other formats can be imported or exported.) PPM (Portable Pixmap): an open-source, uncompressed format. The format is:

- P6: two ASCII characters identifying the file type - w, h: two decimal numbers with a space after them giving the width and height of the image - 255: the largest possible value of a color component - a carriage return character (ASCII 13)

5.3 Binding Textures

For additional speed, you can load several textures, associating them to integer identifiers (just like display lists) and then referring to them later. Setup steps: Ask for a bunch of identifier numbers:

glGenTextures( num_wanted , result_array );

Then, for each texture you want, get one of the numbers out of the array and:

glBindTexture(GL_TEXTURE_2D, textureNumber ); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, something ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, something ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, something ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, something ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, something ); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTex2D(...); or twTex2D(...);

Reference step: When you want a texture, just:

glBindTexture(GL_TEXTURE_2D, textureNumber );

As a convenience, you can replace each of the texture steps with

twLoadTexture(textureIDs[ n ], filename );

However, this function uses GL_MODULATE, GL_REPEAT and GL_LINEAR, which may not be what you want. Demos: TextureBinding.cc and USflag-binding.cc. Try spinning either of these. Notice how rela- tively quick they are. This is because the texture is already loaded into memory on the graphics card, so almost nothing needs to be sent down the pipeline to draw the next frame of animation.

5.4 Saving Images

You can also save the contents of the framebuffer as a PPM file. Just hit the “S” key. This is accomplished thanks to an interesting function

void glReadPixels( GLint x, // raster location of first pixel GLint y, GLsizei width, // dimensions of pixel rectangle GLsizei height, GLenum format, // GL_RGB GLenum type, // GL_UNSIGNED_BYTE GLvoid *pixels ); glReadPixels(0,y,width,1,GL_RGB,GL_UNSIGNED_BYTE, (GLvoid *) pixels);

The file is saved as saved_image01.ppm in the current directory. If you hit “s” again, you get saved_ image02.ppm and so forth. In honor of family and friends weekend, convert these to PNG and put them on your web page! Or email them! Note that PPM files are big. In many of our examples, the framebuffer is 500 by 500. The file size is therefore

len(P6500 500 255)

% ppmtojpeg -v saved-frame01.ppm > saved-frame01.jpg ppmtojpeg: Input file has format P6. It has 500 rows of 500 columns of pixels with max sample value of 255. ppmtojpeg: No scan script is being used % ls -l saved-frame01.* -rw-rw-r-- 1 cs307 cs307 25290 Nov 7 00:06 saved-frame01.jpg -rw-r--r-- 1 cs307 cs307 750014 Oct 31 14:33 saved-frame01.ppm

The JPG is a bit smaller! YMMV. Since you have a finite filespace quota, manage your space carefully.

6 Texture Mapping using Modulate

When you texture-map using GL_MODULATE, you have to think about the color of the underlying surface. In partic- ular, if you’re using material and lighting, you have to use material and textures. Caroline’s texture tutor can help: ˜cs307/public_html/demos/textureTutor

7 Texture Mapping Onto Odd Shapes

7.1 Triangles

There are actually two choices here. If you want a triangular region of your texture, there’s no problem, just use the texture coordinates as usual. If you want to squeeze one edge of the texture down to a point, it would seem that all you have to do is use the same texture coordinates for both vertices, but that yields odd results. Instead, you can use linear B´ezier surfaces to make a triangular region. Demo: TexturemapTriangles.cc

7.2 Cylinders

If mapping onto a curved surface, we usually represent the surface with parametric equations and map texture param- eters to curve parameters. For example, a cylinder:

With the easy mapping:



Demo: CylinderFlag.cc This shows how to put a 2D texture onto a non-planar figure. It uses the US flag, since it’s easy to see the orientation of the texture. Essentially, we have to build the figure ourselves out of vertices, so that we can define texture coordinates for each vertex. There are two ways to put a flag onto a cylinder: with the stripes going around the cylinder or along its length. This demo does either; the “l” keyboard callback switches the orientation. Understanding this code is not easy, but it really only requires understanding polar/cylindrical coordinates. The texture coordinates are relatively straightforward.

7.3 Bezier Surfaces

We’ve already seen this, and we got another dose of it when we looked at mapping onto triangles, but let’s look at it again. To map onto a surface with material and lighting, consider: Demo: LitUSFlag.cc