When I first learned about programming DirectX using shaders, it was back when DirectX 9 was
the newest thing around. Back then, there were only two stages in the shader pipeline, the
Vertex and Pixel shaders that we have been utilizing thus far. DirectX 10 introduced the
geometry shader, which allows us to modify entire geometric primitives on the hardware, after
they have gone through the vertex shader.
One application of this capability is rendering billboards. Billboarding is a common
technique for rendering far-off objects or minor scene details, by replacing a full 3D object
with a texture drawn to a quad that is oriented towards the viewer. This is much less
performance-intensive, and for far-off objects and minor details, provides a good-enough
approximation. As an example, many games use billboarding to render grass or other foliage,
and the Total War series renders far-away units as billboard sprites (In Medieval Total War II,
you can see this by zooming in and out on a unit; at a certain point, you’ll see the unit
“pop”, which is the point where the Total War engine switches from rendering sprite
billboards to rendering the full 3D model). The older way of rendering billboards required
one to maintain a dynamic vertex buffer of the quads for the billboards, and to transform the
vertices to orient towards the viewer on the CPU whenever the camera moved. Dynamic vertex
buffers have a lot of overhead, because it is necessary to re-upload the geometry to the GPU
every time it changes, along with the additional overhead of uploading four vertices per
billboard. Using the geometry shader, we can use a static vertex buffer of 3D points, with
only a single vertex per billboard, and expand the point to a camera-aligned quad in the geometry
shader.
We’ll illustrate this technique by porting the TreeBillboard example from Chapter 11 of
Frank Luna’s Introduction to 3D Game
Programming with Direct3D 11.0.
This demo builds upon our previous Alpha-blending
example, adding some tree billboards to the scene. You can download the full code for
this example from my GitHub repository, at https://github.com/ericrrichards/dx11.git
under the TreeBillboardDemo project.