Draw text with textMeshPro on a texture at runtime?

Hello all,

Please excuse my question, but I am a beginner with unity 3D and I need your help.
At run-time, I want to put some text on 3D object.
I find this old post
http://blog.almostlogical.com/2010/08/20/adding-text-to-texture-at-runtime-in-unity3d-without-using-render-texture/
but I think that textMesh is probably the best solution.
Do you have a snippet or a short example ?
Thanks a lot

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.

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!

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!

1 Like

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.
7365338--897503--upload_2021-7-27_20-13-15.png

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

7365338–897500–RenderTextToTexture.zip (1.33 MB)

6 Likes

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.

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:

[SerializeField] TextMeshPro tmpStandard;
[SerializeField] TextMeshProUGUI tmpUI;

public void SendTmpToRenderTexture()
{
    Vector2 size = new Vector2(100f, 100f);
    RenderTexture tex = RenderTexture.GetTemporary(100f, Mathf.RoundToInt(size.y * 200f), 24, RenderTextureFormat.ARGB32);

    GL.PushMatrix(); // copy current camera matrix settings
    GL.LoadIdentity();

    Matrix4x4 proj = Matrix4x4.Ortho(-size.x / 2f, size.x / 2f, -size.x / 2f, size.y / 2f, -10f, 100f);
    GL.LoadProjectionMatrix(proj);

    RenderTexture currentActiveRT = RenderTexture.active;
    Graphics.SetRenderTarget(tex);

    GL.Clear(false, true, new Color(0f, 0f, 0f, 0f));

    if (tmpUI)
    {
        tmpUI.materialForRendering.SetPass(0);

        Graphics.DrawMeshNow(tmpUI.mesh, Matrix4x4.identity);
    }
    else
    {
        if (Application.isPlaying)
            tmpStandard.renderer.material.SetPass(0);
        else
            tmpStandard.renderer.sharedMaterial.SetPass(0);

        Graphics.DrawMeshNow(tmpStandard.mesh, Matrix4x4.identity);
    }

    //restore settings
    GL.PopMatrix();
    RenderTexture.active = currentActiveRT;

    //assign texture to image
    img.gameObject.SetActive(true);
    imgRt.sizeDelta = thisRt.sizeDelta;
    img.texture = tex;
}

In my case, I’m assigning the RenderTexture to a RawImage, but I believe it can be used anywhere.

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:

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

9583039--1357063--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.