The toon shading example belongs to a class of
effects called nonphotorealistic effects, often
known as NPR effects. Having dangled the carrot of
shaders in front of you, I’d now like to show that ES 1.1 can also render
some cool effects.For example, you might want to produce a
intentionally faceted look to better illustrate the geometry; this is
useful in applications such as CAD visualization or technical
illustration. Figure 1 shows a two-pass
technique whereby the model is first rendered with triangles and then with
lines. The result is less messy than the wireframe viewer because hidden
lines have been eliminated.
An issue with this two-pass technique is
Z-fighting. An obvious workaround
is translating the first pass backward ever so slightly, or translating
the second pass forward. Unfortunately, that approach causes issues
because of the nonlinearity of depth precision; some portions of your
model would look fine, but other parts may have lines on the opposite side
that poke through.
It turns out that both versions of OpenGL ES
offer a solution to this specific issue, and it’s called
polygon offset. Polygon offset tweaks the Z value
of each pixel according to the depth slope of the triangle that it’s in.
You can enable and set it up like so:
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(factor, units);
factor scales the depth
slope, and units gets added to the result. When polygon
offset is enabled, the Z values in each triangle get tweaked as
follows:
You can find the code to implement this effect
in ModelViewer in the downloadable examples. Note that your
RenderingEngine class will need to store two VBO
handles for index buffers: one for the line indices, the other for the
triangle indices. In practice, finding the right values for
factor and units almost
always requires experimentation.
Warning:
Because of a hardware limitation, first- and
second-generation iPhones ignore the factor argument
in glPolygonOffset.
One rather obscure feature found only in
OpenGL ES 1.1 is flat shading, whereby OpenGL
forces the color of each triangle to be uniform. OpenGL performs flat
shading by choosing a specific vertex in each triangle and then
spreading its associated color throughout the triangle. You can turn it
on and off as follows: glShadeModel(GL_FLAT); // Turn on flat shading glShadeModel(GL_SMOOTH); // Turn off flat shading (the default)
I suspect this feature is a bit of a leftover
from olden times, when flat shading was a desirable option to increase
performance. Nowadays it’s probably useful only for nonphotorealistic
rendering. Another way to achieve something similar is simply
duplicating the same normal vector at each of the three corners in each
triangle; this is one approach you could take for ES 2.0. |