Merge pull request #10908 from davidkelly/dk/hmdPreview

hmd preview
This commit is contained in:
David Kelly 2017-07-10 11:14:28 -07:00 committed by GitHub
commit 91ffb003fd
7 changed files with 69 additions and 23 deletions

View file

@ -227,7 +227,7 @@ Rectangle {
height: 250; height: 250;
color: spectatorCameraPreview.visible ? "transparent" : "black"; color: spectatorCameraPreview.visible ? "transparent" : "black";
AnimatedImage { AnimatedImage {
source: "../../images/static.gif" source: "../../images/static.gif"
@ -235,7 +235,7 @@ Rectangle {
anchors.fill: parent; anchors.fill: parent;
opacity: 0.15; opacity: 0.15;
} }
// Instructions (visible when display texture isn't set) // Instructions (visible when display texture isn't set)
FiraSansRegular { FiraSansRegular {
id: spectatorCameraInstructions; id: spectatorCameraInstructions;
@ -247,7 +247,7 @@ Rectangle {
horizontalAlignment: Text.AlignHCenter; horizontalAlignment: Text.AlignHCenter;
verticalAlignment: Text.AlignVCenter; verticalAlignment: Text.AlignVCenter;
} }
// Spectator Camera Preview // Spectator Camera Preview
Hifi.ResourceImageItem { Hifi.ResourceImageItem {
id: spectatorCameraPreview; id: spectatorCameraPreview;
@ -360,6 +360,8 @@ Rectangle {
} }
break; break;
case 'showPreviewTextureNotInstructions': case 'showPreviewTextureNotInstructions':
console.log('showPreviewTextureNotInstructions recvd', JSON.stringify(message));
spectatorCameraPreview.url = message.url;
spectatorCameraPreview.visible = message.setting; spectatorCameraPreview.visible = message.setting;
break; break;
default: default:

View file

@ -497,16 +497,26 @@ void OpenGLDisplayPlugin::submitFrame(const gpu::FramePointer& newFrame) {
_newFrameQueue.push(newFrame); _newFrameQueue.push(newFrame);
}); });
} }
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor) { void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor) {
renderFromTexture(batch, texture, viewport, scissor, gpu::FramebufferPointer());
}
void OpenGLDisplayPlugin::renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor, gpu::FramebufferPointer copyFbo /*=gpu::FramebufferPointer()*/) {
auto fbo = gpu::FramebufferPointer();
batch.enableStereo(false); batch.enableStereo(false);
batch.resetViewTransform(); batch.resetViewTransform();
batch.setFramebuffer(gpu::FramebufferPointer()); batch.setFramebuffer(fbo);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0));
batch.setStateScissorRect(scissor); batch.setStateScissorRect(scissor);
batch.setViewportTransform(viewport); batch.setViewportTransform(viewport);
batch.setResourceTexture(0, texture); batch.setResourceTexture(0, texture);
batch.setPipeline(_presentPipeline); batch.setPipeline(_presentPipeline);
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
if (copyFbo) {
gpu::Vec4i rect {0, 0, scissor.z, scissor.w};
batch.blit(fbo, rect, copyFbo, rect);
}
} }
void OpenGLDisplayPlugin::updateFrameData() { void OpenGLDisplayPlugin::updateFrameData() {

View file

@ -113,6 +113,7 @@ protected:
// Plugin specific functionality to send the composed scene to the output window or device // Plugin specific functionality to send the composed scene to the output window or device
virtual void internalPresent(); virtual void internalPresent();
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor, gpu::FramebufferPointer fbo);
void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor); void renderFromTexture(gpu::Batch& batch, const gpu::TexturePointer texture, glm::ivec4 viewport, const glm::ivec4 scissor);
virtual void updateFrameData(); virtual void updateFrameData();

View file

