Flickering when using Immediate Mode Shapes with an Overlay camera in URP
I've been having a lot of difficulty lately with shapes drawn in Immediate Mode flickering, over-drawing (rendering multiple times), and sometimes just not drawing at all. I've managed to isolate the flickering and over-drawing to a standalone project that can be downloaded below:
- Open the project in Unity 2020.3.2f1
- Open scene at/Bug/Scenes/SampleScene
- Hit play
- The above flickering should be seen.
The flickering seems to come from some elements being drawn more times than they should be. Ideally, there should be only 5 draw commands for the HUD elements, but for some reason it's 7 here. The frame debugger can also act a bit strange, flickering even while scrolling through the list of elements. In extreme situations (not visible here, but it is in my main project) it can re-order elements so dramatically it will make the frame debugger unusable since every click goes somewhere different. When no flickering or overdraw is present, this behavior does not occur.
To give an idea on the architecture of the scene, here's what's happening:
1. The left and right displays are being rendered with the help of a screen space canvas to use as reference for positioning. Both the canvas, and the Immediate Mode Shapes that are drawn on the canvas, are rendered to an overlay camera called ShapesHUDCamera. The RenderCoolThing component on the HUDCanvas draws these two shapes. There is nothing wrong these as far as I can tell. They render just fine under normal circumstances.
It's worth noting that the ShapesHUDCamera happens to be coincident with the main camera. In the real project, this is not the case. The ShapesHUDCamera stays at the origin while the main camera can be anywhere. The guard clauses to render specific shapes to specific cameras are also necessary because not all cameras should see all Shapes elements. Otherwise situations like this can result.
2. In the 3D world, there is an Immediate Mode disc being drawn on top of a cube. This drawing is handled by the StrategicRenderer object, with the StrategicSymbols Monobehaviour.
A weird workaround?
In the process of trying to recreate this bug from my main project, I have noticed something strange. The flickering can be fixed by either drawing all Shapes to the same camera, or by switching the cameras that the Shapes are being rendered to.
To do the former:
- Select the HUDCanvas object
- Change the Canvas' Render Camera to MainCamera
- Change the RenderCoolThing component's DrawCamera to MainCamera
- Run the game
Somehow it works perfectly now?
Putting everything on the same camera does admittedly make some kind of intuitive sense. We can get weirder though. At first, I thought that the cause of the problem was rendering Shapes to an Overlay camera, but for some reason if the disc is drawn on the overlay camera, but the HUD shapes are drawn on the main camera that works too? I'm not sure why one would work and the other doesn't.
- Follow the steps above to put the HUD onto the main camera
- Select the StrategicRenderer object and set its RenderCamera to the ShapesHUDCamera
- Hit Play
- No flickering or overdraw, even though they are rendered to different cameras