Texturing






Texturing

Applying textures in OpenGL involves the following steps:

Enable texturing
glEnable(GL_TEXTURE_2D)
 
Define a texture
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
             0, GL_RGB, GL_UNSIGNED_BYTE, imageData)
 
Assign texture coordinates
glTexCoord2f(0,0)
glVertex2f(-1.0, -1.0)
glTexCoord2f(1,0)
glVertex2f(1.0, -1.0)





Texture Objects

Defining a texture transfers the image data to the graphics card

Texture objects let you do this once, and then use the texture again later by referring to its ID (its "name").

textureID1 = glGenTextures(1)

glBindTexture(GL_TEXTURE_2D, textureID1)
glTexImage2D(...)
glBindTexture(GL_TEXTURE_2D, 0)

...
glBindTexture(GL_TEXTURE_2D, textureID1)
# Draw textured object





glTexImage2D

glTexImage2D(target, level, internalFormat, width,
             height, border, format, type, pixels)

target - GL_TEXTURE_2D
level - used in mipmapping; set to 0
internalFormat - usually the same as format; can be used for optimization
width & height - size of the image, in pixels
border - normally 0; set to 1 when image data includes a border
format - GL_RGB for RGB images, or GL_LUMINANCE for greyscale (there are other formats as well)
type - data type of the pixel data. GL_UNSIGNED_BYTE is standard for 8-bit-per-channel images.
pixels - the actual array of image data. Use the tostring() function with PIL images.

Note: Generally, width & height must be powers of 2 - i.e., 2, 4, 8, 16, 32, 64, 128, 256, 512, etc. (some times other sizes work, but not always)






Texture Coordinates

Objects need texture coordinates to define how a texture is applied

Texture coordinates form a coordinate system on the texture image, ranging from 0 to 1 in each direction

They are referred to as S and T
(to distinguish them from X & Y geometric coordinates)






Texture Coordinates

One texture coordinate should be assigned for each vertex

This defines what part of the texture should be used at that point

When a polygon is filled in, the vertices' texture coordinates are interpolated across its surface, to find the texture data for each pixel






Texture Coordinates

A texture does not have to be evenly applied to a polygon.

The image can appear distorted, either as a result of the geometry or the texture coordinates used.






Texture Tiling

Texture coordinates outside the range 0 - 1 can be used to tile a texture






Texture Tiling

Tiling is controlled by the WRAP texture parameter:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                   GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                   GL_REPEAT)

for no tiling:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
                   GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
                   GL_CLAMP)





Textured Mesh

When applying a texture across a mesh, or collection of polygons, vertices that correspond to the same point should have the same texcoord.

Example: mesh.py




Texture Environment

Textures provide color information, but so does glColor or lighting.

The texture environment controls how these colors interact.

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, mode)

A "GL_REPLACE" environment uses just the texture color, and ignores everything else.
    Color = Ct

A "GL_MODULATE" environment combines the texture and other color, multiplying them together.
    Color = Ct * Cf

Example: texenv.py






Filtering

Applying a texture involves sampling - for each pixel drawn on the screen, OpenGL must compute a color from the texture image.

Texels (texture pixels) rarely match up exactly 1-to-1 with the pixels on the screen .

Filtering modes select what to do when texels are larger than screen pixels (magnification), or when texels are smaller than screen pixels (minification).

    





Filtering

glTexParameteri(GL_TEXTURE_2D, filter, mode)

If filter is GL_TEX_MAG_FILTER, mode can be

If filter is GL_TEX_MIN_FILTER, mode can be

Example: texfilter.py






Mipmapping

Mipmapping uses versions of the texture at smaller & smaller sizes image, to effectively pre-compute the average of many texels.

As a texture gets more and more minified, many texels will correspond to a single screen pixel, and using a "nearest" or "linear" filter will not compute an accurate result. The texture will appear to flicker as the object moves.


A mipmapped texture avoids the flickering problem when minified. As a result, it can look a bit fuzzier.






Mipmapping

gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB,
                  width, height, GL_RGB,
                  GL_UNSIGNED_BYTE, pixels)

Use gluBuild2DMipmaps in place of glTexImage2D.
It will automatically generate all the smaller versions of the texture.


Example: mipmap.py






Texture from Web

Python's urllib or urllib2 can be used to fetch web data.

