Implementing a Billboard Shader in Unity Shadergraph


UPDATE: The shader shared in this article works for unlit billboards and is quite fast, but it suffers from self-shadowing issues when using a lit master node. We fix this self-shadowing issue in our billboard shader here.

In some cases, we want to get an object to rotate towards the player/camera as it moves. This is a pretty neat effect which is especially common for vegetation (bushes or grass).

The problem is that it is expensive to actually rotate the object in world space, due to all the computations needed to get the camera/player position and convert local space coordinates to world coordinates.

A common solution is therefore to offload these computations from CPU to GPU, by using what is called Billboarding.

A Billboard shader is a shader that computes the direction from the camera to a given object and adjusts the rendering angle of the object to be always facing the camera.

This implementation is taken from

Here are the nodes used. That’s a pretty simple graph for a powerful effect.

billboard shader shadergraph
Shadergraph implementation of Billboard

Basically, what happens here is that we take the object position, adjust for scale, and then we compute the view position, aka where the vertices should be if we were looking straight at the object with the camera.

We then adjust these view coordinates by the world coordinates of the object, so that the object is merely rotated, and not moved.

Finally, since the master node expects coordinates in Object Space, we do a final conversion.

billboard shader shadergraph
The HI quad is rotating with the camera

To Note: One drawback from this method is that the shadow is not rotated along with the billboard.

This is a simple implementation, but you can go even further, and modify what is actually being rendered depending on the angle between the camera and the object, by using methods like triplanar shading. This can give the illusion of a complex 3D object while you’re only rendering a quad, so you’re avoiding rendering a complex mesh.

This is what’s called an impostor, check it out!