@ -134,7 +134,7 @@ void HmdDisplayPlugin::customizeContext() {
state->setBlendFunction(true, state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
gpu::Shader::BindingSet bindings; gpu::Shader::BindingSet bindings;
bindings.insert({ "lineData", LINE_DATA_SLOT });; bindings.insert({ "lineData", LINE_DATA_SLOT });;
gpu::Shader::makeProgram(*program, bindings); gpu::Shader::makeProgram(*program, bindings);
@ -242,7 +242,6 @@ void HmdDisplayPlugin::internalPresent() {
glm::ivec4 viewport = getViewportForSourceSize(sourceSize); glm::ivec4 viewport = getViewportForSourceSize(sourceSize);
glm::ivec4 scissor = viewport; glm::ivec4 scissor = viewport;
render([&](gpu::Batch& batch) { render([&](gpu::Batch& batch) {
if (_monoPreview) { if (_monoPreview) {
@ -287,9 +286,11 @@ void HmdDisplayPlugin::internalPresent() {
viewport.z *= 2; viewport.z *= 2;
} }
renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor); auto fbo = DependencyManager::get<TextureCache>()->getHmdPreviewFramebuffer();
renderFromTexture(batch, _compositeFramebuffer->getRenderBuffer(0), viewport, scissor, fbo);
}); });
swapBuffers(); swapBuffers();
} else if (_clearPreviewFlag) { } else if (_clearPreviewFlag) {
QImage image; QImage image;
if (_vsyncEnabled) { if (_vsyncEnabled) {
@ -312,7 +313,7 @@ void HmdDisplayPlugin::internalPresent() {
_previewTexture->assignStoredMip(0, image.byteCount(), image.constBits()); _previewTexture->assignStoredMip(0, image.byteCount(), image.constBits());
_previewTexture->setAutoGenerateMips(true); _previewTexture->setAutoGenerateMips(true);
} }
auto viewport = getViewportForSourceSize(uvec2(_previewTexture->getDimensions())); auto viewport = getViewportForSourceSize(uvec2(_previewTexture->getDimensions()));
render([&](gpu::Batch& batch) { render([&](gpu::Batch& batch) {
@ -323,7 +324,7 @@ void HmdDisplayPlugin::internalPresent() {
} }
postPreview(); postPreview();
// If preview is disabled, we need to check to see if the window size has changed // If preview is disabled, we need to check to see if the window size has changed
// and re-render the no-preview message // and re-render the no-preview message
if (_disablePreview) { if (_disablePreview) {
auto window = _container->getPrimaryWidget(); auto window = _container->getPrimaryWidget();
@ -510,7 +511,7 @@ void HmdDisplayPlugin::OverlayRenderer::build() {
indices = std::make_shared<gpu::Buffer>(); indices = std::make_shared<gpu::Buffer>();
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
static const float fov = CompositorHelper::VIRTUAL_UI_TARGET_FOV.y; static const float fov = CompositorHelper::VIRTUAL_UI_TARGET_FOV.y;
static const float aspectRatio = CompositorHelper::VIRTUAL_UI_ASPECT_RATIO; static const float aspectRatio = CompositorHelper::VIRTUAL_UI_ASPECT_RATIO;
static const uint16_t stacks = 128; static const uint16_t stacks = 128;
@ -672,7 +673,7 @@ bool HmdDisplayPlugin::setHandLaser(uint32_t hands, HandLaserMode mode, const ve
_handLasers[1] = info; _handLasers[1] = info;
} }
}); });
// FIXME defer to a child class plugin to determine if hand lasers are actually // FIXME defer to a child class plugin to determine if hand lasers are actually
// available based on the presence or absence of hand controllers // available based on the presence or absence of hand controllers
return true; return true;
} }
@ -687,7 +688,7 @@ bool HmdDisplayPlugin::setExtraLaser(HandLaserMode mode, const vec4& color, cons
_extraLaserStart = sensorSpaceStart; _extraLaserStart = sensorSpaceStart;
}); });
// FIXME defer to a child class plugin to determine if hand lasers are actually // FIXME defer to a child class plugin to determine if hand lasers are actually
// available based on the presence or absence of hand controllers // available based on the presence or absence of hand controllers
return true; return true;
} }
@ -702,7 +703,7 @@ void HmdDisplayPlugin::compositeExtra() {
if (_presentHandPoses[0] == IDENTITY_MATRIX && _presentHandPoses[1] == IDENTITY_MATRIX && !_presentExtraLaser.valid()) { if (_presentHandPoses[0] == IDENTITY_MATRIX && _presentHandPoses[1] == IDENTITY_MATRIX && !_presentExtraLaser.valid()) {
return; return;
} }
render([&](gpu::Batch& batch) { render([&](gpu::Batch& batch) {
batch.setFramebuffer(_compositeFramebuffer); batch.setFramebuffer(_compositeFramebuffer);
batch.setModelTransform(Transform()); batch.setModelTransform(Transform());

View file

@ -54,6 +54,7 @@ const std::string TextureCache::KTX_EXT { "ktx" };
static const QString RESOURCE_SCHEME = "resource"; static const QString RESOURCE_SCHEME = "resource";
static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame"); static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame");
static const QUrl HMD_PREVIEW_FRAME_URL("resource://hmdPreviewFrame");
static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first static const float SKYBOX_LOAD_PRIORITY { 10.0f }; // Make sure skybox loads first
static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models static const float HIGH_MIPS_LOAD_PRIORITY { 9.0f }; // Make sure high mips loads after skybox but before models
@ -969,7 +970,6 @@ void ImageReader::read() {
Q_ARG(int, texture->getHeight())); Q_ARG(int, texture->getHeight()));
} }
NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) { NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) {
gpu::TexturePointer texture; gpu::TexturePointer texture;
if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) { if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) {
@ -984,10 +984,30 @@ NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl)
} }
} }
} }
// FIXME: Generalize this, DRY up this code
if (resourceTextureUrl == HMD_PREVIEW_FRAME_URL) {
if (!_hmdPreviewNetworkTexture) {
_hmdPreviewNetworkTexture.reset(new NetworkTexture(resourceTextureUrl));
}
if (_hmdPreviewFramebuffer) {
texture = _hmdPreviewFramebuffer->getRenderBuffer(0);
if (texture) {
_hmdPreviewNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight());
return _hmdPreviewNetworkTexture;
}
}
}
return NetworkTexturePointer(); return NetworkTexturePointer();
} }
const gpu::FramebufferPointer& TextureCache::getHmdPreviewFramebuffer() {
if (!_hmdPreviewFramebuffer) {
_hmdPreviewFramebuffer.reset(gpu::Framebuffer::create("hmdPreview",gpu::Element::COLOR_SRGBA_32, 2040, 1024));
}
return _hmdPreviewFramebuffer;
}
const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() { const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() {
if (!_spectatorCameraFramebuffer) { if (!_spectatorCameraFramebuffer) {
resetSpectatorCameraFramebuffer(2048, 1024); resetSpectatorCameraFramebuffer(2048, 1024);

View file

@ -74,7 +74,7 @@ protected:
virtual bool isCacheable() const override { return _loaded; } virtual bool isCacheable() const override { return _loaded; }
virtual void downloadFinished(const QByteArray& data) override; virtual void downloadFinished(const QByteArray& data) override;
Q_INVOKABLE void loadContent(const QByteArray& content); Q_INVOKABLE void loadContent(const QByteArray& content);
Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight); Q_INVOKABLE void setImage(gpu::TexturePointer texture, int originalWidth, int originalHeight);
@ -170,6 +170,7 @@ public:
NetworkTexturePointer getResourceTexture(QUrl resourceTextureUrl); NetworkTexturePointer getResourceTexture(QUrl resourceTextureUrl);
const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(); const gpu::FramebufferPointer& getSpectatorCameraFramebuffer();
void resetSpectatorCameraFramebuffer(int width, int height); void resetSpectatorCameraFramebuffer(int width, int height);
const gpu::FramebufferPointer& getHmdPreviewFramebuffer();
protected: protected:
// Overload ResourceCache::prefetch to allow specifying texture type for loads // Overload ResourceCache::prefetch to allow specifying texture type for loads
@ -202,6 +203,9 @@ private:
NetworkTexturePointer _spectatorCameraNetworkTexture; NetworkTexturePointer _spectatorCameraNetworkTexture;
gpu::FramebufferPointer _spectatorCameraFramebuffer; gpu::FramebufferPointer _spectatorCameraFramebuffer;
NetworkTexturePointer _hmdPreviewNetworkTexture;
gpu::FramebufferPointer _hmdPreviewFramebuffer;
}; };
#endif // hifi_TextureCache_h #endif // hifi_TextureCache_h

View file

@ -19,7 +19,7 @@
onTabletButtonClicked, wireEventBridge, startup, shutdown, registerButtonMappings; onTabletButtonClicked, wireEventBridge, startup, shutdown, registerButtonMappings;
// Function Name: inFrontOf() // Function Name: inFrontOf()
// //
// Description: // Description:
// -Returns the position in front of the given "position" argument, where the forward vector is based off // -Returns the position in front of the given "position" argument, where the forward vector is based off
// the "orientation" argument and the amount in front is based off the "distance" argument. // the "orientation" argument and the amount in front is based off the "distance" argument.
@ -29,7 +29,7 @@
} }
// Function Name: spectatorCameraOn() // Function Name: spectatorCameraOn()
// //
// Description: // Description:
// -Call this function to set up the spectator camera and // -Call this function to set up the spectator camera and
// spawn the camera entity. // spawn the camera entity.
@ -103,7 +103,7 @@
} }
// Function Name: spectatorCameraOff() // Function Name: spectatorCameraOff()
// //
// Description: // Description:
// -Call this function to shut down the spectator camera and // -Call this function to shut down the spectator camera and
// destroy the camera entity. // destroy the camera entity.
@ -218,9 +218,17 @@
// 3. Camera is on; "Monitor Shows" is "HMD Preview": "url" is "" // 3. Camera is on; "Monitor Shows" is "HMD Preview": "url" is ""
// 4. Camera is on; "Monitor Shows" is "Camera View": "url" is "resource://spectatorCameraFrame" // 4. Camera is on; "Monitor Shows" is "Camera View": "url" is "resource://spectatorCameraFrame"
function setDisplay(showCameraView) { function setDisplay(showCameraView) {
var url = (camera && showCameraView) ? "resource://spectatorCameraFrame" : "";
sendToQml({ method: 'showPreviewTextureNotInstructions', setting: !!url }); var url = (camera) ? (showCameraView ? "resource://spectatorCameraFrame" : "resource://hmdPreviewFrame") : "";
Window.setDisplayTexture(url); sendToQml({ method: 'showPreviewTextureNotInstructions', setting: !!url, url: url});
// FIXME: temporary hack to avoid setting the display texture to hmdPreviewFrame
// until it is the correct mono.
if (url === "resource://hmdPreviewFrame") {
Window.setDisplayTexture("");
} else {
Window.setDisplayTexture(url);
}
} }
const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false; const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false;
var monitorShowsCameraView = !!Settings.getValue('spectatorCamera/monitorShowsCameraView', MONITOR_SHOWS_CAMERA_VIEW_DEFAULT); var monitorShowsCameraView = !!Settings.getValue('spectatorCamera/monitorShowsCameraView', MONITOR_SHOWS_CAMERA_VIEW_DEFAULT);
@ -421,7 +429,7 @@
} }
// Function Name: onHMDChanged() // Function Name: onHMDChanged()
// //
// Description: // Description:
// -Called from C++ when HMD mode is changed. The argument "isHMDMode" should be true if HMD is on; false otherwise. // -Called from C++ when HMD mode is changed. The argument "isHMDMode" should be true if HMD is on; false otherwise.
function onHMDChanged(isHMDMode) { function onHMDChanged(isHMDMode) {
@ -433,7 +441,7 @@
} }
// Function Name: shutdown() // Function Name: shutdown()
// //
// Description: // Description:
// -shutdown() will be called when the script ends (i.e. is stopped). // -shutdown() will be called when the script ends (i.e. is stopped).
function shutdown() { function shutdown() {