e.g. textures or sounds

    try:
        webdata = urllib2.urlopen(url).read()
    except:
        return None
    webdataAsFile = StringIO.StringIO(webdata)
    tex = Texture2D(webdataAsFile)

Example: texURL.py









Alpha






Alpha



alpha
1.0fully opaque
0.5half transparent
0.0fully transparent





Blending

Most common method:

R = A1 * R1 + (1-A1) * R2
G = A1 * G1 + (1-A1) * G2
B = A1 * B1 + (1-A1) * B2


e.g. if alpha is 0.25:          
R = 0.25 * R1 + 0.75 * R2
G = 0.25 * G1 + 0.75 * G2
B = 0.25 * B1 + 0.75 * B2





Blending

Many different formulas for blending colors can be used

Formula is defined by glBlendFunc() function


R = A1 * R1 + (1-A1) * R2
G = A1 * G1 + (1-A1) * G2
B = A1 * B1 + (1-A1) * B2

is defined by:

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)





Blending

Enable blending    glEnable(GL_BLEND)
 
Set the blending function    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 
Assign alpha < 1    glColor4f(1, 0, 0, 0.5)

BlendFunc is applied to pixels as they are drawn - blending incoming color with color in the frame buffer

Example: alpha.py






Smooth-shaded Alpha

Alpha is treated like any other color component


If alpha differs at each vertex, it will be smoothly interpolated.
Can give objects soft edges.

Examples: smoothAlpha.py     alphawheel.py






Time-varying Alpha

Changing alpha over time can make an object a fade in or out

Example: fade.py






Texture Alpha

Use 4 channel texture image

Can be used to "cut out" a texture image - creates complex shapes with simple geometry

RGB Alpha
        

Example: texalpha.py






addalpha

addalpha.py can combine an RGB color image with a greyscale alpha image into a single file, for use as a texture

Output file should be TIFF, for 4-channel support

         





Chroma Keying

Used in film & video to composite live actors with other imagery (video or digital)

e.g. TV weatherman, Star Wars virtual sets

Can be done digitally by finding a background color, and setting alpha to 0 for those pixels

Example code: chromakey.py






Other Blend Functions

General blending formula is:

R = SourceFactor * Rs + DestinationFactor * Rd
G = SourceFactor * Gs + DestinationFactor * Gd
B = SourceFactor * Bs + DestinationFactor * Bd

(Rs, Gs, Bs) is the source color (object being drawn)
(Rd, Gd, Bd) is the destination color (color already in the framebuffer)

SourceFactor and DestinationFactor are defined by glBlendFunc()






Other Blend Functions

Factor name Computed factor
GL_ZERO 0
GL_ONE 1

GL_SRC_ALPHA As
GL_ONE_MINUS_SRC_ALPHA 1 - As
 
GL_DST_ALPHA Ad
GL_ONE_MINUS_DST_ALPHA 1 - Ad
 
GL_CONSTANT_ALPHA Ac
GL_ONE_MINUS_CONSTANT_ALPHA 1 - Ac

GL_SRC_COLOR (Rs, Gs, Bs)
GL_ONE_MINUS_SRC_COLOR (1 - Rs, 1 - Gs, 1 - Bs)
 
GL_DST_COLOR (Rd, Gd, Bd)
GL_ONE_MINUS_DST_COLOR (1 - Rd, 1 - Gd, 1 - Bd)
 
GL_CONSTANT_COLOR (Rc, Gc, Bc)
GL_ONE_MINUS_CONSTANT_COLOR (1 - Rc, 1 - Gc, 1 - Bc)

GL_SRC_ALPHA_SATURATE min(As, 1 - Ad)





Filters

Blending can be used to apply a color filter to the whole scene

Draw a square that covers the entire window, with the appropriate blending function

 # Dim the scene 

glBlendFunc(GL_ZERO, GL_SRC_ALPHA)          
glColor4f(1.0, 1.0, 1.0, 0.5)

Example: filter.py






Filters

 # Apply a purple filter

glBlendFunc(GL_ZERO, GL_SRC_COLOR)
glColor4f(1.0, 0.0, 0.5, 1.0)
 # Invert all the colors

glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO)     
glColor4f(1.0, 1.0, 1.0, 1.0)


Creative Commons License
This document is by Dave Pape, and is released under a Creative Commons License.