- Careful Enabling Color Material
OpenGL's color material feature provides a less expensive way to
change material parameters. With color material enabled, material
colors track the current color. This means that instead of using the
relatively expensive glMaterialfv
routine, you can use the
glColor3f
routine.
Here is an example using the color material feature to change the
diffuse color for each vertex of a triangle:
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_TRIANGLES);
glColor3f(0.2, 0.5, 0.8);
glVertex3f(1.0, 0.0, 0.0);
glColor3f(0.3, 0.5, 0.6);
glVertex3f(0.0, 0.0, 0.0);
glColor3f(0.4, 0.2, 0.2);
glVertex3f(1.0, 1.0, 0.0);
glEnd();
Consider the more expensive code sequence needed if glMaterialfv
is
used explicitly:
GLfloat d1[] = { 0.2, 0.5, 0.8, 1.0 };
GLfloat d2[] = { 0.3, 0.5, 0.6, 1.0 };
GLfloat d3[] = { 0.4, 0.2, 0.2, 1.0 };
glBegin(GL_TRIANGLES);
glMaterialfv(GL_FRONT,GL_DIFFUSE,d1);
glVertex3f(1.0, 0.0, 0.0);
glMaterialfv(GL_FRONT,GL_DIFFUSE,d2);
glVertex3f(0.0, 0.0, 0.0);
glMaterialfv(GL_FRONT,GL_DIFFUSE,d3);
glVertex3f(1.0, 1.0, 0.0);
glEnd();
If you are rendering objects that require frequent simple material
changes, try to use the color material mode. However, there is a
common pitfall encountered when enabling the color material mode. When
color material is enabled, OpenGL immediately changes the material
colors controlled by the color material state. Consider the following
piece of code to initialize a newly create OpenGL rendering context:
GLfloat a[] = { 0.1, 0.1, 0.1, 1.0 };
glColor4f(1.0, 1.0, 1.0, 1.0);
glMaterialfv(GL_FRONT, GL_AMBIENT, a);
glEnable(GL_COLOR_MATERIAL); /* WARNING: Ambient and diffuse material latch immediately to the current color. */
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(0.3, 0.5, 0.6);
What state will the front ambient and diffuse material colors be after
executing the above code fragment? While the programmer may have
intended the ambient material state to be (0.1, 0.1, 0.1, 1.0)
and
the diffuse material state to be (0.3, 0.5, 0.6, 1.0)
, that is not
quite what happens.
The resulting diffuse material state is what the programmer intended,
but the resulting ambient material state is rather unexpectedly (1.0,
1.0, 1.0, 1.0)
. How did that happen? Well, remember that the color material mode immediately begins tracking the current color when
enabled. The initial value for the color material settings is
GL_FRONT_AND_BACK
and GL_AMBIENT_AND_DIFFUSE
(probably not what
you expected!).
Since enabling the color material mode immediately begins tracking the
current color, both the ambient and diffuse material states are
updated to be (1.0, 1.0, 1.0, 1.0)
. Note that the effect of the
initial glMaterialfv
is lost. Next, the color material state is
updated to just change the front diffuse material. Lastly, the
glColor3f
invocation changes the diffuse material to (0.3, 0.5,
0.6, 1.0)
. The ambient material state ends up being (1.0, 1.0, 1.0, 1.0)
.
The problem in the code fragment above is that the color material mode
is enabled before calling glColorMaterial
. The color material mode
is very effective for efficient simple material changes, but to avoid
the above pitfall, always be careful to set glColorMaterial
before
you enable GL_COLOR_MATERIAL
.