Billboarding How To

 

1. Introduction 2. What is Billboarding 3. Terms 4. Point Sprites 4.1 Collective Billboarding 4.2 Individual Billboarding 5. Axis Aligned Billboards 6. Arbitrary Axis Billboards 7. Using Those Billboard Vectors 8. Rendering a Billboard

1. Introduction

I looked around a lot for a good billboarding tutorial, but the most I could ever find was a short document that missed a lot or some code with bad commenting. My intention with this document and code was to resolve those issues. I hope this document explains things well enough so you can get billboarding to work in your code. There is also accompanying source to demonstrate this, the source requires that you have freetype and directX5 to build; although I did include a Windows® executable for those who can’t build it. You may notice that there is a lot more code than just billboarding code that comes with. This is a collection of source I written over time, and most my projects I make are based on it. I made the billboarding code in a separate file from this, so hopefully you can just paste the source into your project if you so desire. Questions and comments can be emailed to: opengltut@hotmail.com.

This document should give you an overview of billboarding and it should also teach you how to implement billboarding in your own code. This was written with the purpose of assisting the MDX file document to describe the billboarding techniques used for rendering the MDX models. But it is also intended to be a standalone tutorial. The MDX document is a collection of information on how to render the MDX models from Blizzard’s WarCraft3®. This document is not finished yet, and will be released some day soon.

2. What is Billboarding

Billboarding is a simple concept, but can be difficult to implement. A billboard is a flat object, usually a quad (square), which faces the camera. This direction usually changes constantly during runtime as the object and camera move, and the object needs to be rotated each frame to point in that direction. There are two types of billboarding: point and axis. Point sprites, or point billboards, are a quad that is centered at a point and the billboard rotates about that central point to face the user. Axis billboards come in two types: axis aligned and arbitrary. The axis-aligned (AA) billboards always have one local axis that is aligned with a global axis, and they are rotated about that axis to face the user. The arbitrary axis billboards are rotated about any axis to face the user.

Billboards will always face the camera, but this technique can also be used to face other objects as well. For instance, this can be used to rotate a turret to face a target, or to have the head on a character follow another character.

The concepts in the document use the right handed coordinate system and assume that the billboards you are drawing will face down the +z axis, up is the +y axis, and right is the +x axis. I found this site: http://www.evl.uic.edu/ralph/508S98/coordinates.html has a good explanation.

3. Terms

Point sprite A quad billboard rotated about a central point that faces the camera.
Axis Aligned billboard A billboard that rotates about an axis (x, y, z). The up vector for the billboard is along that axis.
Axis billboard A billboard that is aligned along an arbitrary axis, this can include axis aligned billboards. The up vector for the billboard is along the arbitrary axis.
Look vector The direction the object is facing.
Up vector The up direction of the object.
Right vector The right direction of the object.
Global axis The axis system for the entire application as defined by OpenGL with no transformations applied.

4. Point Sprites

Points sprites are the most common billboard you will usually see, and of course they have a couple flavors to them. The sprites can be billboarded collectively or individually. Collective billboarding is very quick, because you only need to create one transformation matrix to share between all the points, while individual billboards require that you calculate a new transformation matrix for each billboard.

4.1. Collective Billboarding

Collective billboards all face the same direction, and start to look flat as they get closer to the edges of the screen. This is because the direction the billboards face is calculated as the inverse look direction of the camera. This makes a quick and dirty calculation, but may not create the effect you are looking for. The up vector for the collective point sprite is the same as the up vector for the camera. And the right vector is the inverse of the camera’s right vector.

4.2. Individual Billboarding

Individual billboards require some math to point at the camera. To start, you will need to know the camera up vector and position and the billboard position. We will use these to calculate the local billboard’s axis. The billboard look vector is calculated from the camera position and billboard position. The vector is from the billboard to the camera; normalize the vector when finished.

look = camera_pos - point_pos;

Next, calculate the right vector for the billboard. To do this though, you first need an up vector for the billboard. But to get the final up vector you first need the billboards right vector. Obviously we’re going nowhere here, but there is a simple way out. We can use the camera up vector as the temporary up vector for the billboard. This works because the final billboard up vector, the billboard look vector, and the camera up vector lie along the plane that contains the camera and billboard locations. The plane also has a normal equal to the billboard right vector. That can be a lot to take in, so look at this pretty picture to help. The blue vectors are the direction the object is facing, the green vectors are up vectors, and the red vectors are right.


Figure 1 - All three green vectors lie in the plane outlined in grey, the dark blue vector on the
particle also lies in this plane. The dark red vector is perpendicular to the plane.


With the billboard look vector and the camera up vector, we can get the right vector by calculating the cross product of the two vectors. Both the up and look vectors are normalized at this point, so the result will also be normalized.

right = up x look;

We can now calculate the up vector for the billboard with another cross product; this is the final up vector for the billboard.

up = look x right;

Now, you may be asking yourself why we couldn’t just use the camera up vector for the billboard up vector. If we did this, our local axis for the billboard (right, up, look) wouldn’t all be perpendicular to each other, that is some of the angles between the axis would not be 90º to the other axis. This would make for some odd side effects when applying the rotation matrix to use for billboarding our object.

