In computer graphics, Material is a fundamental concept. Like a sheet of really special stretchy wallpaper, it is the collection of elements and properties that describe the visual characteristics of a surface. This encompasses texture, color, transparency, reflection, refraction and much more. Even so, it does not usually say anything about the geometry whose surface is described by a Material.
While Material is a useful abstraction for us, as software engineers and artists, it maps poorly to modern computer graphics hardware. The Material abstraction wildly cross-cuts a large number of subsystems in a modern renderer. As a result, most easy-to-use direct implementations of this concept you're likely to encounter are slow and/or rigid. That being the case, it's a great computer science problem to examine, and any solid, easy-to-use, reasonably fast and flexible solution is useful.
Relationship to Geometry
Let's define a low-level Geometry type as simply a list of vertices and an associated description of the vertex layout. Let's call a description of a vertex layout a Vertex Format. We'll talk about these vertex layouts at length later. The vertex layout is necessary because each vertex in a Geometry can be annotated with additional information, such as texture coordinates, the normal vector of the vertex, color, or pretty much anything you want.
Since the visual appearance of a geometric surface is described by a Material, any higher level geometric abstraction such as a mesh will refer to Materials as well as Geometries. An individual Geometry will be associated with a single Material, although multiple Geometries may point to the same Material.
Unfortunately, a Material needs to know the layout of the associated Geometry. In fact much of the time, the layout and the additional information included in each vertex in the Geometry is in determined by the choice of Material associated with it. This is an unpleasant reverse dependency that tightly couples Geometry creation with a Material.
Relationship to Textures
Here, let's broadly divide the Textures category into two parts - dynamic and static. Dynamic textures are those that can be written to and modified at runtime. An example might be a frame of a video during playback. Static textures are those that we probably load from disk. They don't ever change.
Textures may have different uses. The most common, of course, is that a texture represents an image to be wrapped around a surface. However, in the age of Shaders (see below), textures can represent any two+ dimensional array of data and are frequently used to store a vector (often a per-pixel normal vector) at each pixel.
A Material can refer to static and dynamic textures.
Relationship to Shaders and Shader Constants
Shaders come in different forms. Generally, there are vertex and pixel shaders. A shader is a small program that runs on the GPU for each vertex or pixel. These days, the classic distinction between the two is blurring. In the past an assembly language that was compiled into the hardware-dependent GPU machine code was the predominant way to program shaders. Currently, higher level languages such as HLSL and Cg are more common.
Shaders are tightly coupled with the vertex layout of Geometries and the number and intent of Textures in a Material. Shader Constants are the primary method of game-to-shader communication and as a result, they tend to impose a great deal of coupling between the shader design and the design of the code that invokes it. Some shader constants really are constant (PI, for example), some will be bound to attributes of the Geometry. Others may be related to world or game state. In a lighting shader, the constants may hold the location of the five nearest light sources. Shaders usually require that the current world transform be passed in as shader constants.
Applying a Material
So how do we apply a material? It depends on what the material specifies and a lot of other things as well. We'll look at some possibilities in the upcoming parts.
Render Components for a Given Material Pass
