Clear depth from within Immediate Mode context

Avatar
  • updated

I'm working on some runtime handles using shapes in immediate mode. They are drawn after image effects so they appear on top of the scene. I'm working on rotation handles, and to mask the "backfaces" of the rotation rings, I'm drawing an invisible, opaque sphere within the rings. However I only want these rings to occlude the rings of the rotation handle. As-is it will occlude anything else, like the position handle shown in the attached video.

 Screen Recording 2023-11-12 at 16.36.18.mov

Is there a way to clear the depth buffer myself from within the immediate mode context?

I tried GL.Clear but my understanding is that the Shapes draw functions are deferred via command buffers. I tried creating my own command buffer and adding it to the camera in the DrawShapes callback, but making sure it was only added once, and cleaned up properly was messy.

If Shapes has an internal command buffer, I'm curious if there'd be a way to add my own commands to it? I'm open to ideas :)

For reference, here's the relevant bit of the script

using (Draw.Scope)
{
    // Draw an opaque sphere, with all color channels disabled to make it invisible.
    // This will allow the rings to be occluded by an invisible sphere, where the user can click and drag to f
    Draw.BlendMode = ShapesBlendMode.Opaque;
    Draw.ColorMask = ~ColorWriteMask.All;
    Draw.Sphere(pos: transform.position, radius: Vector3.Distance(transform.position, cam.transform.position) 
    
    Draw.ColorMask = ColorWriteMask.All;
    Draw.ThicknessSpace = ThicknessSpace.Noots;
    var distance = Vector3.Distance(transform.position, cam.transform.position);
    var actualRadius = distance * freeRotateRadius;
    var actualThickness = ringThickness;
    if (IsHovered)
    {
        // Draw the same sphere again, but this time make it transparent to slightly darken the area where fre
        Draw.BlendMode = ShapesBlendMode.Multiplicative;
        Draw.Sphere(pos: transform.position, radius: actualRadius, hoverSphereColor);
        actualThickness = ringHoverThickness;
    }
    // Draw a subtle ring around the outside of the sphere
    Draw.ZTest = CompareFunction.Always;
    Draw.BlendMode = ShapesBlendMode.Transparent;
    var actualRingColor = IsPressed ? pressedRingColor : ringColor;
    Draw.Ring
    (
        pos: transform.position,
        colors: DiscColors.Flat(actualRingColor), 
        radius: actualRadius, 
        thickness: actualThickness, 
        normal: cam.transform.forward
    );
}
// Draw the rotation rings
if (x && x.isActiveAndEnabled)
    x.DrawHandle(cam);
if (y && y.isActiveAndEnabled)
    y.DrawHandle(cam);
if (z && z.isActiveAndEnabled)
    z.DrawHandle(cam);
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
Avatar
Keenan Woodall (Beans)

I may be misunderstanding what's happening, but I also noticed that even when the rotation gameobject with the immediate mode shapes script on it is disabled, it continues to occlude shapes drawn by other immediate mode scripts - as if it is painting its depth into the render target without it ever being cleared. It even occludes itself. The camera's clear flags are set to Skybox. I want the handles to draw on top of everything so I set the camera event to AfterImageEffects. Maybe that's related. I'm using the builtin pipeline, 2022.3.6, M1 Macbook Air.

Screen Recording 2023-11-12 at 16.54.20.mov

Avatar
Keenan Woodall (Beans)
Quote from Keenan Woodall (Beans)

I may be misunderstanding what's happening, but I also noticed that even when the rotation gameobject with the immediate mode shapes script on it is disabled, it continues to occlude shapes drawn by other immediate mode scripts - as if it is painting its depth into the render target without it ever being cleared. It even occludes itself. The camera's clear flags are set to Skybox. I want the handles to draw on top of everything so I set the camera event to AfterImageEffects. Maybe that's related. I'm using the builtin pipeline, 2022.3.6, M1 Macbook Air.

Screen Recording 2023-11-12 at 16.54.20.mov

Here is some repro files. You can test it by dropping the files in a project with Shapes installed, and running the Sample scene. Just like in Unity, 'W' toggles the translate handle, 'E' rotation and 'R' scale. After toggling rotation, the other handles are occluded even tho the rotation handle game-object is inactive. The Cube game-object binds the handle position/rotations to its own, so in play-mode the handles can only be moved from the game-view unless you disable the Cube.

Archive.zip