Text Occlusion in Unity

Over the past few days, I have been tinkering with some simple HoloLens projects. I hope to go into more details on these in a later post, but today I thought I would share some information regarding 3D text and occlusion with unity.

For any of my illustrious readers who might not know, occlusion is when an object is blocked (occluded) from the view of the observer by another object (it occludes the other object). Think of a person walking on the far side of the street. If a bus were to pass between you and the other person, the person would be occluded from your view. The same principle applies in 3D modeling.

The issue I discovered is with 3D text in unity. By default, the shader that 3D text uses is the same one for GUI text (a shader is a script that contains the mathematical calculations and algorithms for calculating the colour of each pixel rendered). In a shooter video game, the heads up display with your health and ammunition should always display in front of you, in front of any other objects (GUI Text). This is a much less desirable effect when displaying the time on an alarm clock 3D model. The time shouldn’t be visible through walls or out the back of the clock. The text there should be occluded.

This sample uses a very basic 3D cube and positioned slightly behind it is an empty game object with a TextMesh component applied to it. As you can see, the text shows right through the cube. No occlusion out of the box here.

So if the default shader doesn’t get me what I need, I need to create my own. Luckily, I’m certainly not the first person to encounter this issue and be seeking an answer. Unity provided the shader script for me along with some basic instructions. I thought I would document my process here and help flesh out some of the areas which I felt were a bit unclear in the instructions.

1. Create/import the assets we need
The 3 assets we need are a shader, material and a font. We can create a new empty shader and material by right clicking the project section of our unity window, selecting create and finding the shader and material from the context menu.

As for the font, a quick google search for “Arial truetype font” turned up a .ttf file from GitHub (thanks to JotJunior for the file). I simply downloaded it and dragged it from my downloads folder into the project window. Download it from here if you want to follow along.

https://github.com/JotJunior/PHP-Boleto-ZF2/raw/master/public/assets/fonts/arial.ttf

A quick rename of my assets to help identify them, and I’m ready to roll.

2. Configure the shader
double clicking our OccludedTextShader or right clicking it and selecting “open” will allow us to edit the content of the shader, to have a script that correctly makes use of occlusion. Replace the entire contents of the OccludedTextShader with the following:

Shader "GUI/3D Text Shader" { 
	Properties {
		_MainTex ("Font Texture", 2D) = "white" {}
		_Color ("Text Color", Color) = (1,1,1,1)
	}
 
	SubShader {
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
		Lighting Off Cull Off ZWrite Off Fog { Mode Off }
		Blend SrcAlpha OneMinusSrcAlpha
		Pass {
			Color [_Color]
			SetTexture [_MainTex] {
				combine primary, texture * primary
			}
		}
	}
}

3. Configure the material
Our OccludedTextMaterial needs to be configured to use a shader of the same type as the OccludedTextShader we just created. Select the OccludedTextMaterial from the project window and in the inspector, change the shader dropdown value to GUI/3D Text Shader. Now we need to set the font texture for OccludedTextMaterial. We expand our arial font file in the project window and drag the font material into the font texture window of OccludedTextMaterial. While we are here, we will set the desired font color. I chose red to have it stand out boldly against the default white of the object that will occlude the text.

4. Configure the game object with our text to use the new assets
By selecting the HelloWorld game object (which has our text mesh on it) from the hierarchy window, we can then drag our arial font from the project window onto the font field.

5. Apply out new OccludedTextMaterial to the Mesh Renderer
Now that we are using our imported font, we then need to update the MeshRenderer of HelloWorld to use our new OccludedTextMaterial. Drag the OccludedTextMaterial from the project window onto the material field of the MeshRenderer.

And with that, we have achieved occlusion! As you can see, the cube now occludes the text behind it. If we rotate the camera to the back side of the scene, we can see the text is then in front of the cube. Our text interacts visually the way we would expect it to in the real world.

Thanks for following along. I hope you found this article useful or learned something new about shaders or occlusion. Check back soon for more how-to articles or updates on what I’m doing.

Leave a comment