XI - 3D UI using Unity's UI Toolkit

Hi,

I have been working on a 3D UI framework to use in a VR game I am working on. I was considering using uGUI but preferred UITK because of the benefits of using tools like UI builder and UI toolkit debugger, working with readable and version-control friendly formats like UXML/USS, ability to build testable isolatable units / components, and because of Unity’s adoption of this new system.

Unfortunately, UITK does not support 3D or world space UI so I ventured into building this feature myself. I ended up getting this to work and start adding additional extensions and support for features not included by UITK. This includes linear-gradient html/css style backgrounds, additional custom styles, support for rendering elements with custom ShaderGraph shaders, and more.

I think this project came a long way but there’s still a lot more work to be done. If anybody finds this interesting or have any suggestions or feedback, I would love to hear it.

1 Like

This is incredible!

Do you have any information on your process behind this? I’m a huge fan of the general structure of UITK but am frustrated it is effectively completely unusable in VR.

How does your shader integration work? I’m dying to use UITK with shaders in screenspace (outside of a VR context) but have had no luck getting anything working.

Thanks. And yeah, I can give you a summary of how it works. In short, I hide the default Unity rendering of UITK and render primitives from scratch. For screenspace, it shouldn’t be too bad, but for 3D/VR/worldspace there are a lot of things to consider.

Rendering
I set the PanelSettings targetTexture to some small 2x2 texture that I don’t use, this way Unity does not render to the screen. I also set the “SetScreenToPanelSpaceFunction” to a function that returns “new Vector2(float.NaN, float.NaN)”, so that the screen space input handling is ignored (so I can provide custom input).

For a simple screenspace implementation you wouldn’t even have to modify the SetScreenToPanelSpaceFunction function as long as you’re rendering matches up with UITK positioning.

For the rendering, a lot of what I do was inspired by the “Shapes” asset by Freya. On update loop, I simply traverse the hierarchy and render quads with properties extracted from the element’s layout and resolved style. In URP, this is done through a ScriptableRenderFeature with cmd.DrawMesh calls. With this you can supply your own custom shaderlab or shadergraph materials.

The shader used is a modification of Inigo Quilez’s Rounded Box SDF to also render borders with optional distinct colors. With this, all UITK element backgrounds and borders are able to be rendered.

To render text, I use TMP, rendering the mesh and submeshes in correct places. (This was very difficult to do, there are a lot of nuances in rendering TMP exactly the way UITK does)

To render images, I use a texture shader. For VR there’s mipmaps and anisotropic sampling that needed to be considered.

For clipping (for example in scroll views) in ShaderGraph, I rendered clip boxes to a custom stencil render texture. For non shadergraph materials and TMP, just make sure to update the stencil buffer.

That should be enough for implementing screenspace UITK with custom shaders.

Other
Just a quick list of other things implemented in XI:

  • Distinct event system with similar API (because of issues trying to simulate events in UITK)
  • Custom styling supporting css styles (like linear-gradient backgrounds), done by accessing UITK internals with asmref and parsing styles (difficult)
  • Local anti-aliasing (inspired by Freya), for fixing jagged borders (maybe not necessary in screen space, but very important especially in VR) (difficult)
  • Animations for custom styles
  • Additional elements

I had plans on implementing screenspace but as this asset isn’t currently doing too well, I was thinking about instead focusing on moving it to use Jobs/ECS for better performance. Probably will make it more attractive and might open up the possibility to do a lot of other cool things as well. With this I’d probably move away from using UITK by adding a flex layout engine but still keeping support for UI Builder and UXML/USS assets for building UI.

2 Likes