Merge pull request #10678 from zfox23/spectatorCamera_improvements1

Secondary camera and rendering improvements
This commit is contained in:
Zach Fox 2017-06-14 14:39:38 -07:00 committed by GitHub
commit f214712b33
4 changed files with 46 additions and 18 deletions

View file

@ -42,6 +42,9 @@ void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int he
class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and and view.
glm::vec3 _position{};
glm::quat _orientation{};
float _vFoV{};
float _nearClipPlaneDistance{};
float _farClipPlaneDistance{};
public:
using Config = BeginSecondaryCameraFrameConfig;
using JobModel = render::Job::ModelO<BeginSecondaryCameraFrame, RenderArgsPointer, Config>;
@ -53,6 +56,9 @@ public:
if (config.enabled || config.alwaysEnabled) {
_position = config.position;
_orientation = config.orientation;
_vFoV = config.vFoV;
_nearClipPlaneDistance = config.nearClipPlaneDistance;
_farClipPlaneDistance = config.farClipPlaneDistance;
}
}
@ -62,7 +68,6 @@ public:
gpu::FramebufferPointer destFramebuffer;
destFramebuffer = textureCache->getSpectatorCameraFramebuffer(); // FIXME: Change the destination based on some unimplemented config var
if (destFramebuffer) {
// Caching/restoring the old values doesn't seem to be needed. Is it because we happen to be last in the pipeline (which would be a bug waiting to happen)?
_cachedArgsPointer->_blitFramebuffer = args->_blitFramebuffer;
_cachedArgsPointer->_viewport = args->_viewport;
_cachedArgsPointer->_displayMode = args->_displayMode;
@ -77,6 +82,10 @@ public:
auto srcViewFrustum = args->getViewFrustum();
srcViewFrustum.setPosition(_position);
srcViewFrustum.setOrientation(_orientation);
srcViewFrustum.setProjection(glm::perspective(glm::radians(_vFoV), ((float)args->_viewport.z / (float)args->_viewport.w), _nearClipPlaneDistance, _farClipPlaneDistance));
// Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera,
// which is not what we want here.
srcViewFrustum.calculate();
args->pushViewFrustum(srcViewFrustum);
cachedArgs = _cachedArgsPointer;
}

View file

