Give textmesh pro text a billboard effect in shader (Always lookAt camera)


I’m working project where I need a floating text effect. But my target hardware is extremely limited and I cant afford to rotate the texts through script to lookAt the camera always. I tried to alter the TextMeshPro/Mobile/Distance Field shader to get that effect and got close. But its not perfect. There is always offset in both axes and rotation pivot seems to be elsewhere. So the text leaves its rect when I look at it from different angles. This is the code I added in the shader right before vertex shader output is added.

vPosition = mul(UNITY_MATRIX_P, mul(UNITY_MATRIX_MV, float4(0.0, 0.0, 0.0, 1.0)) - float4(vert.x, vert.y , vert.z, 0.0) * float4(-unity_ObjectToWorld[0].x , -unity_ObjectToWorld[1].y , unity_ObjectToWorld[1].z, 0.0));

I need help. Any guidance would be very much appreciated.

Almar, has this shader been updated to work with URP?

It would be great to get it working in our current game, we’ve reverted to aligning the transform, but the your solution worked great before we updated to URP! :slight_smile:

Sorry for necro’ing this question, but it might help people:

I just put a shader gist online for this. The important part is to disable the dynamic batching!

See: Unity TextMeshPro Billboard / always facing camera shader · GitHub

This isn’t a shader-based solution, but just in case this might help you:

If you parent the text’s transform to the camera’s transform, you only have to call lookAt once, in the start function. For example, here is a monoBehavior you can use and attach to your TextMeshPro object:

using UnityEngine;

public class BillboardText : MonoBehaviour
	void Start ()
        transform.localEulerAngles = new Vector3(180f, 180f, 180f);

I have to rotate the text afterwards because it shows completely flip side for me. So I left that in in case it helps you.

Match the text’s rotation with that of the camera

public class BillboardText : MonoBehaviour {
    void Update() {
        transform.rotation = Camera.main.transform.rotation;