Search Issue Tracker

Fixed in 5.6.0

Votes

0

Found in

Issue ID

845647

Regression

No

[VR] Camera Preview window broken in Play mode

VR

-

The 'Camera Preview' window that's supposed to pop up when you select the camera doesn't work when in Play mode, and VR is enabled.

If you are just using the editor, you'll see assert information fire at the bottom of the window (Assertion failed on expression: 'tex->GetWidth() == width && tex->GetHeight() == height'). This is triggered from RenderBufferManager::GetTempBuffer. This is because width is 0, and tex->GetWidth() is 1. The reason the width is 1 is that the camera's NormalizedViewportRect gets corrupted due to a bad interaction with the stereo target rects and the Scene window rect.

The bad interactions start all the way in the built in UI scripts, with CameraEditor.cs. OnOverlayGUI is responsible for whipping up some of the bits for the Camera Preview window, particularly the portion of the Scene view to reserve. It generates a size that corresponds to a scaled down version of the Scene view, and requests a rect of that size from GUILayoutUtility. This rect is then used to set the pixelRect of the previewCamera. Setting the pixel rect (in screen space coordinates) invokes the camera bindings that configure the normalized viewport settings (placed in Camera::m_State.m_NormalizedViewportRect).

To use some sample numbers, let's say our scene view is 1200x600. And our requested preview cam rect ends up being 300x150, located at 800,10 (lower right, assuming lower left is origin). This gets converted to normalized w/h ~0.25,~0.25 and x/y ~0.66, ~0.017.

However, in VR, setting this previewCamera.pixelRect blows up.

The setup is the same, as far as requesting a rect. (This process is also debatably wrong, as it requests a non-VR eye ratio rect to render the preview into, which doesn't seem right. Also...it does actually seem to 'render' the scene, which also doesn't make sense inside of Play mode. Shouldn't it just copy over a scaled version of the output into the actual Game view, if it's the main camera? However, the correct functionality can be determined later.) So it will request a rect of 300x150, and get a rect located at 800,10.

When this is pushed into the camera (via previewCamera.pixelRect = cameraRect;), the engine code takes over and sends in the new pixel rect to Camera::SetScreenViewportRect. This is where it all blows up.

In SetScreenViewportRect, we get the target rect pixel coordinates, and then we use our new pixelRect values to generate normalized viewport values, relative to our target rect. To get our target rect, we call GetCameraTargetRect. In the non-VR path, it ends up getting a rect from GetScreenManager. But in the VR path (at least in Play mode), we hit a path that checks if stereo is enabled on the camera (Camera::GetStereoEnabled). This ends up returning true, as these conditions are enough to pass the check:
1) VR is active
2) Camera::GetTargetTexture() == NULL
3) Camera::m_State.m_TargetEye = Both

This passes the VR check, and then we make a rect that matches the size of a VR eye texture. We return this rect as the result from GetCameraTargetRect. Using our example, this rect would be 600x600.

Once this gets returned to SetScreenViewportRect, we generate some bad values for our normalized viewport values (since our requested x location of 800 is outside the bounds of the VR eye target width of 600). This ends up generating a bad aspect ratio here, and then later on down the line, when we call into Camera::StandaloneRender, we end up generating a camera rect of 0 width. And this blows everything up.

Add comment

Log in to post comment

All about bugs

View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.