Render Text Mesh Pro on top of Immediate Draw Mode shapes?

Avatar
  • updated
  • Answered

I have a grid of Lines drawing in Immediate Draw Mode. I want to place a text mesh pro object over them but the lines are always drawn on top of the text. 

I have tried:

1. Changing the ZTest condition for my Lines

2. Settings the BlendMode to Opaque for my Lines

Reporting a bug? please specify Unity version:
Reporting a bug? please specify Shapes version:
Reporting a bug? please specify Render Pipeline:
Built-in render pipeline
Pinned replies
Avatar
Freya Holmér creator
  • Answer
  • Answered

there are two things happening here!

1. Immediate mode drawing doesn't automatically sort, it will naively draw in the order you write the code, no matter what

2. Any renderers (such as TMP text) will render somewhere in the Unity render pipeline, usually along with transparent objects like any other objects in the world

so what can happen is that if #2 happens before #1, immediate mode can draw on top of things you don't want it to draw on top of

The easiest way to check what order things are happening in is to open the frame debugger in Unity, and step through to see how it all renders

That all being said, I think what you might want to do in this case is to either:

A: Draw the lines using components instead of immediate mode
B: Change the injection point of the Draw.Command (this is the second parameter of Draw.Command) to something earlier, such as CameraEvent.AfterForwardOpaque, if you're drawing opaque shapes. That way any transparent renderers will always be drawn after

Avatar
Freya Holmér creator
  • Under Review

how are you drawing the lines and the TMP object, and in what order?

Avatar
Dustin M

I am using the following properties for my lines in Immediate draw mode:

Draw.LineGeometry = LineGeometry.Flat2D;
Draw.LineThicknessSpace = ThicknessSpace.Pixels;
Draw.BlendMode = ShapesBlendMode.Opaque;
Draw.Matrix = transform.localToWorldMatrix;

Then I use Draw.Line in a loop.

The TMP object is a standard TextMeshPro - Text (UI) component with default settings, in "extra settings" is says Geometry Sorting is "normal".

I'm not sure what you mean by in what order? The components are in different child objects and the TMP objects are lower in the hierarchy than the Shapes grid component, but I have tried switching that. 

Thank you for responding! 

Avatar
Freya Holmér creator
  • Answer
  • Answered

there are two things happening here!

1. Immediate mode drawing doesn't automatically sort, it will naively draw in the order you write the code, no matter what

2. Any renderers (such as TMP text) will render somewhere in the Unity render pipeline, usually along with transparent objects like any other objects in the world

so what can happen is that if #2 happens before #1, immediate mode can draw on top of things you don't want it to draw on top of

The easiest way to check what order things are happening in is to open the frame debugger in Unity, and step through to see how it all renders

That all being said, I think what you might want to do in this case is to either:

A: Draw the lines using components instead of immediate mode
B: Change the injection point of the Draw.Command (this is the second parameter of Draw.Command) to something earlier, such as CameraEvent.AfterForwardOpaque, if you're drawing opaque shapes. That way any transparent renderers will always be drawn after

Avatar
Dustin M

I tried solution B and it worked for me! Thank you very much!

Avatar
Anton Orlov

I faced exactly the same, played around blending modes and found Additive blend mode worked well for me:

Draw.BlendMode = ShapesBlendMode.Additive 

Thus I didn't need to change the injection point. 

Avatar
fun fun

Sorry for necro, but I can't seem to get it to work for sprites. 

        using (Draw.Command(cam))
        {
            Draw.DiscGeometry = DiscGeometry.Flat2D;
            Draw.Disc(player.position, Vector3.up);
            Draw.Command(cam, (UnityEngine.Rendering.Universal.RenderPassEvent)CameraEvent.BeforeForwardOpaque);
Avatar
Freya Holmér creator
Quote from fun fun

Sorry for necro, but I can't seem to get it to work for sprites. 

        using (Draw.Command(cam))
        {
            Draw.DiscGeometry = DiscGeometry.Flat2D;
            Draw.Disc(player.position, Vector3.up);
            Draw.Command(cam, (UnityEngine.Rendering.Universal.RenderPassEvent)CameraEvent.BeforeForwardOpaque);

you're nesting draw commands, which isn't supported. remove the last command and put the camera event into the first instead 

Avatar
fun fun
Quote from Freya Holmér

you're nesting draw commands, which isn't supported. remove the last command and put the camera event into the first instead 

Thanks so much, missed that. 

Unfortunately it's still not working, it doesn't seem like it's rendering at all. Suggestions? 

        using (Draw.Command(cam, (UnityEngine.Rendering.Universal.RenderPassEvent)CameraEvent.AfterForwardOpaque))
        {
            Draw.DiscGeometry = DiscGeometry.Flat2D;
            Draw.Disc(player.position, Vector3.up);
        }
Avatar
Freya Holmér creator
Quote from fun fun

Thanks so much, missed that. 

Unfortunately it's still not working, it doesn't seem like it's rendering at all. Suggestions? 

        using (Draw.Command(cam, (UnityEngine.Rendering.Universal.RenderPassEvent)CameraEvent.AfterForwardOpaque))
        {
            Draw.DiscGeometry = DiscGeometry.Flat2D;
            Draw.Disc(player.position, Vector3.up);
        }

where/when are you running this code?

Avatar
fun fun
Quote from Freya Holmér

where/when are you running this code?

To be clear I'm able to render if I omit the camera event, on the draw command. 

[ExecuteAlways]
public class HUD : ImmediateModeShapeDrawer
{
    public Camera cam;
    void Awake()
    {
        if (Application.isPlaying == false)
            return;
    }

    public override void DrawShapes(Camera cam)
    {
        if (cam != this.cam) 
            return;

        using (Draw.Command(cam, (UnityEngine.Rendering.Universal.RenderPassEvent)CameraEvent.AfterForwardOpaque))
        {
            Draw.DiscGeometry = DiscGeometry.Flat2D;
            Draw.Disc(player.position, Vector3.up);
 
        }
    }