Unity: Using NGUI with the Oculus Rift

Many Unity developers are using Tasharen Entertainment’s NGUI as a UI solution, and quite sensibly in my opinion; it’s much better than the built-in GUI framework in many ways and I don’t think there’s anything better on the asset store either. I recently got it working with the dual-camera rendering of the Rift; here’s the method I used.

Basic Setup

NGUI uses its own camera to render everything on the UI layer(s) you specify. That’s a pretty convenient approach for Rift development as it turns out, thanks to a built-in Unity feature. We’ll be rendering to a texture and then displaying that rather than allowing the UI to render directly to the screen. If you’ve snooped around the Tuscany demo scene a bit, you might recognize this as the same approach the supplied OVRMainMenu takes.

Create a render texture in your project; you’ll probably want it to be 1024×1024 or 2048×2048 for UI use. Point the NGUI camera’s “Target texture” field at your render texture. You’ll need to create a new material that uses the render texture as a source, so do that – set the shader as “Unlit/Texture” right now. We’ll be coming back to shaders in a moment.

Next, create a plane (if you’re reading this IN THE FUTURE, Unity are supposed to be implementing a two-triangle optimized plane object; if that’s available, use it instead of the standard 400-poly beast we have now). Parent it to the CameraRight camera object inside the OVRCameraController. Note that this will give you a UI which is locked to the player’s view, no matter where they are looking; if you want a non view-locked UI that the user can look around, you might want to attach the plane object to the player object instead of directly to the camera. Position the plane in front of your player object, and orient it so that the top surface is facing the player. The position you choose is relevant, by the way; the Z distance from the player will affect the size of the UI onscreen.

Now set the material on the plane to be the render texture material you created before. If you have widgets set up in your UI, you should see them render in the scene view at this point, though the background of the UI will be a solid colour. Let’s fix that!


We need to make a new shader to have things render correctly when using a render texture. We want the NGUI widgets to be rendered with an alpha channel. If you’re not used to shader programming, don’t worry! This is a pretty simple thing to pull off.

NGUI holds its shaders in the folder “Assets/NGUI/Resources/Shaders”. Open this path in Windows Explorer (or Finder or whatever other strange OS you might be using!). Find the “Unlit – Transparent Colored” shader and copy it. We’ll keep the original shader so we can reuse it, of course. Rename the copy to “Unlit – Transparent Colored RTT” (RTT being “Render To Texture” if it’s not obvious). Now open the new shader in your favourite text editor (I like Sublime Text!). First, change the name at the top to “Unlit/Transparent Coloured RTT”. Next, find the line with the text “ColorMask RGB”, and delete it. That’s all there is to it! “ColorMask RGB” tells the renderer to write only RGB values and ignore the alpha channel, and by deleting it the shader will default to writing all the info we need.

Save the shader, and find your NGUI atlas in your project view inside Unity. Specifically, you want the material that it’s using, which is always stored alongside the atlas object and texture with the same name. Edit it, and change the shader to the one we just created. Now, head back to your rendering plane under the CameraRight object, and change the shader on the render texture material you created to be “Unlit/Transparent Colored”. There you go – your widgets should be rendering just how you expect them.

If you don’t see your UI, it’s time to troubleshoot!

  • Is the NGUI camera pointing to a valid render texture?
  • Is the render plane oriented correctly? Neither the plane nor the material is double-sided so it will be invisible from the wrong viewing angle.
  • Is the render plane using the correct material?
  • Is the material using the correct shader?
  • Is everything on your UI in the correct layer, and the camera culling mask is set up to include that layer?

As you can see there are a few potential points of failure so make sure to double-check everything as you go along.

Dealing With Clipping

One extra feature you might want is the ability for the UI plane to render over the environment, even if it would ordinarily be obscured by it. If you can stand to set up another shader we can fix that too!

In the NGUI shader folder, again copy “Unlit – Transparent Colored.shader” and rename the copy to “Unlit – Transparent Colored NoClip”. Edit the shader, change the name at the top to add the NoClip extension, and now look for the “Queue” line in the “Tags” group.. Change “Transparent” to “Overlay” – this tells the Unity render queue to render this object in the final group, after everything else in the world. Then find the “ZWrite Off” line, and right underneath that add “ZTest Always”. This means to always draw this material regardless of what else happens to be at that point onscreen.

Now change your render texture material (used on the plane object) to use this shader, and your UI will render on top of everything in the world. I suppose you might run into issues if you’re using fullscreen effects as they use the Overlay render queue too; I haven’t tried that out yet. Otherwise, you should have a nice-looking NGUI UI in your Rift!

, , , , , , , , , ,

  1. #1 by Clint on June 14th, 2013 - 7:05 pm

    Any tips to allow full screen image effects without impacting UI – I’m using a motion blur (easy flow) and it’s sadly impacting the UI. (This is for a stereoscopic game – not targeting rift) – Otherwise I have to find alternate solution to push UI depth into screen – Camera GUI matrix adjustments per camera maybe..

  2. #2 by AntonieB on June 19th, 2013 - 12:02 am

    Thanks for the info!! I learned a thing or two about UI’s / Shaders and got everything to work.

    Thanks for that. I have another question you can maybe help me with though.

    Where can I activate / use for example the joystick buttons or cursor keys on my keyboard to go through the menu. In the NGUI samples keyboard / joystick navigation is working great but I cant get it to work when combining with the oculus rift.

    I think it has something to do with the GUI not being active / in the view directly. Don’t know for sure though.

    Thanks in advance for reading my post :) and even more thanks if you can help me out.

  3. #3 by AntonieB on June 19th, 2013 - 9:30 am

    Forget it. I already found out I was not understanding NGUI correctly.

    Thanks anyway for your time!

  4. #4 by Jamie Fristrom on June 19th, 2013 - 8:43 pm

    Nice! Just what I was looking for. Wondering why a transparent render texture with GUITextures showed up but NGUI ones didn’t, and the overlay fix is a bonus. (We’ll see what happens when I turn my screen effects back on. :P) Let me know if there’s anything I can do for you.

  5. #5 by AntonieB on June 21st, 2013 - 6:31 am

    Here I am again. Still working on a way to present my menus in my Oculus Rift project.

    I’am using some basic buttons / now I have a problem with the render texture having ‘old buttons’ visible from the panel I hide.

    For example i’m having 3 buttons..
    [New Game]
    [ Options ]
    [ Exit ]

    and in the Options menu

    [ Reset ]
    [ Exit ]

    Now when I hide the first menu when you click / activate the Options menu the [New game] menu stays visible..

    I got the feeling it is because the render texture is not clearing things before rendering the new menu…?? But I cant get it to work correctly. (sure I can work around this by adding some background but I want just some buttons floating in front of me)

    anybody? some hints?

  6. #6 by DaveS on June 21st, 2013 - 9:46 pm

    @ AntonieB
    I think I might know what this is… try changing the camera’s Clear flags to “solid color”, then edit the color and turn alpha all the way down to zero. I had to do that too and forgot to mention it in the article!

  7. #7 by DaveS on June 21st, 2013 - 9:47 pm

    @ Jamie Fristrom
    Cool, glad to have helped in some small way!

  8. #8 by DaveS on June 21st, 2013 - 9:48 pm

    Sorry Clint, haven’t tried with screen effects yet, though I might soon.

  9. #9 by AntonieB on June 22nd, 2013 - 1:48 am

    Thanks! I was already searching in that way but somehow could’nt get it to work.

    Doing as u said now works nice!! thanks again

  1. No trackbacks yet.

Comments are closed.