Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a normal to a text mesh so that it lights correctly?

I'm using a text mesh to place text on a 3D object, but as you all know, the text mesh does not have any normals...

http://docs.unity3d.com/Documentation/Components/class-TextMesh.html

...so it does not light correctly. I've done a search and found many people having trouble with lighting 3D text mesh because of it doesn't have any normals, but I haven't found a solution to adding normals to a text mesh object, so that is my question.

How can I add a normal to a text mesh so that it lights correctly?

Thanks so much in advance for your wisdom!

like image 325
BeachRunnerFred Avatar asked Apr 26 '13 03:04

BeachRunnerFred


People also ask

How do I add materials to text Unity?

You can't drag a UI material directly onto UI pieces, but, for instance, the Text (Script) area in the inspector—the same place you enter the text you want displayed in that box—has a property toward the bottom called "Material." You can drag a new material into there.

How do I make text mesh pro material?

To create an empty TextMesh Pro font asset, select a Unity font Asset and then select Asset > Create > TextMeshPro > Font Asset from the menu.

How do I edit TextMeshPro?

Now the problem is, that I want to change the text of the TextMeshPro in the gun script. Simplest solution: create "public TextMeshPro textMesh". Drag the TextMeshPro object to the script in the inspector and youre good to go.

What is text mesh pro?

TextMesh Pro is a replacement for Unity's existing text components like Text Mesh and UI Text. TextMesh Pro uses Signed Distance Field (SDF) as its primary text rendering pipeline making it possible to render text cleanly at any point size and resolution.


1 Answers

I did something similar for lighting a 3D texture. I hope my answer isn't overkill. So this code was a hack I wrote awhile back, it's inefficient and only supports a single directional light (helpful cg lighting tuts here). Hopefully this is enough to get you started.

To create a 3D texture using my code below you have to go through a little more work:

  1. Create an empty game object
  2. Attach Component->Mesh->Text Mesh
  3. Attach Component TextMeshNormals (included below)
  4. Attach Component->Mesh->Mesh Renderer
  5. Assign a material to the Mesh Renderer that uses my GUI/LitText shader below

In the shader you'll notice a text normal attribute. In practice you would have your gameObject's Update() method update the _Normal property with the direction the text is facing so that it reflects a change in orientation. The text is planar so 1 normal is all we need. To test I manually set the normal to (0,0,-1,1), since the default Text Mesh faces down -Z.

Because this script doesn't run in the editor, your text won't show up until you run a scene in preview.

The shader:

Shader "GUI/LitText" { 
Properties { 
   _MainTex ("Font Texture", 2D) = "white" {} 
   _Color ("Text Color", Color) = (1,1,1,1) 
   _Normal ("Text Normal",Vector) = (0,0,0,1)
} 

SubShader {
    Blend SrcAlpha OneMinusSrcAlpha
    Pass { 
        Color [_Color] 
        SetTexture [_MainTex] { 
            combine primary, texture * primary 
        } 
    } 
    pass {
         Tags { "LightMode" = "ForwardBase" } 

         CGPROGRAM

         #pragma vertex vert  
         #pragma fragment frag 

         uniform sampler2D _MainTex;  
         uniform float4 _Color; // define shader property for shaders
         uniform float4 _Normal;

         // The following built-in uniforms (apart from _LightColor0) 
         // are defined in "UnityCG.cginc", which could be #included 
         uniform float4 unity_Scale; // w = 1/scale; see _World2Object
         uniform float3 _WorldSpaceCameraPos;
         uniform float4x4 _Object2World; // model matrix
         uniform float4x4 _World2Object; // inverse model matrix 
            // (all but the bottom-right element have to be scaled 
            // with unity_Scale.w if scaling is important) 
         uniform float4 _WorldSpaceLightPos0; 
            // position or direction of light source
         uniform float4 _LightColor0; 
            // color of light source (from "Lighting.cginc")

         struct vertexInput {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float4 texcoord : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 col : COLOR;
            float4 tex : TEXCOORD0;
         };

         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;

            float4x4 modelMatrix = _Object2World;
            float4x4 modelMatrixInverse = _World2Object; 

            float3 normalDirection = normalize(float3(mul(_Normal, modelMatrixInverse)));
            float3 lightDirection = normalize(float3(_WorldSpaceLightPos0));

            float3 diffuseReflection = float3(_LightColor0) * float3(_Color)
               * max(0.0, dot(normalDirection, lightDirection));

            output.col = float4(diffuseReflection, 1.0);
            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
            output.tex = input.texcoord;
            return output;
         }

         float4 frag(vertexOutput input) : COLOR
         {
            half4 color = tex2D(_MainTex, float2(input.tex));
            // use color.a to get alpha from text texture, rgb comes from vertex shader                        
            return float4(input.col.r,input.col.g,input.col.b,color.a);
         }

         ENDCG
    }
}
}

And the helper script:

public class TextMeshNormals : MonoBehaviour {
    private TextMesh textMesh;

    // Use this for initialization
    void Start () {
        // reassign font texture to our material
        textMesh = transform.GetComponent<TextMesh>();
        renderer.material.mainTexture = textMesh.font.material.mainTexture;
    }
}

Update Unity 4.5.X use this slightly updated version:

Shader "GUI/LitText" { 
Properties { 
   _MainTex ("Font Texture", 2D) = "white" {} 
   _Color ("Text Color", Color) = (1,1,1,1) 
   _Normal ("Text Normal",Vector) = (0,0,0,1)
} 

SubShader {
    Blend SrcAlpha OneMinusSrcAlpha
    Pass { 
        Color [_Color] 
        SetTexture [_MainTex] { 
            combine primary, texture * primary 
        } 
    } 
    pass {
         Tags { "LightMode" = "ForwardBase" } 

         CGPROGRAM

         #pragma vertex vert  
         #pragma fragment frag 

         uniform sampler2D _MainTex;  
         uniform float4 _Color; // define shader property for shaders
         uniform float4 _Normal;
         uniform float4 _LightColor0; 
             // color of light source (from "Lighting.cginc")
         struct vertexInput {
            float4 vertex : POSITION;
            float3 normal : NORMAL;
            float4 texcoord : TEXCOORD0;
         };
         struct vertexOutput {
            float4 pos : SV_POSITION;
            float4 col : COLOR;
            float4 tex : TEXCOORD0;
         };

         vertexOutput vert(vertexInput input) 
         {
            vertexOutput output;

            float4x4 modelMatrix = _Object2World;
            float4x4 modelMatrixInverse = _World2Object; 

            float3 normalDirection = normalize(float3(mul(_Normal, modelMatrixInverse)));
            float3 lightDirection = normalize(float3(_WorldSpaceLightPos0));

            float3 diffuseReflection = float3(_LightColor0) * float3(_Color)
               * max(0.0, dot(normalDirection, lightDirection));

            output.col = float4(diffuseReflection, 1.0);
            output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
            output.tex = input.texcoord;
            return output;
         }

         float4 frag(vertexOutput input) : COLOR
         {
            half4 color = tex2D(_MainTex, float2(input.tex));
            // use color.a to get alpha from text texture, rgb comes from vertex shader                        
            return float4(input.col.r,input.col.g,input.col.b,color.a);
         }

         ENDCG
    }
}
}
like image 174
Jerdak Avatar answered Oct 06 '22 00:10

Jerdak