Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We are updating our Terms of Service for all Unity subscription plans, effective October 13, 2022, to create a more streamlined, user-friendly set of terms. Please review them here: unity.com/legal/terms-of-service.
    Dismiss Notice
  3. Have a look at our Games Focus blog post series which will show what Unity is doing for all game developers – now, next year, and in the future.
    Dismiss Notice
  4. Join us on Thursday, September 29, for a day with Unity's SRP teams here on the forum or on Reddit, and discuss topics around URP, HDRP, and the Scriptable Render Pipeline in general.
    Dismiss Notice

Text background color on some letters

Discussion in 'UGUI & TextMesh Pro' started by Boi, Feb 3, 2017.

  1. Boi

    Boi

    Joined:
    Apr 10, 2010
    Posts:
    65
    Hi,

    I have a Text(Script) component the following text:
    "My name is <b>Boi</b>."
    With the Rich Text checkbox turned on, it looks like:
    "My name is Boi."
    So far so good. Now I would like to change the background color the letters in my name (Boi), let's say to yellow. Unfortunatelly the Rich Text doesn't support a background color tag. Only color tag. So how would one go about this? I can not just manually put an image with a yellow texture behind the text, because I would like a more generic system. I have a lot of sentences with some words bold. I would like only those words to have a yellow background. Also those backgrounds need to follow the words when them move around the screen (for instance in a responsive environment).

    Thanks for any usefull tips.

    Regards,

    Boi
     
  2. SimonDarksideJ

    SimonDarksideJ

    Joined:
    Jul 3, 2012
    Posts:
    1,671
    You can't change the background color of text through the Rich Text XML format. If you want to change the background color, you have to change the color of the text container.

    hope that helps.
     
  3. Stephan-B

    Stephan-B

    Unity Technologies

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Are you looking for something like the <mark> tag in TextMesh Pro?



    As per the link above, the <mark> tag format is <mark=#FF00FF80> which includes color and alpha. These tags can be nested as well.

    I realize that TextMesh Pro is not free but I wanted to make sure you were aware of said functionality just in case you can't find any alternatives to suit your needs.
     
    art092 and Marwa1234 like this.
  4. Boi

    Boi

    Joined:
    Apr 10, 2010
    Posts:
    65

    Thank you for your answer. Unfortunately, I want to highlight some words. Not all of them.
     
  5. Boi

    Boi

    Joined:
    Apr 10, 2010
    Posts:
    65
    @Stephan-B, I am aware of the TextMeshPro asset. Thanks anyway.
     
  6. Boi

    Boi

    Joined:
    Apr 10, 2010
    Posts:
    65
    @Stephan-B, also TextMeshPro seems to overlay a rect with color. I want the rect to be behind the text.
     
    CGDever and MilenaRocha like this.
  7. Stephan-B

    Stephan-B

    Unity Technologies

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Since the geometry of the highlight is part of the text's geometry and added into the vertices array after the text, it renders over the text.

    You can control the transparency of the highlight by using alpha such as <mark=#FFFF0080> or you can actually get the text to be rendered over the highlight by using the font tag which results in the text being part of a sub text object which renders over the highlight.

    For instance, let's assume your text object has the BANGERS SDF font asset assigned to it. Using the following <font="NotoSans SDF">This <mark=#FF8000>text is highlighted</mark>."



    Basically, assign a font asset you are not planning on using in this text and immediately switch to the font asset you are planning to use using the <font> tag.

    P.S. I am currently exploring some alternative ways to handles this as although it works fine, I am not thrilled with having to use this workaround when looking for fully opaque highlight. I also want to provide the ability to add padding on the highlight as well.
     
    MilenaRocha likes this.
  8. Boi

    Boi

    Joined:
    Apr 10, 2010
    Posts:
    65

    Interesting...
    one more question: will the tag be able to be visible over multiple lines? For instance this string:

    "Hello, my name is Boi. Nice to meet you. What is your name?"
    I want to make some words bold and highlight their background orange (like in your example). Th string would look like this:
    "Hello, my name is Boi. <b>Nice to meet you.</b> What is your name?"
    Now here comes the tricky part: I want that string in a Unity UI Textbox like this:
    "Hello, my name is Boi. Nice to
    meet you.
    What is your name?"
    BUT the "Nice to meet you." part highlighted as well. So in fact 2 orange rectangles, but only 1 mark tag (well 2, 1 for opening and one for closing.
     
  9. Stephan-B

    Stephan-B

    Unity Technologies

    Joined:
    Feb 23, 2011
    Posts:
    2,269
    Short answer: Yes



    Just like Underline and Strikethrough which can span multiple lines, the <mark> tag is no different where all of this is handled automatically behind the scene.

    This is the raw text in the Text Input Box
    <font="NotoSans SDF">This <mark=#FF8000>text is <b>high\u00adlighted</b> <sprite="Sprite Icons" index=7></mark>.

    P.S. The hyphenation is done by using a soft hyphen (\u00AD) in the text or "high\u00ADlighted"

    P.S.S. I even added a sprite inline for good measure. "Sprite Icons" refers to the Sprite Asset. index=7 or name="Heart" references the specific sprite in the TMP Sprite Asset.
     
    Last edited: Feb 8, 2017
    pmelo and MilenaRocha like this.
  10. Anflo

    Anflo

    Joined:
    Dec 3, 2014
    Posts:
    17
    Sorry but where do you get the value "<font="NotoSans SDF">" what if I have my own font created?
     
  11. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,523
    The NotoSans SDF is just a font asset that I created from the NotoSans.otf font using the Font Asset Creator in TextMesh Pro.

    This <font="Font Asset Name"> is the font tag itself that allows to use multiple fonts per text object. See the font tag information here.
     
  12. clever

    clever

    Joined:
    Oct 11, 2012
    Posts:
    37
    I wonder, did you find a better way than the workaround? because if the text starts with the highlighted part it doesn't work
     
  13. Hubi_C

    Hubi_C

    Joined:
    Mar 14, 2018
    Posts:
    11
    I'm also interested in an alternative solution. Are there any updates regarding this issue?
     
    CGDever likes this.
  14. Antoniusaft

    Antoniusaft

    Joined:
    Feb 28, 2013
    Posts:
    9
    I second that
     
    CGDever likes this.
  15. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,523
    This is something that I plan on revisiting but simply haven't had a chance yet... and thank you for the remainder.

    P.S. Besides sorting control, the ability to also control the padding of the highlight region is also on the list. Ability to use a sprite with even 9 slice has also been requested. All stuff I plan on adding if I can get there.
     
    MilenaRocha and Shiver like this.
  16. Tknoguyfication

    Tknoguyfication

    Joined:
    Nov 11, 2013
    Posts:
    3
    Right now I'm trying to replicate this highlighting effect that Minecraft uses. It's an underneath highlight that spans the entire line that text appears in. Is this possible?

     
  17. Dobryakov

    Dobryakov

    Joined:
    Jan 25, 2017
    Posts:
    3
    Снимок экрана 2020-06-13 в 15.42.15.png Снимок экрана 2020-06-13 в 15.42.23.png
    This solution doesn't work now. Unity 2019.2.17f1, TMPro 2.0.1
     
  18. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,523
    Using <font="Default"> means that it is using the same primary font where as such the mark geometry would be after the characters which is why it is on top of the characters. You have to assign some other font asset as primary and then use <font="Some other font asset"> to ensure the characters from this other font are rendered on top.

    P.S. When I have time, I will revised this so that Underline and Mark geometry are first.
     
    MilenaRocha and Ghetaldus like this.
  19. gaglabs

    gaglabs

    Joined:
    Oct 17, 2019
    Posts:
    185
    Im getting an error that ; is expected but its already defined.


    s = s.Substring(0, 3);
    TextBody.text = s += "<font="Bariol"><mark=#ffff8000><b>...</b></mark>";
     
  20. redfallenstar

    redfallenstar

    Joined:
    Feb 9, 2019
    Posts:
    10
    This doesn't work with custom font too.
    Без названия.png
     
  21. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    162
    Any update on this? I'm also trying to get the highlight to not show up on top of the text and using the <font> trick don't work.

    <font="Caveat SDF">The patterned walls are made from <mark="#F8C100EE">layers of petrified Navajo sandstone</mark> which date back to the Jurassic period.



    I'm using TextMeshPro 3.0.3 and URP 10
     
    Last edited: Jan 4, 2021
    CGDever and Mjeno like this.
  22. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    162
    Anybody here?
     
    CGDever and Mjeno like this.
  23. Mjeno

    Mjeno

    Joined:
    Apr 7, 2016
    Posts:
    5
    I would also be very interested in a less hacky solution to this. It seems like a fairly basic feature compared to some other things TMP can already do. Just adding my reply in the hopes that it's coming soon. Not holding my breath, though... Threads about this go back more than three years.
     
    CGDever, MilenaRocha and GameDevMig like this.
  24. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,523
    I am reading this posts / threads and addressing this sorting issue which affects underline, strikethrough and mark is on my shorter term list of stuff to address.
     
  25. GameDevMig

    GameDevMig

    Joined:
    Nov 5, 2014
    Posts:
    18
    Thanks, being able to give the text is a flat background color is something I need too
    (Appreciate all your efforts!)
     
  26. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    162
    I found a hacky way to make the highlight appear behind the text. It'll cost an extra draw call but at least looks good.

    Simply replace your TextMeshPro component by this one :)

    Code (CSharp):
    1. using System;
    2. using System;
    3. using TMPro;
    4. using UnityEngine;
    5. using UnityEngine.TextCore;
    6.  
    7. public class TextMeshProHighlightHack : TextMeshPro
    8. {
    9.     private Vector3[] Vertices;
    10.     private Vector2[] UVs;
    11.     private Color32[] Colors32;
    12.     private int[] Triangles;
    13.  
    14.     private MeshFilter HighlightMeshFiter;
    15.  
    16.     protected override void GenerateTextMesh()
    17.     {
    18.         Vertices = new Vector3[0];
    19.         UVs = new Vector2[0];
    20.         Colors32 = new Color32[0];
    21.         Triangles = new int[0];
    22.    
    23.         base.GenerateTextMesh();
    24.  
    25.         var m = new Mesh
    26.         {
    27.             vertices = Vertices,
    28.             uv = UVs,
    29.             colors32 = Colors32,
    30.             triangles = Triangles
    31.         };
    32.  
    33.         if (HighlightMeshFiter == null)
    34.         {
    35.             MeshRenderer mr;
    36.             Transform highlightTransform = transform.Find("Highlight");
    37.        
    38.             if (highlightTransform == null)
    39.             {
    40.                 var go = new GameObject("Highlight") {hideFlags = HideFlags.DontSave};
    41.                 go.transform.SetParent(transform, false);
    42.                 HighlightMeshFiter = go.AddComponent<MeshFilter>();
    43.                 mr = go.AddComponent<MeshRenderer>();
    44.             }
    45.             else
    46.             {
    47.                 HighlightMeshFiter = highlightTransform.gameObject.GetComponent<MeshFilter>();
    48.                 mr = highlightTransform.gameObject.GetComponent<MeshRenderer>();
    49.             }
    50.        
    51.             // In order to support the 'color' attribute (ex: <mark color=#RRGGBBAA>)
    52.             // you might want to use a Shader using vertex colors here
    53.             mr.material = new Material(Shader.Find("Unlit/Color"));
    54.         }
    55.  
    56.         HighlightMeshFiter.mesh = m;
    57.     }
    58.  
    59.    protected override void DrawTextHighlight(Vector3 start, Vector3 end, ref int index, Color32 highlightColor)
    60.     {
    61.         start += new Vector3(-.3f, .2f, .1f);
    62.         end += new Vector3(.3f, -.4f, .1f);
    63.        
    64.         Array.Resize(ref Vertices, Vertices.Length + 4);
    65.         Array.Resize(ref UVs, UVs.Length + 4);
    66.         Array.Resize(ref Colors32, Colors32.Length + 4);
    67.         Array.Resize(ref Triangles, Triangles.Length + 6);
    68.  
    69.         int vertIndex = Vertices.Length - 4;
    70.  
    71.         // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
    72.         #region HIGHLIGHT VERTICES
    73.         Vector3[] vertices = Vertices;
    74.  
    75.         // Front Part of the Underline
    76.         vertices[vertIndex + 0] = start; // BL
    77.         vertices[vertIndex + 1] = new Vector3(start.x, end.y, start.z); // TL
    78.         vertices[vertIndex + 2] = end; // TR
    79.         vertices[vertIndex + 3] = new Vector3(end.x, start.y, end.z); // BR
    80.         #endregion
    81.  
    82.         // UNDERLINE UV0
    83.         #region HANDLE UV0
    84.         Vector2[] uvs0 = UVs;
    85.  
    86.         // UVs for the Quad
    87.         uvs0[0 + vertIndex] = new Vector2(0.01f, 0.01f); // BL
    88.         uvs0[1 + vertIndex] = new Vector2(0.01f, .99f); // TL
    89.         uvs0[2 + vertIndex] = new Vector2(.99f, .99f); // TR
    90.         uvs0[3 + vertIndex] = new Vector2(.99f, 0.01f); // BR
    91.         #endregion
    92.  
    93.         // HIGHLIGHT VERTEX COLORS
    94.         #region
    95.         // Alpha is the lower of the vertex color or tag color alpha used.
    96.         highlightColor.a = m_fontColor32.a < highlightColor.a ? m_fontColor32.a : highlightColor.a;
    97.  
    98.         Color32[] colors32 = Colors32;
    99.         colors32[0 + vertIndex] = highlightColor;
    100.         colors32[1 + vertIndex] = highlightColor;
    101.         colors32[2 + vertIndex] = highlightColor;
    102.         colors32[3 + vertIndex] = highlightColor;
    103.         #endregion
    104.        
    105.         Array.Resize(ref Triangles, Triangles.Length + 6);
    106.  
    107.         Triangles = new int[6 * Vertices.Length / 4];
    108.  
    109.         int index_X6 = 0;
    110.         int index_X4 = 0;
    111.         while (index_X4 / 4 < Vertices.Length / 4)
    112.         {
    113.             Triangles[index_X6 + 0] = index_X4 + 0;
    114.             Triangles[index_X6 + 1] = index_X4 + 1;
    115.             Triangles[index_X6 + 2] = index_X4 + 2;
    116.             Triangles[index_X6 + 3] = index_X4 + 2;
    117.             Triangles[index_X6 + 4] = index_X4 + 3;
    118.             Triangles[index_X6 + 5] = index_X4 + 0;
    119.  
    120.             index_X4 += 4;
    121.             index_X6 += 6;
    122.         }
    123.     }
    124. }
    125.  
    126.  
     
    Last edited: Jan 27, 2021
    CGDever likes this.
  27. Davon92

    Davon92

    Joined:
    Oct 24, 2014
    Posts:
    12
    Damn I wasn't expecting to see this still in the works in 2021.

    I'm looking to use a more unorthodox method for work and am hoping that there might be some solution that someone has tried.

    I am using TextMeshProUGUI and have some highlight boxes that I would like to position and size the same as either individual words, a grouping of words, if not some specific text lines.

    Since the highlight boxes are rect's with images with some nice round corners if like to keep them as I don't see a way to round out or even change the visuals of the highlight to something other than solid color.

    I am having major trouble with getting the position and converting the text mesh info to something i can convert for the highlight box rect.

    Is there anyone who has accomplished this or something similar?

    this would help a ton.
     
    Braza likes this.
  28. Braza

    Braza

    Joined:
    Oct 11, 2013
    Posts:
    118
    Unfortunately, it did not work for me. It resulted in a very small text of white color and red outline.
    I'd appreciate a native solution for this too.
     
    CGDever likes this.
  29. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    162
    Code (CSharp):
    1. using System;
    2. using TMPro;
    3. using UnityEngine;
    4.  
    5. public class TextMeshProHighlight : TextMeshPro
    6. {
    7.     private Vector3[] Vertices;
    8.     private Vector2[] UVs;
    9.     private Color32[] Colors32;
    10.     private int[] Triangles;
    11.  
    12.     private MeshFilter HighlightMeshFiter;
    13.  
    14.     protected override void OnDisable()
    15.     {
    16.         base.OnDisable();
    17.  
    18.         if (HighlightMeshFiter != null)
    19.             HighlightMeshFiter.gameObject.SetActive(false);
    20.     }
    21.  
    22.     protected override void GenerateTextMesh()
    23.     {
    24.         Vertices = new Vector3[0];
    25.         UVs = new Vector2[0];
    26.         Colors32 = new Color32[0];
    27.         Triangles = new int[0];
    28.      
    29.         base.GenerateTextMesh();
    30.  
    31.         var m = new Mesh
    32.         {
    33.             vertices = Vertices,
    34.             uv = UVs,
    35.             colors32 = Colors32,
    36.             triangles = Triangles
    37.         };
    38.  
    39.         if (HighlightMeshFiter == null)
    40.         {
    41.             MeshRenderer mr;
    42.             Transform highlightTransform = transform.Find("Highlight");
    43.          
    44.             if (highlightTransform == null)
    45.             {
    46.                 var go = new GameObject("Highlight") {hideFlags = HideFlags.DontSave};
    47.                 go.transform.SetParent(transform, false);
    48.                 go.layer = LayerMask.NameToLayer("MenuRenderer");
    49.                 HighlightMeshFiter = go.AddComponent<MeshFilter>();
    50.                 mr = go.AddComponent<MeshRenderer>();
    51.             }
    52.             else
    53.             {
    54.                 HighlightMeshFiter = highlightTransform.gameObject.GetComponent<MeshFilter>();
    55.                 mr = highlightTransform.gameObject.GetComponent<MeshRenderer>();
    56.             }
    57.  
    58.             mr.material = new Material(Shader.Find("UI/TextMeshPro/Highlight"))
    59.             {
    60.                 mainTexture = Resources.Load<Texture>("Textures/TextHighlight"),
    61.                 renderQueue = 4001
    62.             };
    63.         }
    64.      
    65.         HighlightMeshFiter.gameObject.SetActive(true);
    66.         HighlightMeshFiter.mesh = m;
    67.     }
    68.  
    69.     protected override void DrawTextHighlight(Vector3 start, Vector3 end, ref int index, Color32 highlightColor)
    70.     {
    71.         start += new Vector3(-.3f, .2f, .1f);
    72.         end += new Vector3(.3f, -.4f, .1f);
    73.      
    74.         Array.Resize(ref Vertices, Vertices.Length + 4);
    75.         Array.Resize(ref UVs, UVs.Length + 4);
    76.         Array.Resize(ref Colors32, Colors32.Length + 4);
    77.         Array.Resize(ref Triangles, Triangles.Length + 6);
    78.  
    79.         int vertIndex = Vertices.Length - 4;
    80.  
    81.         // UNDERLINE VERTICES FOR (3) LINE SEGMENTS
    82.         #region HIGHLIGHT VERTICES
    83.         Vector3[] vertices = Vertices;
    84.  
    85.         // Front Part of the Underline
    86.         vertices[vertIndex + 0] = start; // BL
    87.         vertices[vertIndex + 1] = new Vector3(start.x, end.y, start.z); // TL
    88.         vertices[vertIndex + 2] = end; // TR
    89.         vertices[vertIndex + 3] = new Vector3(end.x, start.y, end.z); // BR
    90.         #endregion
    91.  
    92.         // UNDERLINE UV0
    93.         #region HANDLE UV0
    94.         Vector2[] uvs0 = UVs;
    95.  
    96.         // UVs for the Quad
    97.         uvs0[0 + vertIndex] = new Vector2(0.01f, 0.01f); // BL
    98.         uvs0[1 + vertIndex] = new Vector2(0.01f, .99f); // TL
    99.         uvs0[2 + vertIndex] = new Vector2(.99f, .99f); // TR
    100.         uvs0[3 + vertIndex] = new Vector2(.99f, 0.01f); // BR
    101.         #endregion
    102.  
    103.         // HIGHLIGHT VERTEX COLORS
    104.         #region
    105.         // Alpha is the lower of the vertex color or tag color alpha used.
    106.         highlightColor.a = m_fontColor32.a < highlightColor.a ? m_fontColor32.a : highlightColor.a;
    107.  
    108.         Color32[] colors32 = Colors32;
    109.         colors32[0 + vertIndex] = highlightColor;
    110.         colors32[1 + vertIndex] = highlightColor;
    111.         colors32[2 + vertIndex] = highlightColor;
    112.         colors32[3 + vertIndex] = highlightColor;
    113.         #endregion
    114.      
    115.         Array.Resize(ref Triangles, Triangles.Length + 6);
    116.  
    117.         Triangles = new int[6 * Vertices.Length / 4];
    118.  
    119.         int index_X6 = 0;
    120.         int index_X4 = 0;
    121.         while (index_X4 / 4 < Vertices.Length / 4)
    122.         {
    123.             Triangles[index_X6 + 0] = index_X4 + 0;
    124.             Triangles[index_X6 + 1] = index_X4 + 1;
    125.             Triangles[index_X6 + 2] = index_X4 + 2;
    126.             Triangles[index_X6 + 3] = index_X4 + 2;
    127.             Triangles[index_X6 + 4] = index_X4 + 3;
    128.             Triangles[index_X6 + 5] = index_X4 + 0;
    129.  
    130.             index_X4 += 4;
    131.             index_X6 += 6;
    132.         }
    133.     }
    134.  
    135.     protected override void FillCharacterVertexBuffers(int i, int index_X4)
    136.     {
    137.         int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
    138.      
    139.         // TODO: this IF is a workaround to prevent a 'index out of bounds' when changing
    140.         // text opacity with a sprite
    141.      
    142.         if (materialIndex <= m_textInfo.meshInfo.Length - 1)
    143.         {
    144.             index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
    145.  
    146.             // Check to make sure our current mesh buffer allocations can hold these new Quads.
    147.             if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length)
    148.                 m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4));
    149.  
    150.             TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
    151.             m_textInfo.characterInfo[i].vertexIndex = index_X4;
    152.  
    153.             // Setup Vertices for Characters
    154.             m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
    155.             m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
    156.             m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
    157.             m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
    158.  
    159.  
    160.             // Setup UVS0
    161.             m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
    162.             m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
    163.             m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
    164.             m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
    165.  
    166.  
    167.             // Setup UVS2
    168.             m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
    169.             m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
    170.             m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
    171.             m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
    172.  
    173.  
    174.             // setup Vertex Colors
    175.             m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
    176.             m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
    177.             m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
    178.             m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
    179.  
    180.             m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
    181.         }
    182.     }
    183.  
    184.     protected override void FillSpriteVertexBuffers(int i, int index_X4)
    185.     {
    186.         int materialIndex = m_textInfo.characterInfo[i].materialReferenceIndex;
    187.      
    188.         // TODO: this IF is a workaround to prevent a 'index out of bounds' when changing
    189.         // text opacity with a sprite
    190.      
    191.         if (materialIndex <= m_textInfo.meshInfo.Length - 1)
    192.         {
    193.             index_X4 = m_textInfo.meshInfo[materialIndex].vertexCount;
    194.  
    195.             // Check to make sure our current mesh buffer allocations can hold these new Quads.
    196.             if (index_X4 >= m_textInfo.meshInfo[materialIndex].vertices.Length)
    197.                 m_textInfo.meshInfo[materialIndex].ResizeMeshInfo(Mathf.NextPowerOfTwo((index_X4 + 4) / 4));
    198.  
    199.             TMP_CharacterInfo[] characterInfoArray = m_textInfo.characterInfo;
    200.             m_textInfo.characterInfo[i].vertexIndex = index_X4;
    201.  
    202.             // Setup Vertices for Characters
    203.             m_textInfo.meshInfo[materialIndex].vertices[0 + index_X4] = characterInfoArray[i].vertex_BL.position;
    204.             m_textInfo.meshInfo[materialIndex].vertices[1 + index_X4] = characterInfoArray[i].vertex_TL.position;
    205.             m_textInfo.meshInfo[materialIndex].vertices[2 + index_X4] = characterInfoArray[i].vertex_TR.position;
    206.             m_textInfo.meshInfo[materialIndex].vertices[3 + index_X4] = characterInfoArray[i].vertex_BR.position;
    207.  
    208.  
    209.             // Setup UVS0
    210.             m_textInfo.meshInfo[materialIndex].uvs0[0 + index_X4] = characterInfoArray[i].vertex_BL.uv;
    211.             m_textInfo.meshInfo[materialIndex].uvs0[1 + index_X4] = characterInfoArray[i].vertex_TL.uv;
    212.             m_textInfo.meshInfo[materialIndex].uvs0[2 + index_X4] = characterInfoArray[i].vertex_TR.uv;
    213.             m_textInfo.meshInfo[materialIndex].uvs0[3 + index_X4] = characterInfoArray[i].vertex_BR.uv;
    214.  
    215.  
    216.             // Setup UVS2
    217.             m_textInfo.meshInfo[materialIndex].uvs2[0 + index_X4] = characterInfoArray[i].vertex_BL.uv2;
    218.             m_textInfo.meshInfo[materialIndex].uvs2[1 + index_X4] = characterInfoArray[i].vertex_TL.uv2;
    219.             m_textInfo.meshInfo[materialIndex].uvs2[2 + index_X4] = characterInfoArray[i].vertex_TR.uv2;
    220.             m_textInfo.meshInfo[materialIndex].uvs2[3 + index_X4] = characterInfoArray[i].vertex_BR.uv2;
    221.  
    222.  
    223.             // setup Vertex Colors
    224.             m_textInfo.meshInfo[materialIndex].colors32[0 + index_X4] = characterInfoArray[i].vertex_BL.color;
    225.             m_textInfo.meshInfo[materialIndex].colors32[1 + index_X4] = characterInfoArray[i].vertex_TL.color;
    226.             m_textInfo.meshInfo[materialIndex].colors32[2 + index_X4] = characterInfoArray[i].vertex_TR.color;
    227.             m_textInfo.meshInfo[materialIndex].colors32[3 + index_X4] = characterInfoArray[i].vertex_BR.color;
    228.  
    229.             m_textInfo.meshInfo[materialIndex].vertexCount = index_X4 + 4;
    230.         }
    231.     }
    232. }
    233.  
    Try that. That might work.
     
    Last edited: Sep 10, 2021
  30. FlorianBernard

    FlorianBernard

    Joined:
    Jun 9, 2015
    Posts:
    162
    oh and here is the shader (amplify)

    Code (CSharp):
    1. // Made with Amplify Shader Editor
    2. // Available at the Unity Asset Store - http://u3d.as/y3X
    3. Shader "UI/TextMeshPro/Highlight"
    4. {
    5.     Properties
    6.     {
    7.         [HideInInspector] _AlphaCutoff("Alpha Cutoff ", Range(0, 1)) = 0.5
    8.         [HideInInspector] _EmissionColor("Emission Color", Color) = (1,1,1,1)
    9.         [ASEEnd][ASEBegin]_MainTex("MainTex", 2D) = "white" {}
    10.         [HideInInspector] _texcoord( "", 2D ) = "white" {}
    11.  
    12.         //_TessPhongStrength( "Tess Phong Strength", Range( 0, 1 ) ) = 0.5
    13.         //_TessValue( "Tess Max Tessellation", Range( 1, 32 ) ) = 16
    14.         //_TessMin( "Tess Min Distance", Float ) = 10
    15.         //_TessMax( "Tess Max Distance", Float ) = 25
    16.         //_TessEdgeLength ( "Tess Edge length", Range( 2, 50 ) ) = 16
    17.         //_TessMaxDisp( "Tess Max Displacement", Float ) = 25
    18.     }
    19.  
    20.     SubShader
    21.     {
    22.         LOD 0
    23.  
    24.        
    25.         Tags { "RenderPipeline"="UniversalPipeline" "RenderType"="Transparent" "Queue"="Transparent" }
    26.        
    27.         Cull Back
    28.         AlphaToMask Off
    29.         HLSLINCLUDE
    30.         #pragma target 2.0
    31.  
    32.         float4 FixedTess( float tessValue )
    33.         {
    34.             return tessValue;
    35.         }
    36.        
    37.         float CalcDistanceTessFactor (float4 vertex, float minDist, float maxDist, float tess, float4x4 o2w, float3 cameraPos )
    38.         {
    39.             float3 wpos = mul(o2w,vertex).xyz;
    40.             float dist = distance (wpos, cameraPos);
    41.             float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0) * tess;
    42.             return f;
    43.         }
    44.  
    45.         float4 CalcTriEdgeTessFactors (float3 triVertexFactors)
    46.         {
    47.             float4 tess;
    48.             tess.x = 0.5 * (triVertexFactors.y + triVertexFactors.z);
    49.             tess.y = 0.5 * (triVertexFactors.x + triVertexFactors.z);
    50.             tess.z = 0.5 * (triVertexFactors.x + triVertexFactors.y);
    51.             tess.w = (triVertexFactors.x + triVertexFactors.y + triVertexFactors.z) / 3.0f;
    52.             return tess;
    53.         }
    54.  
    55.         float CalcEdgeTessFactor (float3 wpos0, float3 wpos1, float edgeLen, float3 cameraPos, float4 scParams )
    56.         {
    57.             float dist = distance (0.5 * (wpos0+wpos1), cameraPos);
    58.             float len = distance(wpos0, wpos1);
    59.             float f = max(len * scParams.y / (edgeLen * dist), 1.0);
    60.             return f;
    61.         }
    62.  
    63.         float DistanceFromPlane (float3 pos, float4 plane)
    64.         {
    65.             float d = dot (float4(pos,1.0f), plane);
    66.             return d;
    67.         }
    68.  
    69.         bool WorldViewFrustumCull (float3 wpos0, float3 wpos1, float3 wpos2, float cullEps, float4 planes[6] )
    70.         {
    71.             float4 planeTest;
    72.             planeTest.x = (( DistanceFromPlane(wpos0, planes[0]) > -cullEps) ? 1.0f : 0.0f ) +
    73.                           (( DistanceFromPlane(wpos1, planes[0]) > -cullEps) ? 1.0f : 0.0f ) +
    74.                           (( DistanceFromPlane(wpos2, planes[0]) > -cullEps) ? 1.0f : 0.0f );
    75.             planeTest.y = (( DistanceFromPlane(wpos0, planes[1]) > -cullEps) ? 1.0f : 0.0f ) +
    76.                           (( DistanceFromPlane(wpos1, planes[1]) > -cullEps) ? 1.0f : 0.0f ) +
    77.                           (( DistanceFromPlane(wpos2, planes[1]) > -cullEps) ? 1.0f : 0.0f );
    78.             planeTest.z = (( DistanceFromPlane(wpos0, planes[2]) > -cullEps) ? 1.0f : 0.0f ) +
    79.                           (( DistanceFromPlane(wpos1, planes[2]) > -cullEps) ? 1.0f : 0.0f ) +
    80.                           (( DistanceFromPlane(wpos2, planes[2]) > -cullEps) ? 1.0f : 0.0f );
    81.             planeTest.w = (( DistanceFromPlane(wpos0, planes[3]) > -cullEps) ? 1.0f : 0.0f ) +
    82.                           (( DistanceFromPlane(wpos1, planes[3]) > -cullEps) ? 1.0f : 0.0f ) +
    83.                           (( DistanceFromPlane(wpos2, planes[3]) > -cullEps) ? 1.0f : 0.0f );
    84.             return !all (planeTest);
    85.         }
    86.  
    87.         float4 DistanceBasedTess( float4 v0, float4 v1, float4 v2, float tess, float minDist, float maxDist, float4x4 o2w, float3 cameraPos )
    88.         {
    89.             float3 f;
    90.             f.x = CalcDistanceTessFactor (v0,minDist,maxDist,tess,o2w,cameraPos);
    91.             f.y = CalcDistanceTessFactor (v1,minDist,maxDist,tess,o2w,cameraPos);
    92.             f.z = CalcDistanceTessFactor (v2,minDist,maxDist,tess,o2w,cameraPos);
    93.  
    94.             return CalcTriEdgeTessFactors (f);
    95.         }
    96.  
    97.         float4 EdgeLengthBasedTess( float4 v0, float4 v1, float4 v2, float edgeLength, float4x4 o2w, float3 cameraPos, float4 scParams )
    98.         {
    99.             float3 pos0 = mul(o2w,v0).xyz;
    100.             float3 pos1 = mul(o2w,v1).xyz;
    101.             float3 pos2 = mul(o2w,v2).xyz;
    102.             float4 tess;
    103.             tess.x = CalcEdgeTessFactor (pos1, pos2, edgeLength, cameraPos, scParams);
    104.             tess.y = CalcEdgeTessFactor (pos2, pos0, edgeLength, cameraPos, scParams);
    105.             tess.z = CalcEdgeTessFactor (pos0, pos1, edgeLength, cameraPos, scParams);
    106.             tess.w = (tess.x + tess.y + tess.z) / 3.0f;
    107.             return tess;
    108.         }
    109.  
    110.         float4 EdgeLengthBasedTessCull( float4 v0, float4 v1, float4 v2, float edgeLength, float maxDisplacement, float4x4 o2w, float3 cameraPos, float4 scParams, float4 planes[6] )
    111.         {
    112.             float3 pos0 = mul(o2w,v0).xyz;
    113.             float3 pos1 = mul(o2w,v1).xyz;
    114.             float3 pos2 = mul(o2w,v2).xyz;
    115.             float4 tess;
    116.  
    117.             if (WorldViewFrustumCull(pos0, pos1, pos2, maxDisplacement, planes))
    118.             {
    119.                 tess = 0.0f;
    120.             }
    121.             else
    122.             {
    123.                 tess.x = CalcEdgeTessFactor (pos1, pos2, edgeLength, cameraPos, scParams);
    124.                 tess.y = CalcEdgeTessFactor (pos2, pos0, edgeLength, cameraPos, scParams);
    125.                 tess.z = CalcEdgeTessFactor (pos0, pos1, edgeLength, cameraPos, scParams);
    126.                 tess.w = (tess.x + tess.y + tess.z) / 3.0f;
    127.             }
    128.             return tess;
    129.         }
    130.         ENDHLSL
    131.  
    132.        
    133.         Pass
    134.         {
    135.            
    136.             Name "Forward"
    137.             Tags { "LightMode"="UniversalForward" }
    138.            
    139.             Blend SrcAlpha OneMinusSrcAlpha, One OneMinusSrcAlpha
    140.             ZWrite Off
    141.             ZTest LEqual
    142.             Offset 0 , 0
    143.             ColorMask RGBA
    144.            
    145.  
    146.             HLSLPROGRAM
    147.             #define _RECEIVE_SHADOWS_OFF 1
    148.             #pragma multi_compile_instancing
    149.             #define ASE_SRP_VERSION 999999
    150.  
    151.             #pragma prefer_hlslcc gles
    152.             #pragma exclude_renderers d3d11_9x
    153.  
    154.             #pragma vertex vert
    155.             #pragma fragment frag
    156.  
    157.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    158.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    159.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    160.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"
    161.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
    162.  
    163.             #if ASE_SRP_VERSION <= 70108
    164.             #define REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
    165.             #endif
    166.  
    167.             #define ASE_NEEDS_FRAG_COLOR
    168.  
    169.  
    170.             struct VertexInput
    171.             {
    172.                 float4 vertex : POSITION;
    173.                 float3 ase_normal : NORMAL;
    174.                 float4 ase_texcoord : TEXCOORD0;
    175.                 half4 ase_color : COLOR;
    176.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    177.             };
    178.  
    179.             struct VertexOutput
    180.             {
    181.                 float4 clipPos : SV_POSITION;
    182.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    183.                 float3 worldPos : TEXCOORD0;
    184.                 #endif
    185.                 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    186.                 float4 shadowCoord : TEXCOORD1;
    187.                 #endif
    188.                 #ifdef ASE_FOG
    189.                 float fogFactor : TEXCOORD2;
    190.                 #endif
    191.                 float4 ase_texcoord3 : TEXCOORD3;
    192.                 float4 ase_color : COLOR;
    193.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    194.                 UNITY_VERTEX_OUTPUT_STEREO
    195.             };
    196.  
    197.             CBUFFER_START(UnityPerMaterial)
    198.             half4 _MainTex_ST;
    199.             #ifdef TESSELLATION_ON
    200.                 float _TessPhongStrength;
    201.                 float _TessValue;
    202.                 float _TessMin;
    203.                 float _TessMax;
    204.                 float _TessEdgeLength;
    205.                 float _TessMaxDisp;
    206.             #endif
    207.             CBUFFER_END
    208.             sampler2D _MainTex;
    209.  
    210.  
    211.                        
    212.             VertexOutput VertexFunction ( VertexInput v  )
    213.             {
    214.                 VertexOutput o = (VertexOutput)0;
    215.                 UNITY_SETUP_INSTANCE_ID(v);
    216.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    217.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    218.  
    219.                 o.ase_texcoord3.xy = v.ase_texcoord.xy;
    220.                 o.ase_color = v.ase_color;
    221.                
    222.                 //setting value to unused interpolator channels and avoid initialization warnings
    223.                 o.ase_texcoord3.zw = 0;
    224.                 #ifdef ASE_ABSOLUTE_VERTEX_POS
    225.                     float3 defaultVertexValue = v.vertex.xyz;
    226.                 #else
    227.                     float3 defaultVertexValue = float3(0, 0, 0);
    228.                 #endif
    229.                 float3 vertexValue = defaultVertexValue;
    230.                 #ifdef ASE_ABSOLUTE_VERTEX_POS
    231.                     v.vertex.xyz = vertexValue;
    232.                 #else
    233.                     v.vertex.xyz += vertexValue;
    234.                 #endif
    235.                 v.ase_normal = v.ase_normal;
    236.  
    237.                 float3 positionWS = TransformObjectToWorld( v.vertex.xyz );
    238.                 float4 positionCS = TransformWorldToHClip( positionWS );
    239.  
    240.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    241.                 o.worldPos = positionWS;
    242.                 #endif
    243.                 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    244.                 VertexPositionInputs vertexInput = (VertexPositionInputs)0;
    245.                 vertexInput.positionWS = positionWS;
    246.                 vertexInput.positionCS = positionCS;
    247.                 o.shadowCoord = GetShadowCoord( vertexInput );
    248.                 #endif
    249.                 #ifdef ASE_FOG
    250.                 o.fogFactor = ComputeFogFactor( positionCS.z );
    251.                 #endif
    252.                 o.clipPos = positionCS;
    253.                 return o;
    254.             }
    255.  
    256.             #if defined(TESSELLATION_ON)
    257.             struct VertexControl
    258.             {
    259.                 float4 vertex : INTERNALTESSPOS;
    260.                 float3 ase_normal : NORMAL;
    261.                 float4 ase_texcoord : TEXCOORD0;
    262.                 half4 ase_color : COLOR;
    263.  
    264.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    265.             };
    266.  
    267.             struct TessellationFactors
    268.             {
    269.                 float edge[3] : SV_TessFactor;
    270.                 float inside : SV_InsideTessFactor;
    271.             };
    272.  
    273.             VertexControl vert ( VertexInput v )
    274.             {
    275.                 VertexControl o;
    276.                 UNITY_SETUP_INSTANCE_ID(v);
    277.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    278.                 o.vertex = v.vertex;
    279.                 o.ase_normal = v.ase_normal;
    280.                 o.ase_texcoord = v.ase_texcoord;
    281.                 o.ase_color = v.ase_color;
    282.                 return o;
    283.             }
    284.  
    285.             TessellationFactors TessellationFunction (InputPatch<VertexControl,3> v)
    286.             {
    287.                 TessellationFactors o;
    288.                 float4 tf = 1;
    289.                 float tessValue = _TessValue; float tessMin = _TessMin; float tessMax = _TessMax;
    290.                 float edgeLength = _TessEdgeLength; float tessMaxDisp = _TessMaxDisp;
    291.                 #if defined(ASE_FIXED_TESSELLATION)
    292.                 tf = FixedTess( tessValue );
    293.                 #elif defined(ASE_DISTANCE_TESSELLATION)
    294.                 tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, GetObjectToWorldMatrix(), _WorldSpaceCameraPos );
    295.                 #elif defined(ASE_LENGTH_TESSELLATION)
    296.                 tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams );
    297.                 #elif defined(ASE_LENGTH_CULL_TESSELLATION)
    298.                 tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes );
    299.                 #endif
    300.                 o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w;
    301.                 return o;
    302.             }
    303.  
    304.             [domain("tri")]
    305.             [partitioning("fractional_odd")]
    306.             [outputtopology("triangle_cw")]
    307.             [patchconstantfunc("TessellationFunction")]
    308.             [outputcontrolpoints(3)]
    309.             VertexControl HullFunction(InputPatch<VertexControl, 3> patch, uint id : SV_OutputControlPointID)
    310.             {
    311.                return patch[id];
    312.             }
    313.  
    314.             [domain("tri")]
    315.             VertexOutput DomainFunction(TessellationFactors factors, OutputPatch<VertexControl, 3> patch, float3 bary : SV_DomainLocation)
    316.             {
    317.                 VertexInput o = (VertexInput) 0;
    318.                 o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z;
    319.                 o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z;
    320.                 o.ase_texcoord = patch[0].ase_texcoord * bary.x + patch[1].ase_texcoord * bary.y + patch[2].ase_texcoord * bary.z;
    321.                 o.ase_color = patch[0].ase_color * bary.x + patch[1].ase_color * bary.y + patch[2].ase_color * bary.z;
    322.                 #if defined(ASE_PHONG_TESSELLATION)
    323.                 float3 pp[3];
    324.                 for (int i = 0; i < 3; ++i)
    325.                     pp[i] = o.vertex.xyz - patch[i].ase_normal * (dot(o.vertex.xyz, patch[i].ase_normal) - dot(patch[i].vertex.xyz, patch[i].ase_normal));
    326.                 float phongStrength = _TessPhongStrength;
    327.                 o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz;
    328.                 #endif
    329.                 UNITY_TRANSFER_INSTANCE_ID(patch[0], o);
    330.                 return VertexFunction(o);
    331.             }
    332.             #else
    333.             VertexOutput vert ( VertexInput v )
    334.             {
    335.                 return VertexFunction( v );
    336.             }
    337.             #endif
    338.  
    339.             half4 frag ( VertexOutput IN  ) : SV_Target
    340.             {
    341.                 UNITY_SETUP_INSTANCE_ID( IN );
    342.                 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN );
    343.  
    344.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    345.                 float3 WorldPosition = IN.worldPos;
    346.                 #endif
    347.                 float4 ShadowCoords = float4( 0, 0, 0, 0 );
    348.  
    349.                 #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    350.                     #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
    351.                         ShadowCoords = IN.shadowCoord;
    352.                     #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
    353.                         ShadowCoords = TransformWorldToShadowCoord( WorldPosition );
    354.                     #endif
    355.                 #endif
    356.                 float2 uv_MainTex = IN.ase_texcoord3.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    357.                 half4 tex2DNode5 = tex2D( _MainTex, uv_MainTex );
    358.                
    359.                 float3 BakedAlbedo = 0;
    360.                 float3 BakedEmission = 0;
    361.                 float3 Color = ( tex2DNode5 * IN.ase_color ).rgb;
    362.                 float Alpha = ( tex2DNode5.a * IN.ase_color.a );
    363.                 float AlphaClipThreshold = 0.5;
    364.                 float AlphaClipThresholdShadow = 0.5;
    365.  
    366.                 #ifdef _ALPHATEST_ON
    367.                     clip( Alpha - AlphaClipThreshold );
    368.                 #endif
    369.  
    370.                 #ifdef LOD_FADE_CROSSFADE
    371.                     LODDitheringTransition( IN.clipPos.xyz, unity_LODFade.x );
    372.                 #endif
    373.  
    374.                 #ifdef ASE_FOG
    375.                     Color = MixFog( Color, IN.fogFactor );
    376.                 #endif
    377.  
    378.                 return half4( Color, Alpha );
    379.             }
    380.  
    381.             ENDHLSL
    382.         }
    383.  
    384.        
    385.         Pass
    386.         {
    387.            
    388.             Name "DepthOnly"
    389.             Tags { "LightMode"="DepthOnly" }
    390.  
    391.             ZWrite On
    392.             ColorMask 0
    393.             AlphaToMask Off
    394.  
    395.             HLSLPROGRAM
    396.             #define _RECEIVE_SHADOWS_OFF 1
    397.             #pragma multi_compile_instancing
    398.             #define ASE_SRP_VERSION 999999
    399.  
    400.             #pragma prefer_hlslcc gles
    401.             #pragma exclude_renderers d3d11_9x
    402.  
    403.             #pragma vertex vert
    404.             #pragma fragment frag
    405.  
    406.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    407.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
    408.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl"
    409.             #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    410.  
    411.            
    412.  
    413.             struct VertexInput
    414.             {
    415.                 float4 vertex : POSITION;
    416.                 float3 ase_normal : NORMAL;
    417.                 float4 ase_texcoord : TEXCOORD0;
    418.                 half4 ase_color : COLOR;
    419.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    420.             };
    421.  
    422.             struct VertexOutput
    423.             {
    424.                 float4 clipPos : SV_POSITION;
    425.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    426.                 float3 worldPos : TEXCOORD0;
    427.                 #endif
    428.                 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    429.                 float4 shadowCoord : TEXCOORD1;
    430.                 #endif
    431.                 float4 ase_texcoord2 : TEXCOORD2;
    432.                 float4 ase_color : COLOR;
    433.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    434.                 UNITY_VERTEX_OUTPUT_STEREO
    435.             };
    436.  
    437.             CBUFFER_START(UnityPerMaterial)
    438.             half4 _MainTex_ST;
    439.             #ifdef TESSELLATION_ON
    440.                 float _TessPhongStrength;
    441.                 float _TessValue;
    442.                 float _TessMin;
    443.                 float _TessMax;
    444.                 float _TessEdgeLength;
    445.                 float _TessMaxDisp;
    446.             #endif
    447.             CBUFFER_END
    448.             sampler2D _MainTex;
    449.  
    450.  
    451.            
    452.             VertexOutput VertexFunction( VertexInput v  )
    453.             {
    454.                 VertexOutput o = (VertexOutput)0;
    455.                 UNITY_SETUP_INSTANCE_ID(v);
    456.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    457.                 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
    458.  
    459.                 o.ase_texcoord2.xy = v.ase_texcoord.xy;
    460.                 o.ase_color = v.ase_color;
    461.                
    462.                 //setting value to unused interpolator channels and avoid initialization warnings
    463.                 o.ase_texcoord2.zw = 0;
    464.                 #ifdef ASE_ABSOLUTE_VERTEX_POS
    465.                     float3 defaultVertexValue = v.vertex.xyz;
    466.                 #else
    467.                     float3 defaultVertexValue = float3(0, 0, 0);
    468.                 #endif
    469.                 float3 vertexValue = defaultVertexValue;
    470.                 #ifdef ASE_ABSOLUTE_VERTEX_POS
    471.                     v.vertex.xyz = vertexValue;
    472.                 #else
    473.                     v.vertex.xyz += vertexValue;
    474.                 #endif
    475.  
    476.                 v.ase_normal = v.ase_normal;
    477.  
    478.                 float3 positionWS = TransformObjectToWorld( v.vertex.xyz );
    479.  
    480.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    481.                 o.worldPos = positionWS;
    482.                 #endif
    483.  
    484.                 o.clipPos = TransformWorldToHClip( positionWS );
    485.                 #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR) && defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    486.                     VertexPositionInputs vertexInput = (VertexPositionInputs)0;
    487.                     vertexInput.positionWS = positionWS;
    488.                     vertexInput.positionCS = clipPos;
    489.                     o.shadowCoord = GetShadowCoord( vertexInput );
    490.                 #endif
    491.                 return o;
    492.             }
    493.  
    494.             #if defined(TESSELLATION_ON)
    495.             struct VertexControl
    496.             {
    497.                 float4 vertex : INTERNALTESSPOS;
    498.                 float3 ase_normal : NORMAL;
    499.                 float4 ase_texcoord : TEXCOORD0;
    500.                 half4 ase_color : COLOR;
    501.  
    502.                 UNITY_VERTEX_INPUT_INSTANCE_ID
    503.             };
    504.  
    505.             struct TessellationFactors
    506.             {
    507.                 float edge[3] : SV_TessFactor;
    508.                 float inside : SV_InsideTessFactor;
    509.             };
    510.  
    511.             VertexControl vert ( VertexInput v )
    512.             {
    513.                 VertexControl o;
    514.                 UNITY_SETUP_INSTANCE_ID(v);
    515.                 UNITY_TRANSFER_INSTANCE_ID(v, o);
    516.                 o.vertex = v.vertex;
    517.                 o.ase_normal = v.ase_normal;
    518.                 o.ase_texcoord = v.ase_texcoord;
    519.                 o.ase_color = v.ase_color;
    520.                 return o;
    521.             }
    522.  
    523.             TessellationFactors TessellationFunction (InputPatch<VertexControl,3> v)
    524.             {
    525.                 TessellationFactors o;
    526.                 float4 tf = 1;
    527.                 float tessValue = _TessValue; float tessMin = _TessMin; float tessMax = _TessMax;
    528.                 float edgeLength = _TessEdgeLength; float tessMaxDisp = _TessMaxDisp;
    529.                 #if defined(ASE_FIXED_TESSELLATION)
    530.                 tf = FixedTess( tessValue );
    531.                 #elif defined(ASE_DISTANCE_TESSELLATION)
    532.                 tf = DistanceBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, tessValue, tessMin, tessMax, GetObjectToWorldMatrix(), _WorldSpaceCameraPos );
    533.                 #elif defined(ASE_LENGTH_TESSELLATION)
    534.                 tf = EdgeLengthBasedTess(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams );
    535.                 #elif defined(ASE_LENGTH_CULL_TESSELLATION)
    536.                 tf = EdgeLengthBasedTessCull(v[0].vertex, v[1].vertex, v[2].vertex, edgeLength, tessMaxDisp, GetObjectToWorldMatrix(), _WorldSpaceCameraPos, _ScreenParams, unity_CameraWorldClipPlanes );
    537.                 #endif
    538.                 o.edge[0] = tf.x; o.edge[1] = tf.y; o.edge[2] = tf.z; o.inside = tf.w;
    539.                 return o;
    540.             }
    541.  
    542.             [domain("tri")]
    543.             [partitioning("fractional_odd")]
    544.             [outputtopology("triangle_cw")]
    545.             [patchconstantfunc("TessellationFunction")]
    546.             [outputcontrolpoints(3)]
    547.             VertexControl HullFunction(InputPatch<VertexControl, 3> patch, uint id : SV_OutputControlPointID)
    548.             {
    549.                return patch[id];
    550.             }
    551.  
    552.             [domain("tri")]
    553.             VertexOutput DomainFunction(TessellationFactors factors, OutputPatch<VertexControl, 3> patch, float3 bary : SV_DomainLocation)
    554.             {
    555.                 VertexInput o = (VertexInput) 0;
    556.                 o.vertex = patch[0].vertex * bary.x + patch[1].vertex * bary.y + patch[2].vertex * bary.z;
    557.                 o.ase_normal = patch[0].ase_normal * bary.x + patch[1].ase_normal * bary.y + patch[2].ase_normal * bary.z;
    558.                 o.ase_texcoord = patch[0].ase_texcoord * bary.x + patch[1].ase_texcoord * bary.y + patch[2].ase_texcoord * bary.z;
    559.                 o.ase_color = patch[0].ase_color * bary.x + patch[1].ase_color * bary.y + patch[2].ase_color * bary.z;
    560.                 #if defined(ASE_PHONG_TESSELLATION)
    561.                 float3 pp[3];
    562.                 for (int i = 0; i < 3; ++i)
    563.                     pp[i] = o.vertex.xyz - patch[i].ase_normal * (dot(o.vertex.xyz, patch[i].ase_normal) - dot(patch[i].vertex.xyz, patch[i].ase_normal));
    564.                 float phongStrength = _TessPhongStrength;
    565.                 o.vertex.xyz = phongStrength * (pp[0]*bary.x + pp[1]*bary.y + pp[2]*bary.z) + (1.0f-phongStrength) * o.vertex.xyz;
    566.                 #endif
    567.                 UNITY_TRANSFER_INSTANCE_ID(patch[0], o);
    568.                 return VertexFunction(o);
    569.             }
    570.             #else
    571.             VertexOutput vert ( VertexInput v )
    572.             {
    573.                 return VertexFunction( v );
    574.             }
    575.             #endif
    576.  
    577.             half4 frag(VertexOutput IN  ) : SV_TARGET
    578.             {
    579.                 UNITY_SETUP_INSTANCE_ID(IN);
    580.                 UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX( IN );
    581.  
    582.                 #if defined(ASE_NEEDS_FRAG_WORLD_POSITION)
    583.                 float3 WorldPosition = IN.worldPos;
    584.                 #endif
    585.                 float4 ShadowCoords = float4( 0, 0, 0, 0 );
    586.  
    587.                 #if defined(ASE_NEEDS_FRAG_SHADOWCOORDS)
    588.                     #if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
    589.                         ShadowCoords = IN.shadowCoord;
    590.                     #elif defined(MAIN_LIGHT_CALCULATE_SHADOWS)
    591.                         ShadowCoords = TransformWorldToShadowCoord( WorldPosition );
    592.                     #endif
    593.                 #endif
    594.  
    595.                 float2 uv_MainTex = IN.ase_texcoord2.xy * _MainTex_ST.xy + _MainTex_ST.zw;
    596.                 half4 tex2DNode5 = tex2D( _MainTex, uv_MainTex );
    597.                
    598.                 float Alpha = ( tex2DNode5.a * IN.ase_color.a );
    599.                 float AlphaClipThreshold = 0.5;
    600.  
    601.                 #ifdef _ALPHATEST_ON
    602.                     clip(Alpha - AlphaClipThreshold);
    603.                 #endif
    604.  
    605.                 #ifdef LOD_FADE_CROSSFADE
    606.                     LODDitheringTransition( IN.clipPos.xyz, unity_LODFade.x );
    607.                 #endif
    608.                 return 0;
    609.             }
    610.             ENDHLSL
    611.         }
    612.  
    613.    
    614.     }
    615.     CustomEditor "UnityEditor.ShaderGraph.PBRMasterGUI"
    616.     Fallback "Hidden/InternalErrorShader"
    617.    
    618. }
    619. /*ASEBEGIN
    620. Version=18712
    621. 0;6;2560;1383;1829.225;868.6758;1;True;False
    622. Node;AmplifyShaderEditor.VertexColorNode;9;-733.9046,187.8119;Inherit;False;0;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
    623. Node;AmplifyShaderEditor.SamplerNode;5;-825.0001,-150;Inherit;True;Property;_MainTex;MainTex;0;0;Create;True;0;0;0;False;0;False;-1;None;4caac0564fbc05b48a5ec865e3ac4f45;True;0;False;white;Auto;False;Object;-1;Auto;Texture2D;8;0;SAMPLER2D;;False;1;FLOAT2;0,0;False;2;FLOAT;0;False;3;FLOAT2;0,0;False;4;FLOAT2;0,0;False;5;FLOAT;1;False;6;FLOAT;0;False;7;SAMPLERSTATE;;False;5;COLOR;0;FLOAT;1;FLOAT;2;FLOAT;3;FLOAT;4
    624. Node;AmplifyShaderEditor.SimpleMultiplyOpNode;7;-407.4001,59.69999;Inherit;False;2;2;0;COLOR;0,0,0,0;False;1;COLOR;0,0,0,0;False;1;COLOR;0
    625. Node;AmplifyShaderEditor.SimpleMultiplyOpNode;10;-180.3254,149.7495;Inherit;False;2;2;0;FLOAT;0;False;1;FLOAT;0;False;1;FLOAT;0
    626. Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;0;0,0;Float;False;False;-1;2;UnityEditor.ShaderGraph.PBRMasterGUI;0;3;New Amplify Shader;2992e84f91cbeb14eab234972e07ea9d;True;ExtraPrePass;0;0;ExtraPrePass;5;False;False;False;False;False;False;False;False;True;0;False;-1;True;0;False;-1;False;False;False;False;False;False;False;False;True;3;RenderPipeline=UniversalPipeline;RenderType=Opaque=RenderType;Queue=Geometry=Queue=0;True;0;0;True;1;1;False;-1;0;False;-1;0;1;False;-1;0;False;-1;False;False;False;False;False;False;False;False;True;0;False;-1;True;True;True;True;True;0;False;-1;False;False;False;True;False;255;False;-1;255;False;-1;255;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;True;1;False;-1;True;3;False;-1;True;True;0;False;-1;0;False;-1;True;0;False;0;Hidden/InternalErrorShader;0;0;Standard;0;False;0
    627. Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;2;0,0;Float;False;False;-1;2;UnityEditor.ShaderGraph.PBRMasterGUI;0;3;New Amplify Shader;2992e84f91cbeb14eab234972e07ea9d;True;ShadowCaster;0;2;ShadowCaster;0;False;False;False;False;False;False;False;False;True;0;False;-1;True;0;False;-1;False;False;False;False;False;False;False;False;True;3;RenderPipeline=UniversalPipeline;RenderType=Opaque=RenderType;Queue=Geometry=Queue=0;True;0;0;False;False;False;False;False;False;False;False;True;0;False;-1;False;False;False;False;False;False;True;1;False;-1;True;3;False;-1;False;True;1;LightMode=ShadowCaster;False;0;Hidden/InternalErrorShader;0;0;Standard;0;False;0
    628. Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;3;0,0;Float;False;False;-1;2;UnityEditor.ShaderGraph.PBRMasterGUI;0;3;New Amplify Shader;2992e84f91cbeb14eab234972e07ea9d;True;DepthOnly;0;3;DepthOnly;0;False;False;False;False;False;False;False;False;True;0;False;-1;True;0;False;-1;False;False;False;False;False;False;False;False;True;3;RenderPipeline=UniversalPipeline;RenderType=Opaque=RenderType;Queue=Geometry=Queue=0;True;0;0;False;False;False;False;False;False;False;False;True;0;False;-1;False;True;False;False;False;False;0;False;-1;False;False;False;False;True;1;False;-1;False;False;True;1;LightMode=DepthOnly;False;0;Hidden/InternalErrorShader;0;0;Standard;0;False;0
    629. Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;4;0,0;Float;False;False;-1;2;UnityEditor.ShaderGraph.PBRMasterGUI;0;3;New Amplify Shader;2992e84f91cbeb14eab234972e07ea9d;True;Meta;0;4;Meta;0;False;False;False;False;False;False;False;False;True;0;False;-1;True;0;False;-1;False;False;False;False;False;False;False;False;True;3;RenderPipeline=UniversalPipeline;RenderType=Opaque=RenderType;Queue=Geometry=Queue=0;True;0;0;False;False;False;False;False;False;False;False;False;True;2;False;-1;False;False;False;False;False;False;False;False;True;1;LightMode=Meta;False;0;Hidden/InternalErrorShader;0;0;Standard;0;False;0
    630. Node;AmplifyShaderEditor.TemplateMultiPassMasterNode;1;87,-1;Half;False;True;-1;2;UnityEditor.ShaderGraph.PBRMasterGUI;0;3;Brink/UI/TextMeshPro/Highlight;2992e84f91cbeb14eab234972e07ea9d;True;Forward;0;1;Forward;8;False;False;False;False;False;False;False;False;True;0;False;-1;True;0;False;-1;False;False;False;False;False;False;False;False;True;3;RenderPipeline=UniversalPipeline;RenderType=Transparent=RenderType;Queue=Transparent=Queue=0;True;0;0;True;1;5;False;-1;10;False;-1;1;1;False;-1;10;False;-1;False;False;False;False;False;False;False;False;False;True;True;True;True;True;0;False;-1;False;False;False;True;False;255;False;-1;255;False;-1;255;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;7;False;-1;1;False;-1;1;False;-1;1;False;-1;True;2;False;-1;True;3;False;-1;True;True;0;False;-1;0;False;-1;True;1;LightMode=UniversalForward;False;0;Hidden/InternalErrorShader;0;0;Standard;22;Surface;1;  Blend;0;Two Sided;1;Cast Shadows;0;  Use Shadow Threshold;0;Receive Shadows;0;GPU Instancing;1;LOD CrossFade;0;Built-in Fog;0;DOTS Instancing;0;Meta Pass;0;Extra Pre Pass;0;Tessellation;0;  Phong;0;  Strength;0.5,False,-1;  Type;0;  Tess;16,False,-1;  Min;10,False,-1;  Max;25,False,-1;  Edge Length;16,False,-1;  Max Displacement;25,False,-1;Vertex Position,InvertActionOnDeselection;1;0;5;False;True;False;True;False;False;;False;0
    631. WireConnection;7;0;5;0
    632. WireConnection;7;1;9;0
    633. WireConnection;10;0;5;4
    634. WireConnection;10;1;9;4
    635. WireConnection;1;2;7;0
    636. WireConnection;1;3;10;0
    637. ASEEND*/
    638. //CHKSM=3E11D34689E563A032696D7D30809BF572B65D0F
     
  31. Mikhail94

    Mikhail94

    Joined:
    Dec 22, 2015
    Posts:
    31
    Any progress about in-build solution? <font> trick works, but it's hacky solution.
     
    CGDever likes this.
  32. Strom_CL

    Strom_CL

    Joined:
    Nov 17, 2012
    Posts:
    57
    OK so using <mark> in a 3D TextMeshPro object causes it to draw over the text, thought I was going crazy looking at some of these examples out there. Will give one of those "hacks" a shot above, the <font> workaround works but has weird Z issues, and setting Z position or sort order in the prefab gets overridden at runtime, and the <mark> color doesn't match what I'm setting it to so its all screwy.

    upload_2021-10-25_14-46-45.png
     
    Last edited: Oct 25, 2021
    CGDever likes this.
  33. vl4dimir

    vl4dimir

    Joined:
    Jun 28, 2012
    Posts:
    21
    Thread necro @Stephan_B is your fix still being planned for release at some point?
     
    CGDever likes this.
  34. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    6,523
    Yes.
     
    Strom_CL likes this.
  35. CGDever

    CGDever

    Joined:
    Dec 17, 2014
    Posts:
    141
    Big necro, @Stephan_B, do you have some updates?
    Current solution with "font" is quite ugly for me :/
     
  36. GAZEREAPER

    GAZEREAPER

    Joined:
    Feb 15, 2014
    Posts:
    9
    For anyone still looking for a neater solution to this, this is the cleanest one that I found;

    $"<font=\"{text.font.name}\"><mark=#{ColorUtility.ToHtmlStringRGBA(backgroundColor)}>"


    Where text is the TMP_Text component and backgroundColor your desired Color.
    ColorUtility.ToHtmlStringRGBA is built into Unity, FYI.

    Just remember to put your font asset in a correctly named resource folder and all should work fine: http://digitalnativestudios.com/textmeshpro/docs/settings/#font

    Example extension method;
    Code (CSharp):
    1.     public static class TMPExtensions
    2.     {
    3.         public static string Mark(this TMP_Text component, string text, Color color)
    4.         {
    5.             return $"<font=\"{component.font.name}\"><mark=#{ColorUtility.ToHtmlStringRGBA(color)}>{text}</mark></font>";
    6.         }
    7.     }
    use:
    text.text = text.Mark("some string", backgroundColor);
     
    Last edited: Jul 28, 2022
  37. pmelo

    pmelo

    Joined:
    Oct 30, 2013
    Posts:
    9
    @Stephan_B I just tested your solution in the 2021.3.6, and this works:
    <font="Theinhardt Pan Bold SDF">This <mark=#FF8000>text is <b>high\u00adlighted</b></mark>


    Whereas this doesn't work:
    <font="Theinhardt Pan Regular SDF">This <mark=#FF8000>text is <b>high\u00adlighted</b></mark>


    See images attached.
    That can be helpful for the team to figure it out there ;). I exported the fonts, hope that helps.

    Note for those trying this workaround, you have to put your font file under the following folder hierarchy in your project:
    Assets
    Resources
    Fonts & Materials
    Theinhardt Pan Bold SDF
    Theinhardt Pan Regular SDF​

    Resources folder can be inside a subfolder of your preference, you can have multiple resources folders and that still works.
     
    Strom_CL likes this.
unityunity