From 7aef4dab4c26f4d8f6c76f9bffaad20958a52f27 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 7 Jun 2017 11:02:23 -0700 Subject: [PATCH 1/7] Variable renaming pass --- interface/src/Application.cpp | 4 +- ...rototypeSelfie.cpp => SecondaryCamera.cpp} | 26 +++++------ .../{PrototypeSelfie.h => SecondaryCamera.h} | 20 ++++----- .../src/model-networking/TextureCache.cpp | 44 +++++++++---------- .../src/model-networking/TextureCache.h | 18 ++++---- scripts/system/spectatorCamera.js | 8 ++-- 6 files changed, 59 insertions(+), 61 deletions(-) rename interface/src/{PrototypeSelfie.cpp => SecondaryCamera.cpp} (77%) rename interface/src/{PrototypeSelfie.h => SecondaryCamera.h} (63%) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e831d39a6..f116b5fd6d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -114,7 +114,7 @@ #include #include #include -#include +#include #include #include #include @@ -1874,7 +1874,7 @@ void Application::initializeGL() { } _renderEngine->addJob("MainFrame", cullFunctor, isDeferred); - _renderEngine->addJob("SelfieFrame", cullFunctor); + _renderEngine->addJob("SecondaryCameraFrame", cullFunctor); /* _renderEngine->addJob("RenderShadowTask", cullFunctor); diff --git a/interface/src/PrototypeSelfie.cpp b/interface/src/SecondaryCamera.cpp similarity index 77% rename from interface/src/PrototypeSelfie.cpp rename to interface/src/SecondaryCamera.cpp index 6b719a12de..c6f7526256 100644 --- a/interface/src/PrototypeSelfie.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -1,5 +1,5 @@ -#include "PrototypeSelfie.h" +#include "SecondaryCamera.h" #include @@ -20,21 +20,21 @@ void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render using RenderArgsPointer = std::shared_ptr; -void SelfieRenderTaskConfig::resetSize(int width, int height) { // Carefully adjust the framebuffer / texture. +void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // Carefully adjust the framebuffer / texture. bool wasEnabled = isEnabled(); setEnabled(false); auto textureCache = DependencyManager::get(); - textureCache->resetSelfieFramebuffer(width, height); + textureCache->resetSecondaryCameraFramebuffer(width, height); setEnabled(wasEnabled); } -class BeginSelfieFrame { // Changes renderContext for our framebuffer and and view. +class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and and view. glm::vec3 _position{}; glm::quat _orientation{}; public: - using Config = BeginSelfieFrameConfig; - using JobModel = render::Job::ModelO; - BeginSelfieFrame() { + using Config = BeginSecondaryCameraFrameConfig; + using JobModel = render::Job::ModelO; + BeginSecondaryCameraFrame() { _cachedArgsPointer = std::make_shared(_cachedArgs); } @@ -48,7 +48,7 @@ public: void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) { auto args = renderContext->args; auto textureCache = DependencyManager::get(); - auto destFramebuffer = textureCache->getSelfieFramebuffer(); + auto destFramebuffer = textureCache->getSecondaryCameraFramebuffer(); // 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; @@ -76,9 +76,9 @@ protected: RenderArgsPointer _cachedArgsPointer; }; -class EndSelfieFrame { // Restores renderContext. +class EndSecondaryCameraFrame { // Restores renderContext. public: - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; void run(const render::RenderContextPointer& renderContext, const RenderArgsPointer& cachedArgs) { auto args = renderContext->args; @@ -93,10 +93,10 @@ public: } }; -void SelfieRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor) { - const auto cachedArg = task.addJob("BeginSelfie"); +void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor) { + const auto cachedArg = task.addJob("BeginSecondaryCamera"); const auto items = task.addJob("FetchCullSort", cullFunctor); assert(items.canCast()); task.addJob("RenderDeferredTask", items); - task.addJob("EndSelfie", cachedArg); + task.addJob("EndSecondaryCamera", cachedArg); } \ No newline at end of file diff --git a/interface/src/PrototypeSelfie.h b/interface/src/SecondaryCamera.h similarity index 63% rename from interface/src/PrototypeSelfie.h rename to interface/src/SecondaryCamera.h index 7bb9bbe861..f68a65dd12 100644 --- a/interface/src/PrototypeSelfie.h +++ b/interface/src/SecondaryCamera.h @@ -1,6 +1,6 @@ #pragma once -#ifndef hifi_PrototypeSelfie_h -#define hifi_PrototypeSelfie_h +#ifndef hifi_SecondaryCamera_h +#define hifi_SecondaryCamera_h #include #include @@ -18,33 +18,33 @@ public: void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true); }; -class BeginSelfieFrameConfig : public render::Task::Config { // Exposes view frustum position/orientation to javascript. +class BeginSecondaryCameraFrameConfig : public render::Task::Config { // Exposes view frustum position/orientation 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 public: glm::vec3 position{}; glm::quat orientation{}; - BeginSelfieFrameConfig() : render::Task::Config(false) {} + BeginSecondaryCameraFrameConfig() : render::Task::Config(false) {} signals: void dirty(); }; -class SelfieRenderTaskConfig : public render::Task::Config { +class SecondaryCameraRenderTaskConfig : public render::Task::Config { Q_OBJECT public: - SelfieRenderTaskConfig() : render::Task::Config(false) {} + SecondaryCameraRenderTaskConfig() : render::Task::Config(false) {} signals: void dirty(); public slots: void resetSize(int width, int height); }; -class SelfieRenderTask { +class SecondaryCameraRenderTask { public: - using Config = SelfieRenderTaskConfig; - using JobModel = render::Task::Model; - SelfieRenderTask() {} + using Config = SecondaryCameraRenderTaskConfig; + using JobModel = render::Task::Model; + SecondaryCameraRenderTask() {} void configure(const Config& config) {} void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor); }; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 0a291a79ec..f64b917520 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,7 +50,7 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; const std::string TextureCache::KTX_EXT { "ktx" }; -const std::string TextureCache::SELFIE_FRAME_URL { "http://selfieFrame" }; +const std::string TextureCache::SECONDARY_CAMERA_FRAME_URL { "http://secondaryCameraFrame" }; 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 @@ -182,9 +182,9 @@ ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNum } NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { - if (url == QUrl(SELFIE_FRAME_URL.c_str())) { + if (url == QUrl(SECONDARY_CAMERA_FRAME_URL.c_str())) { - return getSelfieNetworkTexture(); + return getSecondaryCameraNetworkTexture(); } TextureExtra extra = { type, content, maxNumPixels }; return ResourceCache::getResource(url, QUrl(), &extra).staticCast(); @@ -885,31 +885,31 @@ void ImageReader::read() { } -NetworkTexturePointer TextureCache::getSelfieNetworkTexture() { - if (!_selfieNetworkTexture) { - _selfieNetworkTexture.reset(new NetworkTexture(QUrl(SELFIE_FRAME_URL.c_str()))); - auto texture = getSelfieTexture(); - _selfieNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); +NetworkTexturePointer TextureCache::getSecondaryCameraNetworkTexture() { + if (!_secondaryCameraNetworkTexture) { + _secondaryCameraNetworkTexture.reset(new NetworkTexture(QUrl(SECONDARY_CAMERA_FRAME_URL.c_str()))); + auto texture = getSecondaryCameraTexture(); + _secondaryCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); } - return _selfieNetworkTexture; + return _secondaryCameraNetworkTexture; } -const gpu::TexturePointer& TextureCache::getSelfieTexture() { - if (!_selfieTexture) { - getSelfieFramebuffer(); +const gpu::TexturePointer& TextureCache::getSecondaryCameraTexture() { + if (!_secondaryCameraTexture) { + getSecondaryCameraFramebuffer(); } - return _selfieTexture; + return _secondaryCameraTexture; } -const gpu::FramebufferPointer& TextureCache::getSelfieFramebuffer() { - if (!_selfieFramebuffer) { - resetSelfieFramebuffer(2048, 1024); +const gpu::FramebufferPointer& TextureCache::getSecondaryCameraFramebuffer() { + if (!_secondaryCameraFramebuffer) { + resetSecondaryCameraFramebuffer(2048, 1024); } - return _selfieFramebuffer; + return _secondaryCameraFramebuffer; } -void TextureCache::resetSelfieFramebuffer(int width, int height) { - _selfieFramebuffer.reset(gpu::Framebuffer::create("selfie", gpu::Element::COLOR_SRGBA_32, 2048, 1024)); - _selfieTexture = _selfieFramebuffer->getRenderBuffer(0); - _selfieNetworkTexture.reset(); -} \ No newline at end of file +void TextureCache::resetSecondaryCameraFramebuffer(int width, int height) { + _secondaryCameraFramebuffer.reset(gpu::Framebuffer::create("secondaryCamera", gpu::Element::COLOR_SRGBA_32, 2048, 1024)); + _secondaryCameraTexture = _secondaryCameraFramebuffer->getRenderBuffer(0); + _secondaryCameraNetworkTexture.reset(); +} diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 698d37f38d..498a5ffb8f 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -170,11 +170,11 @@ public: gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); - /// Selfie rendering targets. - NetworkTexturePointer getSelfieNetworkTexture(); - const gpu::TexturePointer& getSelfieTexture(); - const gpu::FramebufferPointer& getSelfieFramebuffer(); - void resetSelfieFramebuffer(int width, int height); + /// SecondaryCamera rendering targets. + NetworkTexturePointer getSecondaryCameraNetworkTexture(); + const gpu::TexturePointer& getSecondaryCameraTexture(); + const gpu::FramebufferPointer& getSecondaryCameraFramebuffer(); + void resetSecondaryCameraFramebuffer(int width, int height); protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads @@ -193,7 +193,7 @@ private: static const std::string KTX_DIRNAME; static const std::string KTX_EXT; - static const std::string SELFIE_FRAME_URL; + static const std::string SECONDARY_CAMERA_FRAME_URL; KTXCache _ktxCache; // Map from image hashes to texture weak pointers @@ -207,9 +207,9 @@ private: gpu::TexturePointer _blackTexture; - gpu::FramebufferPointer _selfieFramebuffer; - gpu::TexturePointer _selfieTexture; - NetworkTexturePointer _selfieNetworkTexture; + gpu::FramebufferPointer _secondaryCameraFramebuffer; + gpu::TexturePointer _secondaryCameraTexture; + NetworkTexturePointer _secondaryCameraNetworkTexture; }; #endif // hifi_TextureCache_h diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 44419d73ff..04aa2b8186 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -54,8 +54,8 @@ // The update function for the spectator camera. Modifies the camera's position // and orientation. // - var spectatorFrameRenderConfig = Render.getConfig("SelfieFrame"); - var beginSpectatorFrameRenderConfig = Render.getConfig("BeginSelfie"); + var spectatorFrameRenderConfig = Render.getConfig("SecondaryCameraFrame"); + var beginSpectatorFrameRenderConfig = Render.getConfig("BeginSecondaryCamera"); var viewFinderOverlay = false; var camera = false; var cameraIsDynamic = false; @@ -105,8 +105,7 @@ }, true); // Put an image3d overlay on the near face, as a viewFinder. viewFinderOverlay = Overlays.addOverlay("image3d", { - url: "http://selfieFrame", - //url: "http://1.bp.blogspot.com/-1GABEq__054/T03B00j_OII/AAAAAAAAAa8/jo55LcvEPHI/s1600/Winning.jpg", + url: "http://secondaryCameraFrame", parentID: camera, alpha: 1, position: inFrontOf(-0.25, cameraPosition, cameraRotation), @@ -141,7 +140,6 @@ } if (camera) { Entities.deleteEntity(camera); - print("ZACH FOX GOODBYE"); } if (viewFinderOverlay) { Overlays.deleteOverlay(viewFinderOverlay); From 5114fd8e1f46a52b1d31f5a6f35ab6926cd561f6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 7 Jun 2017 14:46:59 -0700 Subject: [PATCH 2/7] Rename correctly? --- interface/src/SecondaryCamera.cpp | 4 +- .../src/model-networking/TextureCache.cpp | 42 +++++++++---------- .../src/model-networking/TextureCache.h | 18 ++++---- scripts/system/spectatorCamera.js | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index c6f7526256..4603a4be79 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -24,7 +24,7 @@ void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // Care bool wasEnabled = isEnabled(); setEnabled(false); auto textureCache = DependencyManager::get(); - textureCache->resetSecondaryCameraFramebuffer(width, height); + textureCache->resetSpectatorCameraFramebuffer(width, height); setEnabled(wasEnabled); } @@ -48,7 +48,7 @@ public: void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) { auto args = renderContext->args; auto textureCache = DependencyManager::get(); - auto destFramebuffer = textureCache->getSecondaryCameraFramebuffer(); + auto destFramebuffer = textureCache->getSpectatorCameraFramebuffer(); // 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; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index f64b917520..f8b48833f7 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,7 +50,7 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; const std::string TextureCache::KTX_EXT { "ktx" }; -const std::string TextureCache::SECONDARY_CAMERA_FRAME_URL { "http://secondaryCameraFrame" }; +const std::string TextureCache::SPECTATOR_CAMERA_FRAME_URL { "http://spectatorCameraFrame" }; 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 @@ -182,9 +182,9 @@ ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNum } NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { - if (url == QUrl(SECONDARY_CAMERA_FRAME_URL.c_str())) { + if (url == QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str())) { - return getSecondaryCameraNetworkTexture(); + return getSpectatorCameraNetworkTexture(); } TextureExtra extra = { type, content, maxNumPixels }; return ResourceCache::getResource(url, QUrl(), &extra).staticCast(); @@ -885,31 +885,31 @@ void ImageReader::read() { } -NetworkTexturePointer TextureCache::getSecondaryCameraNetworkTexture() { - if (!_secondaryCameraNetworkTexture) { - _secondaryCameraNetworkTexture.reset(new NetworkTexture(QUrl(SECONDARY_CAMERA_FRAME_URL.c_str()))); - auto texture = getSecondaryCameraTexture(); - _secondaryCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); +NetworkTexturePointer TextureCache::getSpectatorCameraNetworkTexture() { + if (!_spectatorCameraNetworkTexture) { + _spectatorCameraNetworkTexture.reset(new NetworkTexture(QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str()))); + auto texture = getSpectatorCameraTexture(); + _spectatorCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); } - return _secondaryCameraNetworkTexture; + return _spectatorCameraNetworkTexture; } -const gpu::TexturePointer& TextureCache::getSecondaryCameraTexture() { - if (!_secondaryCameraTexture) { - getSecondaryCameraFramebuffer(); +const gpu::TexturePointer& TextureCache::getSpectatorCameraTexture() { + if (!_spectatorCameraTexture) { + getSpectatorCameraFramebuffer(); } - return _secondaryCameraTexture; + return _spectatorCameraTexture; } -const gpu::FramebufferPointer& TextureCache::getSecondaryCameraFramebuffer() { - if (!_secondaryCameraFramebuffer) { - resetSecondaryCameraFramebuffer(2048, 1024); +const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() { + if (!_spectatorCameraFramebuffer) { + resetSpectatorCameraFramebuffer(2048, 1024); } - return _secondaryCameraFramebuffer; + return _spectatorCameraFramebuffer; } -void TextureCache::resetSecondaryCameraFramebuffer(int width, int height) { - _secondaryCameraFramebuffer.reset(gpu::Framebuffer::create("secondaryCamera", gpu::Element::COLOR_SRGBA_32, 2048, 1024)); - _secondaryCameraTexture = _secondaryCameraFramebuffer->getRenderBuffer(0); - _secondaryCameraNetworkTexture.reset(); +void TextureCache::resetSpectatorCameraFramebuffer(int width, int height) { + _spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, 2048, 1024)); + _spectatorCameraTexture = _spectatorCameraFramebuffer->getRenderBuffer(0); + _spectatorCameraNetworkTexture.reset(); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 498a5ffb8f..38cb8e1982 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -170,11 +170,11 @@ public: gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); - /// SecondaryCamera rendering targets. - NetworkTexturePointer getSecondaryCameraNetworkTexture(); - const gpu::TexturePointer& getSecondaryCameraTexture(); - const gpu::FramebufferPointer& getSecondaryCameraFramebuffer(); - void resetSecondaryCameraFramebuffer(int width, int height); + /// SpectatorCamera rendering targets. + NetworkTexturePointer getSpectatorCameraNetworkTexture(); + const gpu::TexturePointer& getSpectatorCameraTexture(); + const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(); + void resetSpectatorCameraFramebuffer(int width, int height); protected: // Overload ResourceCache::prefetch to allow specifying texture type for loads @@ -193,7 +193,7 @@ private: static const std::string KTX_DIRNAME; static const std::string KTX_EXT; - static const std::string SECONDARY_CAMERA_FRAME_URL; + static const std::string SPECTATOR_CAMERA_FRAME_URL; KTXCache _ktxCache; // Map from image hashes to texture weak pointers @@ -207,9 +207,9 @@ private: gpu::TexturePointer _blackTexture; - gpu::FramebufferPointer _secondaryCameraFramebuffer; - gpu::TexturePointer _secondaryCameraTexture; - NetworkTexturePointer _secondaryCameraNetworkTexture; + gpu::FramebufferPointer _spectatorCameraFramebuffer; + gpu::TexturePointer _spectatorCameraTexture; + NetworkTexturePointer _spectatorCameraNetworkTexture; }; #endif // hifi_TextureCache_h diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 04aa2b8186..9df7dade53 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -105,7 +105,7 @@ }, true); // Put an image3d overlay on the near face, as a viewFinder. viewFinderOverlay = Overlays.addOverlay("image3d", { - url: "http://secondaryCameraFrame", + url: "http://spectatorCameraFrame", parentID: camera, alpha: 1, position: inFrontOf(-0.25, cameraPosition, cameraRotation), From 3884287c416d9f8e5c62af2b40e1e96d2bc589ad Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 7 Jun 2017 15:11:53 -0700 Subject: [PATCH 3/7] Use 'resource' protocol instead of 'http' --- .../model-networking/src/model-networking/TextureCache.cpp | 2 +- scripts/system/spectatorCamera.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index f8b48833f7..69eede0cc2 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,7 +50,7 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; const std::string TextureCache::KTX_EXT { "ktx" }; -const std::string TextureCache::SPECTATOR_CAMERA_FRAME_URL { "http://spectatorCameraFrame" }; +const std::string TextureCache::SPECTATOR_CAMERA_FRAME_URL { "resource://spectatorCameraFrame" }; 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 diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 9df7dade53..051741d55f 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -105,7 +105,7 @@ }, true); // Put an image3d overlay on the near face, as a viewFinder. viewFinderOverlay = Overlays.addOverlay("image3d", { - url: "http://spectatorCameraFrame", + url: "resource://spectatorCameraFrame", parentID: camera, alpha: 1, position: inFrontOf(-0.25, cameraPosition, cameraRotation), From fd50434d869d1103a47dc10b3f04a1c76461f507 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 8 Jun 2017 14:36:38 -0700 Subject: [PATCH 4/7] New camera model; Cleanup; Bashing head :against desk --- interface/src/SecondaryCamera.cpp | 73 +++++++++++-------- interface/src/SecondaryCamera.h | 15 +++- .../src/model-networking/TextureCache.cpp | 37 +++++----- .../src/model-networking/TextureCache.h | 8 +- scripts/system/spectatorCamera.js | 52 +++++++++---- 5 files changed, 113 insertions(+), 72 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 4603a4be79..0af51bb2c4 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -1,8 +1,20 @@ +// +// SecondaryCamera.cpp +// interface/src +// +// Created by Samuel Gateau, Howard Stearns, and Zach Fox on 2017-06-08. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// #include "SecondaryCamera.h" - +#include #include +using RenderArgsPointer = std::shared_ptr; + void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred) { task.addJob("RenderShadowTask", cullFunctor); @@ -15,19 +27,18 @@ void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render } } - -#include - -using RenderArgsPointer = std::shared_ptr; - -void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // Carefully adjust the framebuffer / texture. +void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // FIXME: Add an arg here for "destinationFramebuffer" bool wasEnabled = isEnabled(); setEnabled(false); auto textureCache = DependencyManager::get(); - textureCache->resetSpectatorCameraFramebuffer(width, height); + textureCache->resetSpectatorCameraFramebuffer(width, height); // FIXME: Call the correct reset function based on the "destinationFramebuffer" arg setEnabled(wasEnabled); } +void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int height) { // Carefully adjust the framebuffer / texture. + resetSize(width, height); +} + class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and and view. glm::vec3 _position{}; glm::quat _orientation{}; @@ -39,36 +50,36 @@ public: } void configure(const Config& config) { - // Why does this run all the time, even when not enabled? Should we check and bail? - //qDebug() << "FIXME pos" << config.position << "orient" << config.orientation; - _position = config.position; - _orientation = config.orientation; + if (config.enabled || config.alwaysEnabled) { + _position = config.position; + _orientation = config.orientation; + } } void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) { auto args = renderContext->args; auto textureCache = DependencyManager::get(); - auto destFramebuffer = textureCache->getSpectatorCameraFramebuffer(); - // 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; - args->_blitFramebuffer = destFramebuffer; - args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight()); - args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight()); - args->_displayMode = RenderArgs::MONO; + 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; + args->_blitFramebuffer = destFramebuffer; + args->_viewport = glm::ivec4(0, 0, destFramebuffer->getWidth(), destFramebuffer->getHeight()); + args->_displayMode = RenderArgs::MONO; - gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { - batch.disableContextStereo(); - }); + gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + batch.disableContextStereo(); + }); - auto srcViewFrustum = args->getViewFrustum(); - srcViewFrustum.setPosition(_position); - srcViewFrustum.setOrientation(_orientation); - //srcViewFrustum.calculate(); // do we need this? I don't think so - //qDebug() << "FIXME pos" << _position << "orient" << _orientation << "frust pos" << srcViewFrustum.getPosition() << "orient" << srcViewFrustum.getOrientation() << "direct" << srcViewFrustum.getDirection(); - args->pushViewFrustum(srcViewFrustum); - cachedArgs = _cachedArgsPointer; + auto srcViewFrustum = args->getViewFrustum(); + srcViewFrustum.setPosition(_position); + srcViewFrustum.setOrientation(_orientation); + args->pushViewFrustum(srcViewFrustum); + cachedArgs = _cachedArgsPointer; + } } protected: diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index f68a65dd12..1abb2952aa 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -1,3 +1,14 @@ +// +// SecondaryCamera.h +// interface/src +// +// Created by Samuel Gateau, Howard Stearns, and Zach Fox on 2017-06-08. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + #pragma once #ifndef hifi_SecondaryCamera_h #define hifi_SecondaryCamera_h @@ -34,10 +45,12 @@ class SecondaryCameraRenderTaskConfig : public render::Task::Config { Q_OBJECT public: SecondaryCameraRenderTaskConfig() : render::Task::Config(false) {} +private: + void resetSize(int width, int height); signals: void dirty(); public slots: - void resetSize(int width, int height); + void resetSizeSpectatorCamera(int width, int height); }; class SecondaryCameraRenderTask { diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 69eede0cc2..0ecd8e8aab 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -50,7 +50,8 @@ Q_LOGGING_CATEGORY(trace_resource_parse_image_ktx, "trace.resource.parse.image.k const std::string TextureCache::KTX_DIRNAME { "ktx_cache" }; const std::string TextureCache::KTX_EXT { "ktx" }; -const std::string TextureCache::SPECTATOR_CAMERA_FRAME_URL { "resource://spectatorCameraFrame" }; +static const QString RESOURCE_SCHEME = "resource"; +static const QUrl SPECTATOR_CAMERA_FRAME_URL("resource://spectatorCameraFrame"); 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 @@ -182,9 +183,8 @@ ScriptableResource* TextureCache::prefetch(const QUrl& url, int type, int maxNum } NetworkTexturePointer TextureCache::getTexture(const QUrl& url, image::TextureUsage::Type type, const QByteArray& content, int maxNumPixels) { - if (url == QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str())) { - - return getSpectatorCameraNetworkTexture(); + if (url.scheme() == RESOURCE_SCHEME) { + return getResourceTexture(url); } TextureExtra extra = { type, content, maxNumPixels }; return ResourceCache::getResource(url, QUrl(), &extra).staticCast(); @@ -885,31 +885,30 @@ void ImageReader::read() { } -NetworkTexturePointer TextureCache::getSpectatorCameraNetworkTexture() { - if (!_spectatorCameraNetworkTexture) { - _spectatorCameraNetworkTexture.reset(new NetworkTexture(QUrl(SPECTATOR_CAMERA_FRAME_URL.c_str()))); - auto texture = getSpectatorCameraTexture(); - _spectatorCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); +NetworkTexturePointer TextureCache::getResourceTexture(QUrl resourceTextureUrl) { + gpu::TexturePointer texture; + if (resourceTextureUrl == SPECTATOR_CAMERA_FRAME_URL) { + if (!_spectatorCameraNetworkTexture) { + _spectatorCameraNetworkTexture.reset(new NetworkTexture(resourceTextureUrl)); + } + texture = _spectatorCameraFramebuffer->getRenderBuffer(0); + if (texture) { + _spectatorCameraNetworkTexture->setImage(texture, texture->getWidth(), texture->getHeight()); + return _spectatorCameraNetworkTexture; + } } - return _spectatorCameraNetworkTexture; - } -const gpu::TexturePointer& TextureCache::getSpectatorCameraTexture() { - if (!_spectatorCameraTexture) { - getSpectatorCameraFramebuffer(); - } - return _spectatorCameraTexture; + return NetworkTexturePointer(); } + const gpu::FramebufferPointer& TextureCache::getSpectatorCameraFramebuffer() { if (!_spectatorCameraFramebuffer) { resetSpectatorCameraFramebuffer(2048, 1024); } - return _spectatorCameraFramebuffer; } void TextureCache::resetSpectatorCameraFramebuffer(int width, int height) { - _spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, 2048, 1024)); - _spectatorCameraTexture = _spectatorCameraFramebuffer->getRenderBuffer(0); + _spectatorCameraFramebuffer.reset(gpu::Framebuffer::create("spectatorCamera", gpu::Element::COLOR_SRGBA_32, width, height)); _spectatorCameraNetworkTexture.reset(); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 38cb8e1982..c7bb34068d 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -171,8 +171,7 @@ public: /// SpectatorCamera rendering targets. - NetworkTexturePointer getSpectatorCameraNetworkTexture(); - const gpu::TexturePointer& getSpectatorCameraTexture(); + NetworkTexturePointer getResourceTexture(QUrl resourceTextureUrl); const gpu::FramebufferPointer& getSpectatorCameraFramebuffer(); void resetSpectatorCameraFramebuffer(int width, int height); @@ -193,7 +192,6 @@ private: static const std::string KTX_DIRNAME; static const std::string KTX_EXT; - static const std::string SPECTATOR_CAMERA_FRAME_URL; KTXCache _ktxCache; // Map from image hashes to texture weak pointers @@ -206,10 +204,8 @@ private: gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; - - gpu::FramebufferPointer _spectatorCameraFramebuffer; - gpu::TexturePointer _spectatorCameraTexture; NetworkTexturePointer _spectatorCameraNetworkTexture; + gpu::FramebufferPointer _spectatorCameraFramebuffer; }; #endif // hifi_TextureCache_h diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 051741d55f..6e3d032e31 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -28,7 +28,7 @@ // Spectator camera utility functions and variables. // function inFrontOf(distance, position, orientation) { - return Vec3.sum(position || MyAvatar.position, + return Vec3.sum(position || Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 }), Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation))); } var aroundY = Quat.fromPitchYawRollDegrees(0, 180, 0); @@ -46,6 +46,8 @@ // camera: The in-world entity that corresponds to the spectator camera. // cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays // drift with respect to their parent + // lastCameraPosition: Holds the last known camera position + // lastCameraRotation: Holds the last known camera rotation // // Arguments: // None @@ -59,11 +61,18 @@ var viewFinderOverlay = false; var camera = false; var cameraIsDynamic = false; + var lastCameraPosition = false; + var lastCameraRotation = false; function updateRenderFromCamera() { var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']); - // FIXME: don't muck with config if properties haven't changed. - beginSpectatorFrameRenderConfig.position = cameraData.position; - beginSpectatorFrameRenderConfig.orientation = cameraData.rotation; + if (JSON.stringify(lastCameraPosition) !== JSON.stringify(cameraData.position)) { + lastCameraPosition = cameraData.position; + beginSpectatorFrameRenderConfig.position = lastCameraPosition; + } + if (JSON.stringify(lastCameraRotation) !== JSON.stringify(cameraData.rotation)) { + lastCameraRotation = cameraData.rotation; + beginSpectatorFrameRenderConfig.orientation = lastCameraRotation; + } if (cameraIsDynamic) { // BUG: image3d overlays don't retain their locations properly when parented to a dynamic object Overlays.editOverlay(viewFinderOverlay, { orientation: flip(cameraData.rotation) }); @@ -88,33 +97,46 @@ 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.resetSize(size.x, size.y); + spectatorFrameRenderConfig.resetSizeSpectatorCamera(size.x, size.y); spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = true; var cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(2); Script.update.connect(updateRenderFromCamera); isUpdateRenderWired = true; camera = Entities.addEntity({ - type: 'Box', - dimensions: { x: 0.4, y: 0.2, z: 0.4 }, - userData: '{"grabbableKey":{"grabbable":true}}', - dynamic: cameraIsDynamic, - color: { red: 255, green: 0, blue: 0 }, - name: 'SpectatorCamera', - position: cameraPosition, // Put the camera in front of me so that I can find it. - rotation: cameraRotation + "angularDamping": 0.98000001907348633, + "collisionsWillMove": 1, + "damping": 0.98000001907348633, + "dimensions": { + "x": 0.2338641881942749, + "y": 0.407032310962677, + "z": 0.38702544569969177 + }, + "dynamic": cameraIsDynamic, + "modelURL": "http://hifi-content.s3.amazonaws.com/alan/dev/spectator-camera.fbx", + "queryAACube": { + "scale": 0.60840487480163574, + "x": -0.30420243740081787, + "y": -0.30420243740081787, + "z": -0.30420243740081787 + }, + "rotation": cameraRotation, + "position": cameraPosition, + "shapeType": "simple-compound", + "type": "Model", + "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); // Put an image3d overlay on the near face, as a viewFinder. viewFinderOverlay = Overlays.addOverlay("image3d", { url: "resource://spectatorCameraFrame", parentID: camera, alpha: 1, - position: inFrontOf(-0.25, cameraPosition, cameraRotation), + position: inFrontOf(0, Vec3.sum(cameraPosition, { x: 0, y: 0.15, z: 0 }), 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! orientation: flip(cameraRotation), - scale: -0.35, + scale: -0.16, }); setDisplay(monitorShowsCameraView); } From 3d9904cde1579f4a737a98fb6acff00315fa08d9 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 8 Jun 2017 15:41:51 -0700 Subject: [PATCH 5/7] Correctly position actual camera and preview overlay --- scripts/system/spectatorCamera.js | 34 ++++++++++++++++--------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 6e3d032e31..af0fd92b64 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -28,7 +28,7 @@ // Spectator camera utility functions and variables. // function inFrontOf(distance, position, orientation) { - return Vec3.sum(position || Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 }), + return Vec3.sum(position || MyAvatar.position, Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation))); } var aroundY = Quat.fromPitchYawRollDegrees(0, 180, 0); @@ -65,14 +65,14 @@ var lastCameraRotation = false; function updateRenderFromCamera() { var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']); - if (JSON.stringify(lastCameraPosition) !== JSON.stringify(cameraData.position)) { - lastCameraPosition = cameraData.position; - beginSpectatorFrameRenderConfig.position = lastCameraPosition; - } if (JSON.stringify(lastCameraRotation) !== JSON.stringify(cameraData.rotation)) { lastCameraRotation = cameraData.rotation; beginSpectatorFrameRenderConfig.orientation = lastCameraRotation; } + if (JSON.stringify(lastCameraPosition) !== JSON.stringify(cameraData.position)) { + 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) }); @@ -99,12 +99,12 @@ var size = Controller.getViewportDimensions(); // FIXME: Need a signal to hook into when the dimensions change. spectatorFrameRenderConfig.resetSizeSpectatorCamera(size.x, size.y); spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = true; - var cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(2); + var cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); Script.update.connect(updateRenderFromCamera); isUpdateRenderWired = true; camera = Entities.addEntity({ "angularDamping": 0.98000001907348633, - "collisionsWillMove": 1, + "collisionsWillMove": 0, "damping": 0.98000001907348633, "dimensions": { "x": 0.2338641881942749, @@ -119,25 +119,26 @@ "y": -0.30420243740081787, "z": -0.30420243740081787 }, - "rotation": cameraRotation, - "position": cameraPosition, + "rotation": { x: 0, y: 0, z: 0 }, + "position": { x: 0, y: 0, z: 0 }, "shapeType": "simple-compound", "type": "Model", "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); - // Put an image3d overlay on the near face, as a viewFinder. + // This image3d overlay acts as the camera's preview screen. viewFinderOverlay = Overlays.addOverlay("image3d", { url: "resource://spectatorCameraFrame", parentID: camera, alpha: 1, - position: inFrontOf(0, Vec3.sum(cameraPosition, { x: 0, y: 0.15, z: 0 }), 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! - orientation: flip(cameraRotation), + position: { x: 0.007, y: 0.15, z: -0.005 }, scale: -0.16, }); + 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); } @@ -284,6 +285,7 @@ tablet.loadQMLSource("../SpectatorCamera.qml"); onSpectatorCameraScreen = true; sendToQml({ method: 'updateSpectatorCameraCheckbox', params: !!camera }); + sendToQml({ method: 'updateMonitorShowsSwitch', params: !!Settings.getValue('spectatorCamera/monitorShowsCameraView', false) }); setMonitorShowsCameraViewAndSendToQml(monitorShowsCameraView); } } From 3f169e50fe776734cd991103069b5ae66f20e1e6 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 8 Jun 2017 16:18:25 -0700 Subject: [PATCH 6/7] selfie to spectatorCamera --- scripts/system/spectatorCamera.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index af0fd92b64..ed67c97f4a 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -237,7 +237,7 @@ function setDisplay(showCameraView) { // It would be fancy if (showCameraView && !isUpdateRenderWired) would show instructions, but that's out of scope for now. - var url = (showCameraView && isUpdateRenderWired) ? "http://selfieFrame" : ""; + var url = (showCameraView && isUpdateRenderWired) ? "resource://spectatorCameraFrame" : ""; Window.setDisplayTexture(url); } const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false; From 8825e9177536d6844b88152b4ae37fdecb140a34 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 9 Jun 2017 11:36:32 -0700 Subject: [PATCH 7/7] emissive is true --- scripts/system/spectatorCamera.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index ed67c97f4a..ea934bd83c 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -128,6 +128,7 @@ // This image3d overlay acts as the camera's preview screen. viewFinderOverlay = Overlays.addOverlay("image3d", { url: "resource://spectatorCameraFrame", + emissive: true, parentID: camera, alpha: 1, position: { x: 0.007, y: 0.15, z: -0.005 },