@ -29,13 +29,19 @@ public:
void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true);
};
class BeginSecondaryCameraFrameConfig : public render::Task::Config { // Exposes view frustum position/orientation to javascript.
class BeginSecondaryCameraFrameConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript.
Q_OBJECT
Q_PROPERTY(glm::vec3 position MEMBER position NOTIFY dirty) // of viewpoint to render from
Q_PROPERTY(glm::quat orientation MEMBER orientation NOTIFY dirty) // of viewpoint to render from
Q_PROPERTY(float vFoV MEMBER vFoV NOTIFY dirty) // Secondary camera's vertical field of view. In degrees.
Q_PROPERTY(float nearClipPlaneDistance MEMBER nearClipPlaneDistance NOTIFY dirty) // Secondary camera's near clip plane distance. In meters.
Q_PROPERTY(float farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters.
public:
glm::vec3 position{};
glm::quat orientation{};
float vFoV{ 45.0f };
float nearClipPlaneDistance{ 0.1f };
float farClipPlaneDistance{ 100.0f };
BeginSecondaryCameraFrameConfig() : render::Task::Config(false) {}
signals:
void dirty();

View file

@ -119,7 +119,7 @@ void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const Stereo
size_t offset = _cameraUboSize * _cameras.size();
_cameraOffsets.push_back(TransformStageState::Pair(commandIndex, offset));
if (stereo._enable) {
if (stereo.isStereo()) {
#ifdef GPU_STEREO_CAMERA_BUFFER
_cameras.push_back(CameraBufferElement(_camera.getEyeCamera(0, stereo, _view), _camera.getEyeCamera(1, stereo, _view)));
#else
@ -151,7 +151,7 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
#ifdef GPU_STEREO_CAMERA_BUFFER
bindCurrentCamera(0);
#else
if (!stereo._enable) {
if (!stereo.isStereo()) {
bindCurrentCamera(0);
}
#endif

View file

@ -22,7 +22,7 @@
//
// Function Name: inFrontOf(), flip()
// Function Name: inFrontOf()
//
// Description:
// Spectator camera utility functions and variables.
@ -31,8 +31,6 @@
return Vec3.sum(position || MyAvatar.position,
Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation)));
}
var aroundY = Quat.fromPitchYawRollDegrees(0, 180, 0);
function flip(rotation) { return Quat.multiply(rotation, aroundY); }
//
// Function Name: updateRenderFromCamera()
@ -73,10 +71,6 @@
lastCameraPosition = cameraData.position;
beginSpectatorFrameRenderConfig.position = Vec3.sum(inFrontOf(0.17, lastCameraPosition, lastCameraRotation), {x: 0, y: 0.02, z: 0});
}
if (cameraIsDynamic) {
// BUG: image3d overlays don't retain their locations properly when parented to a dynamic object
Overlays.editOverlay(viewFinderOverlay, { orientation: flip(cameraData.rotation) });
}
}
//
@ -85,6 +79,11 @@
// Relevant Variables:
// isUpdateRenderWired: Bool storing whether or not the camera's update
// function is wired.
// windowAspectRatio: The ratio of the Interface windows's sizeX/sizeY
// previewAspectRatio: The ratio of the camera preview's sizeX/sizeY
// vFoV: The vertical field of view of the spectator camera
// nearClipPlaneDistance: The near clip plane distance of the spectator camera
// farClipPlaneDistance: The far clip plane distance of the spectator camera
//
// Arguments:
// None
@ -94,11 +93,22 @@
// spawn the camera entity.
//
var isUpdateRenderWired = false;
var windowAspectRatio;
var previewAspectRatio = 16 / 9;
var vFoV = 45.0;
var nearClipPlaneDistance = 0.1;
var farClipPlaneDistance = 100.0;
function spectatorCameraOn() {
// Set the special texture size based on the window in which it will eventually be displayed.
var size = Controller.getViewportDimensions(); // FIXME: Need a signal to hook into when the dimensions change.
spectatorFrameRenderConfig.resetSizeSpectatorCamera(size.x, size.y);
var sizeX = Window.innerWidth;
var sizeY = Window.innerHeight;
windowAspectRatio = sizeX/sizeY;
spectatorFrameRenderConfig.resetSizeSpectatorCamera(sizeX, sizeY);
spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = true;
beginSpectatorFrameRenderConfig.vFoV = vFoV;
beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance;
beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance;
var cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 }));
Script.update.connect(updateRenderFromCamera);
isUpdateRenderWired = true;
@ -132,14 +142,17 @@
parentID: camera,
alpha: 1,
position: { x: 0.007, y: 0.15, z: -0.005 },
scale: -0.16,
dimensions: { x: 0.16, y: -0.16 * windowAspectRatio / previewAspectRatio, z: 0 }
// Negative dimension for viewfinder is necessary for now due to the way Image3DOverlay
// draws textures.
// See Image3DOverlay.cpp:91. If you change the two lines there to:
// glm::vec2 topLeft(-x, -y);
// glm::vec2 bottomRight(x, y);
// the viewfinder will appear rightside up without this negative y-dimension.
// However, other Image3DOverlay textures (like the PAUSED one) will appear upside-down. *Why?*
// FIXME: This code will stretch the preview as the window aspect ratio changes. Fix that!
});
Entities.editEntity(camera, { position: cameraPosition, rotation: cameraRotation });
// FIXME: We shouldn't need the flip and the negative scale.
// e.g., This isn't necessary using an ordinary .jpg with lettering, above.
// Must be something about the view frustum projection matrix?
// But don't go changing that in (c++ code) without getting all the way to a desktop display!
Overlays.editOverlay(viewFinderOverlay, { orientation: flip(cameraRotation) });
setDisplay(monitorShowsCameraView);
}