Search Unity

TextMesh Pro Draw text with textMeshPro on a texture at runtime?

Discussion in 'UGUI & TextMesh Pro' started by twilightZone, Sep 20, 2017.

  1. twilightZone

    twilightZone

    Joined:
    Oct 10, 2014
    Posts:
    30
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You can still render a normal TextMesh Pro object "Create - 3D Object - TextMeshPro - Text" into a render texture.

    I don't have any code snippets but the process would be similar to how you would do it with a TextMesh object.
     
  3. graffitiarco

    graffitiarco

    Joined:
    Sep 28, 2017
    Posts:
    1
    Hi, Stephan!

    I am also stuck with same issue.
    1) I take a photo from web camera.
    2) I put the taken photo to background RawImage with preserved aspect ratio and original size. The photo is big and could be bigger than screen. So it overflows the screen and part of the photo is not visible.
    3) After that i put some TextMeshPro objects on top of it.
    4) Then i want to get combined texture (photo + text meshes).

    So if i would use RenderTexture with main camera i will get just camera (display) resolution which could be worse and cropped TextMeshPro object if it doesn't fit in the screen (but does fit in the bigger image).

    I was trying to create another adhoc camera and set position and viewport to embrace the whole photo but it doesn't render since TextMeshPro is a UI element within Canvas, which itself renders on the Main Camera only.

    What would you suggest?

    Thank you!
     
  4. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Sorry for bumping this, but seeing as the answer is a bit undetailed and one of the first results on Google (along with the decade old link OP provided), I'd like to hear people's take on the best way to achieve this effect, preferably in detail?

    I only just learned about the existence of Render Texture, so if anyone has valid input on the best way to achieve this, maybe with TextMesh Pro I would be ever so happy!
     
    jhubert3 likes this.
  5. dujimache

    dujimache

    Joined:
    Dec 17, 2011
    Posts:
    89
    see the attached file, a simple demo, using Graphics.DrawMeshNow. Using Unity 2020.3.1f1 (64-bit), and the shader of the text' material is Distance Field SSD.
    upload_2021-7-27_20-13-15.png

    upload_2021-7-27_20-13-35.png
     

    Attached Files:

  6. shibi2017

    shibi2017

    Joined:
    Jan 18, 2018
    Posts:
    153
    it works amazing in build-in pipeline, but when I play it on URP, the text.mesh all seems to rendered as simple blocks, only shows the bounds of every character of my words.
    And I use a silly way: just add a render texture to a camera, and use this render texture as my material's maintex, it works but not that elegant.
     
  7. _eternal

    _eternal

    Joined:
    Nov 25, 2014
    Posts:
    304
    This is great, thank you.

    For what it's worth, it looks like this can work with TextMeshProUGUI if you use materialForRendering instead of renderer.material.

    For convenience, here's the code from the project plus my edits:

    Code (CSharp):
    1. [SerializeField] TextMeshPro tmpStandard;
    2. [SerializeField] TextMeshProUGUI tmpUI;
    3.  
    4. public void SendTmpToRenderTexture()
    5. {
    6.     Vector2 size = new Vector2(100f, 100f);
    7.     RenderTexture tex = RenderTexture.GetTemporary(100f, Mathf.RoundToInt(size.y * 200f), 24, RenderTextureFormat.ARGB32);
    8.  
    9.     GL.PushMatrix(); // copy current camera matrix settings
    10.     GL.LoadIdentity();
    11.  
    12.     Matrix4x4 proj = Matrix4x4.Ortho(-size.x / 2f, size.x / 2f, -size.x / 2f, size.y / 2f, -10f, 100f);
    13.     GL.LoadProjectionMatrix(proj);
    14.  
    15.     RenderTexture currentActiveRT = RenderTexture.active;
    16.     Graphics.SetRenderTarget(tex);
    17.  
    18.     GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));
    19.  
    20.     if (tmpUI)
    21.     {
    22.         tmpUI.materialForRendering.SetPass(0);
    23.  
    24.         Graphics.DrawMeshNow(tmpUI.mesh, Matrix4x4.identity);
    25.     }
    26.     else
    27.     {
    28.         if (Application.isPlaying)
    29.             tmpStandard.renderer.material.SetPass(0);
    30.         else
    31.             tmpStandard.renderer.sharedMaterial.SetPass(0);
    32.  
    33.         Graphics.DrawMeshNow(tmpStandard.mesh, Matrix4x4.identity);
    34.     }
    35.  
    36.     //restore settings
    37.     GL.PopMatrix();
    38.     RenderTexture.active = currentActiveRT;
    39.  
    40.     //assign texture to image
    41.     img.gameObject.SetActive(true);
    42.     imgRt.sizeDelta = thisRt.sizeDelta;
    43.     img.texture = tex;
    44. }
    In my case, I'm assigning the RenderTexture to a RawImage, but I believe it can be used anywhere.
     
  8. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    In 2024 this thread was still a big help (TMP docs were not of any hepl - the official FAQ linked to from Unity manual is still offline after more than a year, and there was nothing in the docs about materials and how TMP uses them in an unusual way).

    TL;DR: For anyone else using DrawMesh or similar, and getting this:

    upload_2024-1-15_16-44-59.png

    ...Where the actual mesh being rendered (and so the above image should look like this):

    upload_2024-1-15_16-45-40.png

    ... it seems to be that (as per @_eternal's comment above), TMP requires you to:

    1. Ignore the material on the TMP object (its MeshRenderer.sharedMaterial) - it will fail with the blocks output above (presumably something to do with TMP using custom shaders to do the SDF effect for smooth text etc? - that would make sense)
    2. Use TMP's custom .renderer attribute, and the material on that instead.
    3. The SetPass stuff shouldn't be needed for modern DrawMesh (it's needed I think for the low-level GL approach @_eternal was using)
    4. ... I don't know why @_eternal was doing a switch based on Application state.

    Also I couldn't find anything in the TMP docs explaining any of this, so this is trial-and-error/guesswork - but kind-of makes sense after the fact.