kurohuku
Posted on June 16, 2024
Prepare an image file
Prepare an image file that satisfies the following conditions.
- Size is lower than 1920 x 1080 px.
- File format is in PNG, JPG, or TGA (24 or 32 bit color)
From here on, I explain with my SNS icon named “sns-icon.jpg”.
Put the image file inside Assets/StreamingAssets folder.
Draw image
Call SetOverlayFromFile() to draw an image file. (read the wiki for details)
void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
+ var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
+ var error = OpenVR.Overlay.SetOverlayFromFile(overlayHandle, filePath);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to draw image file: " + error);
+ }
}
Pass the overlay handle and image file path to SetOverlayFromFile()
.
We use the StreamingAssets folder to get the file path at runtime with Application.streamingAssetsPath.
Error handling remains the same as before.
Run the program, then launch the Overlay Viewer.
Click WatchOverlayKey
and check the image is drawing on the right preview area.
Switch overlay visibility
The overlay is hidden by default. It is shown on the Overlay Viewer but not in the VR space.
Switch the overlay visibility with ShowOverlay() and HideOverlay(). (read the wiki for details)
Let’s show the overlay with ShowOverlay()
at the start of the application.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
var error = OpenVR.Overlay.SetOverlayFromFile(overlayHandle, filePath);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to draw image file: " + error);
}
+ error = OpenVR.Overlay.ShowOverlay(overlayHandle);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to show overlay: " + error);
+ }
}
Run the program, put on your HMD, and look down at the floor. The overlay should appear at the center of the floor. Since overlays can’t be seen from the back, if you can’t view the overlay, move to the opposite side.
It shows during a VR game (the screenshot is Legendary Tales)
Organize code
Draw image file
Move the drawing code into SetOverlayFromFile()
.
void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
- var error = OpenVR.Overlay.SetOverlayFromFile(overlayHandle, filePath);
- if (error != EVROverlayError.None)
- {
- throw new Exception("Failed to draw image file: " + error);
- }
+ SetOverlayFromFile(overlayHandle, filePath);
error = OpenVR.Overlay.ShowOverlay(overlayHandle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to show overlay: " + error);
}
}
...
+ // Variable names changed
+ // overlayHandle -> handle
+ // filePath -> path
+ private void SetOverlayFromFile(ulong handle, string path)
+ {
+ var error = OpenVR.Overlay.SetOverlayFromFile(handle, path);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to draw image file: " + error);
+ }
+ }
Show overlay
Move the switching overlay visibility into ShowOverlay()
.
void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
- error = OpenVR.Overlay.ShowOverlay(overlayHandle);
- if (error != EVROverlayError.None)
- {
- throw new Exception("Failed to show overlay: " + error);
- }
+ ShowOverlay(overlayHandle);
}
...
+ private void ShowOverlay(ulong handle)
+ {
+ var error = OpenVR.Overlay.ShowOverlay(handle);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to show overlay: " + error);
+ }
+ }
}
Final code
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private ulong overlayHandle = OpenVR.k_ulOverlayHandleInvalid;
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
ShowOverlay(overlayHandle);
}
private void OnApplicationQuit()
{
DestroyOverlay(overlayHandle);
}
private void OnDestroy()
{
ShutdownOpenVR();
}
private void InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
private void ShutdownOpenVR()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
private ulong CreateOverlay(string key, string name)
{
var handle = OpenVR.k_ulOverlayHandleInvalid;
var error = OpenVR.Overlay.CreateOverlay(key, name, ref handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to create overlay: " + error);
}
return handle;
}
private void DestroyOverlay(ulong handle)
{
if (handle != OpenVR.k_ulOverlayHandleInvalid)
{
var error = OpenVR.Overlay.DestroyOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to dispose overlay: " + error);
}
}
}
private void SetOverlayFromFile(ulong handle, string path)
{
var error = OpenVR.Overlay.SetOverlayFromFile(handle, path);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to draw image file: " + error);
}
}
private void ShowOverlay(ulong handle)
{
var error = OpenVR.Overlay.ShowOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to show overlay: " + error);
}
}
}
Here, we have displayed the image on the overlay. Next part, we will change the overlay size and position.
Posted on June 16, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.