
106 IDiscovering
Writing a good procedural shader is more complicated than using image editing
software to paint a texture or edit a photographic image to suit our needs, but with
procedural shaders, the pattern and the colors can be varied with a simple change of
parameters. This allows extensive reuse of data for many different purposes, as well
as fine-tuning or even complete overhauls of surface appearance very late in a pro-
duction process. A procedural pattern allows for analytic derivatives, which makes it
less complicated to generate the corresponding surface normals, as compared to tra-
ditional bump mapping or normal mapping, and enables analytic anisotropic anti-
aliasing. Procedural patterns require very little storage, and they can be rendered at
an arbitrary resolution without jagged edges or blurring, which is particularly useful
when rendering close-up details in real-time applications where the viewpoint is of-
ten unrestricted. A procedural texture can be designed to avoid problems with seams
and periodic artifacts when applied to a large area, and random-looking detail pat-
terns can be generated automatically instead of having artists paint them. Procedural
shading also removes the memory restrictions for 3D textures and animated patterns.
3D procedural textures, solid textures, can be applied to objects of any shape without
requiring 2D texture coordinates.
While all these advantages have made procedural shading popular for offline ren-
dering, real-time applications have been slow to adopt the practice. One obvious
reason is that the GPU is a limited resource, and quality often has to be sacrificed for
performance. However, recent developments have given us lots of computing power
even on typical consumer-level GPUs, and given their massively parallel architectures,
memory access is becoming a major bottleneck. A modern GPU has an abundance
of texture units and uses caching strategies to reduce the number of accesses to global
memory, but many real-time applications now have an imbalance between texture
bandwidth and processing bandwidth. ALU instructions can essentially be “free”
and cause no slowdown at all when executed in parallel to memory reads, and image-
based textures can be augmented with procedural elements. Somewhat surprisingly,
procedural texturing is a lso useful at the opposite end of the performance scale. GPU
hardware for mobile devices can incur a considerable penalty for texture download
and texture access, and this can sometimes be alleviated by procedural texturing. A
procedural shader does not necessarily have to be complex, as demonstrated by some
of the examples in this chapter.
Procedural methods are not limited to fragment shading. With the ever-
increasing complexity of real-time geometry and the recent introduction of GPU-
hosted tessellation as discussed in Chapter 6, tasks like surface displacements and
secondary animations are best performed on the GPU. The tight interaction be-
tween procedural displacement shaders and procedural surface shaders has proven
very fr uitful for creating complex and impressive visuals in offline shading environ-
ments, and there is no reason to assume that real-time shading would be fundamen-
tally different in that respect.
This chapter is meant as an introduction to procedural shader programming in
GLSL. First, I present some fundamentals of procedural patterns, including antialias-