Ok, here’s the setup:
You need to duplicate your VR eye camera, and place it above the “Camera (head)” gameobject so that SteamVR_Camera.cs on the main VR eye camera won’t destroy it. Remove SteamVR_Camera.cs from the duplicated camera. Set the main VR eye camera’s target eye to Left Eye, and the duplicated camera’s target eye to Right Eye. Then you need to set up a layer mask for portal left eye and a layer mask for portal right eye. Make sure the left eye has the portal left eye layer in its culling mask, and that it doesn’t have the portal right eye layer mask. And do the opposite for the right eye camera.
Then you need to duplicate your portal gameobject and its material. Set one portal to be on the portal left eye layer mask, and the other portal to be on the portal right eye layer mask.
Then you need to duplicate your portal camera. You know the drill: one for the left eye, and one for the right. The RenderTexture for the left portal camera needs to be fed into the left portal material, and the RenderTexture for the right portal camera needs to be fed into the right portal material.
And now the code… Just like in your github portal project, disable the portal cameras. On the portal gameobjects, have an OnWillRenderObject() method where you call a function on a script you’ve created on your portal camera gameobjects that will render their cameras, making sure it has the correct left or right portal camera reference.
private void Start() { Valve.VR.EVREye eye; if (isLeftEye) { eye = Valve.VR.EVREye.Eye_Left; } else { eye = Valve.VR.EVREye.Eye_Right; } _cameraForPortal.projectionMatrix = HMDMatrix4x4ToMatrix4x4(SteamVR.instance.hmd.GetProjectionMatrix(eye, _vrEye.nearClipPlane, _vrEye.farClipPlane, Valve.VR.EGraphicsAPIConvention.API_DirectX)); } private Matrix4x4 HMDMatrix4x4ToMatrix4x4(Valve.VR.HmdMatrix44_t input) { var m = Matrix4x4.identity; m[0, 0] = input.m0; m[0, 1] = input.m1; m[0, 2] = input.m2; m[0, 3] = input.m3; m[1, 0] = input.m4; m[1, 1] = input.m5; m[1, 2] = input.m6; m[1, 3] = input.m7; m[2, 0] = input.m8; m[2, 1] = input.m9; m[2, 2] = input.m10; m[2, 3] = input.m11; m[3, 0] = input.m12; m[3, 1] = input.m13; m[3, 2] = input.m14; m[3, 3] = input.m15; return m; }
And lastly, you need to grab the position of each eye and position the camera accordingly, on the script I mentioned above that you’ve got on each portal camera:
public void Render() { // in my script, _vrEye is a reference to the main VR eye. the one with SteamVR_Camera.cs on it. if (Camera.current == _vrEye) { Vector3 eyeOffset = Vector3.zero; if (isLeftEye) { eyeOffset = SteamVR.instance.eyes[0].pos; } else { eyeOffset = SteamVR.instance.eyes[1].pos; } transform.localPosition = _vrEye.transform.position + _vrEye.transform.TransformVector(eyeOffset); transform.localRotation = _vrEye.transform.localRotation; _cameraForPortal.Render(); } }
Some of that is specific to my own project, so it won’t be just copy and paste. But the above is how I made it work in my project
As you can see, it’s way more convoluted than what you were able to pull off in your github portal project. I’m still holding out hope for a better solution. Perhaps there’s some clever way to draw a RenderTexture double-wide, and then send that to a camera with Target Eye set to Both, and have it correctly render each half in one eye?
Since I’ve now got 2 main VR cameras, one set to render to the left eye, and one set to render to the right eye, I’m not sure if I’m really getting the full performance benefit of native OpenVR anymore. Maybe I am? My frame rate is pretty smooth as is, so it’s hard to tell if I’m losing anything this way. I didn’t see a frame rate drop when I implemented it this way.
If anyone’s got a more clever idea, I’m all ears!
////////////////////////////////////////
On the portal camera gameobjects, you need to set the projection matrix specific to each eye (you can’t just take the main VR camera’s projection matrix and use it on both eyes):
I looked into this some more and thep3000 is right, it was just a projection matrix problem. The solution is simple – when you render to a render texture, set your camera’s projection matrix to be the vive’s projection matrix. Query the device and then if Vive is detected, assign the projection matrix as shown in this thread:
https://steamcommunity.com/app/358720/discussions/0/405694031550581171/#c405694031552884526
The only thing I did differently was using namespace Valve.VR and then calling:
OpenVR.System.GetProjectionMatrix(vrEye, mainCamera.nearClipPlane, mainCamera.farClipPlane, EGraphicsAPIConvention.API_DirectX)
///////////////////////////////////
Render Second Camera – UI
Rework Selector & Attractor Prefabs
Radius Inner – Radius Outer
/////////////////////////////////