A texture map is a 1D, 2D, or 3D array of "texels".
A texel has 1, 2, 3, or 4 values, typically corresponding to RGB or RGBA (where A is opacity).
Each texel has coordinates within the texture map. Coordinates are always in the range $[0,1]$, regardlesss of the dimensions of the texture map. So a non-square texture map would still have texture coordinates in $[0,1] \times [0,1]$.
Vertices of a primitive can have texture coordinates as an attribute. This attribute gets stored in a VBO in the usual manner. Upon rendering, the vertex shader gets the texture coordinates of each vertex and, typically, outputs them for smooth interpolation across the fragments of the primitive. Then the fragment shader uses the interpolated texture coordinates to look up texels from a texture.
A texture is stored on the GPU by
The GPU has a number of texture units which are used to look up texture values, given the floating-point texture coordinates. These texture units can do a simple texel lookup or can blend texture values from nearby texels.
A texture unit N is connected to a particular texture texID by
The program on the CPU side must then tell the GPU shaders which texture unit to use. This is done by setting a "uniform" to the texture unit ID. The shader can then look up a texture value by
In the following diagram, the colours show the code that transmits a texture (purple), links a texture to a texture unit (cyan), or looks up a texture value (red).
See 04-textures/wavefront.cpp in openGL.zip.
There are several different modes of drawing textures on a surface:
See 04-textures/wavefront.frag in openGL.zip.