Textures in OpenGL

CS 381 Lecture, Dr. Lawlor

Here's how I do textures in OpenGL:
  1. Make up some texture data in C++.  A texture is just a big 1D array of bytes, with groups of 4 bytes representing the RGBA color of each pixel, and pixels listed in x-first, then y-first order.  For example, here's a  2x2 texture with red, green, blue, and white pixels:
    	enum {w=2}; enum{h=2};
    unsigned char colors[4*w*h]={
    /*R G B A */
    0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff,
    0x00,0x00,0xff,0xff, 0xff,0xff,0xff,0x7f,
    };
  2. Copy the texture data from C++ onto the graphics card.  I've written a handy class to do this, "oglTexture".  The constructor takes a pointer to your pixel data (from step 1), and the width and height of the texture in pixels.  WARNING: most graphics cards can only handle power-of-two sized textures!
    bob
    	oglTexture *t=new oglTexture(pixelData,w,h);
  3. Every frame, before drawing geometry that's going to use that texture, "bind" the texture as the current texture, like
    	t->bind();	
  4. Optionally, set the wrap and filtering modes.  See below for your options.
  5. Declare the  texture as a "sampler2D" object in GLSL.  This is a uniform, coming in from C++.  Textures always work in the fragment shader, but with the latest hardware also work in the vertex shader.
    	uniform sampler2D myTex;
  6. In C++, copy the texture unit number (more on those later) into GLSL, with glUniform1iARB or oglProgramObject->set.  The default texture unit is unit 0:
    	program->set("myTex",0);
  7. Back in GLSL, call "texture2D(myTex,texCoords)" with a vec2 of 'texture coordinates' to look up the texture value.  Texture coordinates ARE NOT PIXEL COORDINATES--they always go from 0.0 at the left and top of the image to 1.0 at the right and bottom of the image.  Depending on your wrap modes (in step 4), texture coordinates can go far outside these values.  Texture coordinates can be interpolated from the vertex shader (the typical, old-school approach), or computed directly in the fragment shader.  The looked-up texture value can be used for anything, from an ordinary color to a vector perturbation.
    	gl_FragColor = texture2D(myTex,texCoords);
Definitely check out the example program linked from the front page to see how it all fits together.

Texture Coordinate Wrapping

You can change what happens outside normal texture coordinate bounds, on both the S (x axis) and T (y axis) texture coordinate axes.

Texture Filtering

You can also change how colors interpolate between pixels in the texture map when blowing up the texture map onscreen ("magnification" mode):
The same options exist when shrinking a texture map down onscreen ("minification" mode), along with extra "mipmap" options:
You definitely have to just try these things out.  Fire up the example 'texture' code, crank up the scale factor to put a zillion copies of the texture onscreen, and tilt and rotate.