5. Axis Aligned Billboards

Axis aligned billboards lock their up vector into a global axis, either x or y or z. The billboard is then rotated around the local y axis to face the camera. The calculations follow the same format as above, but we are given the local up vector to make the math simpler.


Figure 2 – The three Axis Aligned billboards, each access shows the local Y axis drawn in green over
the axis that the billboard is aligned to. The billboard is draw in its axis color about that axis.


There are three cases of axis aligned billboards, one for each axis. As stated above, the billboard is always rotated about the local Y axis. This means that the local Y axis is rotated into the global axis that we are aligned to. This also means that we don’t need to create the billboard up vector from the camera up vector, it is given to us. We can follow the steps as we did for the point sprite. Calculate the billboard look vector as the vector from the billboard center to the camera location; then zero the value for the axis we are aligned to and normalize the vector. The up vector is given to us as the aligned axis which means we don’t need to use a temporary up vector to create the right vector. Instead we can calculate the right vector as the cross product of up and look and we’re done.

right = up x look;

 

6. Arbitrary Axis Billboards

Arbitrarily aligned billboards might sound difficult, heck it kind of hard to pronounce, but they follow a similar idea and code path as the rest of the billboards types. The billboard calculation starts like the rest, calculate the billboard look vector as the vector from the billboard center to the camera position. Although this value isn’t the final look vector, it’s a temporary value used to calculate the right and up vectors. This works on the same principal as the point sprite using the camera up vector as a temporary billboard up vector. This look vector lies along the same plane as the final look vector will; but the temporary look vector is not perpendicular to the billboard up vector. The billboard up vector is the arbitrary axis we want the billboard to rotate about. Now that we have two vectors we can do a cross product to get the right vector.

right = up x look;

 


Figure 3 – Representation of a particle billboarded about an arbitrary axis. The green vectors are up
vectors, the blue are look vectors, the red are right vectors, and the gold is the temporary
look vector. The top left object is the particle and the bottom right is the camera.


Now, there is a special case to watch out for. When the billboard up vector is almost parallel to the billboard look vector, the cross product doesn’t result in a normalized vector, due to floating point limitations. If the vectors are parallel, the cross product will have a magnitude of zero, that’s just how they work. For these reasons, we will recalculate the unit vector for the right vector. If the look and up vectors are parallel, you can choose to not draw the particle since you would be looking down the edge of a flat polygon anyways. The code sample chooses to live with whatever side-effects may arise when the look and up vectors are parallel because this event is extremely rare. It requires the two vectors to be exactly parallel, if they are just really close, the normalization should fix it.

Now that we have legitimate up and right vectors, we can get back to calculating the final look vector.

look = right x up;

Not so bad after all, we can now use these vectors to calculate the billboard matrix. Read on to see how.

7. Using Those Billboard Vectors

Ok, you’ve found multiple ways to create a local coordinate system for a billboard. Now you’re wondering how to make use of them. I’ve saved that until now because they all follow the same code to make the billboard a billboard. Keep in mind that all our billboard vectors are normalized, so we can use the rule of orthogonal matrices to create a rotation matrix for the billboard. The whole orthogonal matrix explanation is outside the scope of this document, so just implement as I show you and it will work :) The rules state that in order to transform the local coordinates into the global coordinates we must multiply by this vector.

	[r1	u1	l1	px]
	[r2	u2	l2	py]
	[r3	u3	l3	pz]
	[0	0	0	1]

The vectors are (r)ight, (u)p, (l)ook; and the values are the offsets in the vector (1, 2, 3). The right, up, and look vectors are as you guessed, the values we calculated earlier. This matrix will transform the billboard coordinate system into the global coordinate system. Now you can multiply by this in the rendering stage and your billboard will be properly facing the camera. If you haven’t figured it out already, the p* values are the world position of the billboard (px, py, pz).

Make sure you push the current model view matrix before multiplying by this transformation matrix and then pop the matrix after rendering the quad. If you don’t, you will end up only having the first billboard work as the billboard matrices will accumulate in the model view matrix.

8. Rendering a Billboard

Lastly, we need to know how to render a billboard. For all the above calculations, we set the Y axis to the billboard up vector, and the X axis to the right vector. So the billboard is drawn along the XY plane facing down the +Z axis.

glBegin(GL_TRIANGLE_FAN);
glVertex3f(10, -12, 0);
glVertex3f(10, 12, 0);
glVertex3f(-10, 12, 0);
glVertex3f(-10, -12, 0);
glEnd();

You can change the coordinate values for the billboard as needed. They don’t need to be a square or rectangle either; just make sure all the points are on the same plane. Of course if the points don’t lie on the XY plane the billboard won’t work.

If your billboards aren’t in the XY plane, you’ll need to adjust the billboard matrix that is created so that the billboard look vector is the normal to the plane that the billboard is on. For instance, if you billboard is in the XZ plane, the normal for that plane is the +Y axis. Your billboard look vector now needs to be rotated into the +Y axis. The billboard up vector will be rotated into the +Z axis, and the right vector is the cross from look to up, which is the +X axis.

Download the code for this article: Billboard Demo