Mapping Vertices to Texels

The idea of pasting a 2D texture onto a 3D surface is backward. The opposite is what actually happens: the 3D model is flattened or unwrapped onto the 2D texture. Each vertex flattens onto a location within the bounds of the texture. The 2D coordinates of the location are called texture coordinates, and they are stored as an additional vertex attribute.

Sometimes multiple resolutions of a texture are provided. When the viewer is close to the texture or when the graphics card is a beast, a high-resolution version of the texture is used. When the viewer is too far away from the texture to see detail or if the graphics card is an underachiever, a low-resolution version is used. So that the same texture coordinates can be applied to either version of the image, the coordinates are stored not as absolute numbers but as proportions in [0, 1].

Consider this square, whose spatial positions span [-1, 1] but whose texture coordinates span [0.2, 0.8]:

const positions = [
  -1, -1, 0,
   1, -1, 0,
   1,  1, 0,
  -1,  1, 0,
];

const texPositions = [
  0.2, 0.2,
  0.8, 0.2,
  0.8, 0.8,
  0.2, 0.8, 
];

const attributes = new VertexAttributes();
attributes.addAttribute('position', 4, 3, positions);
attributes.addAttribute('texPosition', 4, 2, texPositions);

The texture-mapped square appears in the left panel of this renderer, and the complete texture is shown in the right panel:

The wireframe shows the unwrapping of the square onto the texture. Note how the texture coordinates of 0.2 and 0.8 inset the unwrapping by 20% on each side. Drag the vertices around to alter the texture coordinates and see how the textured view changes. In particular, try the following:

Observe that changing a vertex's texture coordinates has no impact on its spatial position. The square steadfastly remains a square, even if its unwrapping is not a square.

Unwrapping the square does not require much effort or imagination since it is already flat. Sophisticated models require a more surgical approach and are usually unwrapped in a 3D modeling application, where a mixture of algorithms and manual editing are used to place vertices on the texture.

The texture coordinates assigned by the modeling application are stored in model file, as in this OBJ file of an octagon:

v 0.000000 1.000000 0.000000
v -0.707107 0.707107 0.000000
v -1.000000 0.000000 0.000000
v -0.707107 -0.707107 0.000000
v 0.000000 -1.000000 0.000000
v 0.707107 -0.707107 0.000000
v 1.000000 0.000000 0.000000
v 0.707107 0.707107 0.000000
vt 0.000100 0.707065
vt 0.292935 0.000100
vt 0.999900 0.292935
vt 0.000100 0.292935
vt 0.707065 0.000100
vt 0.999900 0.707066
vt 0.707066 0.999900
vt 0.292935 0.999900
vn 0.0000 0.0000 -1.0000
f 3/1/1 1/2/1 7/3/1
f 3/1/1 2/4/1 1/2/1
f 1/2/1 8/5/1 7/3/1
f 7/3/1 6/6/1 5/7/1
f 5/7/1 4/8/1 7/3/1
f 4/8/1 3/1/1 7/3/1

Each vt line describes one set of texture coordinates. The slash tokens in the f lines define each vertex as a combination of a spatial position, a texture position, and a normal.