From e69362dadc064655897cfc0ddbc6d81a599c3f2a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 22 May 2015 17:51:59 -0700 Subject: [PATCH] Working on stereo rendering --- CMakeLists.txt | 5 +- cmake/externals/boostconfig/CMakeLists.txt | 18 ++ cmake/externals/oglplus/CMakeLists.txt | 18 ++ cmake/modules/FindBoostConfig.cmake | 24 ++ cmake/modules/FindOGLPLUS.cmake | 24 ++ interface/CMakeLists.txt | 9 + interface/src/Application.cpp | 79 ++--- .../plugins/display/SimpleDisplayPlugin.cpp | 74 ++++- .../src/plugins/display/SimpleDisplayPlugin.h | 32 +- .../src/plugins/display/Tv3dDisplayPlugin.cpp | 293 ++++++++++++++---- .../src/plugins/display/Tv3dDisplayPlugin.h | 17 +- .../plugins/display/WindowDisplayPlugin.cpp | 18 -- .../src/plugins/display/WindowDisplayPlugin.h | 1 - interface/src/ui/ApplicationOverlay.cpp | 4 +- interface/src/ui/ApplicationOverlay.h | 6 + libraries/render-utils/src/GlWindow.cpp | 21 +- libraries/render-utils/src/GlWindow.h | 7 +- .../render-utils/src/OffscreenGlCanvas.cpp | 2 +- .../render-utils/src/OffscreenGlCanvas.h | 2 + 19 files changed, 477 insertions(+), 177 deletions(-) create mode 100644 cmake/externals/boostconfig/CMakeLists.txt create mode 100644 cmake/externals/oglplus/CMakeLists.txt create mode 100644 cmake/modules/FindBoostConfig.cmake create mode 100644 cmake/modules/FindOGLPLUS.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e267ba97c3..6ce714b508 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,8 +178,11 @@ option(GET_SOXR "Get Soxr library automatically as external project" 1) option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1) option(GET_LIBOVR "Get LibOVR library automatically as external project" 1) option(GET_OPENVR "Get OpenVR library automatically as external project" 1) -option(USE_NSIGHT "Attempt to find the nSight libraries" 1) option(GET_VHACD "Get V-HACD library automatically as external project" 1) +option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1) +option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1) + +option(USE_NSIGHT "Attempt to find the nSight libraries" 1) if (WIN32) option(GET_GLEW "Get GLEW library automatically as external project" 1) diff --git a/cmake/externals/boostconfig/CMakeLists.txt b/cmake/externals/boostconfig/CMakeLists.txt new file mode 100644 index 0000000000..8785e0d7c7 --- /dev/null +++ b/cmake/externals/boostconfig/CMakeLists.txt @@ -0,0 +1,18 @@ +set(EXTERNAL_NAME boostconfig) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL https://github.com/boostorg/config/archive/boost-1.58.0.zip + URL_MD5 42fa673bae2b7645a22736445e80eb8d + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) + diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt new file mode 100644 index 0000000000..1413edce34 --- /dev/null +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -0,0 +1,18 @@ +set(EXTERNAL_NAME oglplus) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip + URL_MD5 bb55038c36c660d2b6c7be380414fa60 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include ${SOURCE_DIR}/implement CACHE TYPE INTERNAL) + diff --git a/cmake/modules/FindBoostConfig.cmake b/cmake/modules/FindBoostConfig.cmake new file mode 100644 index 0000000000..90682d2425 --- /dev/null +++ b/cmake/modules/FindBoostConfig.cmake @@ -0,0 +1,24 @@ +# +# Try to find BOOSTCONFIG include path. +# Once done this will define +# +# BOOSTCONFIG_INCLUDE_DIRS +# +# Created by Bradley Austin Davis on 2015/05/22 +# Copyright 2015 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 +# + +# setup hints for BOOSTCONFIG search +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("BOOSTCONFIG") + +# locate header +find_path(BOOSTCONFIG_INCLUDE_DIRS "boost/config.hpp" HINTS ${BOOSTCONFIG_SEARCH_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BOOSTCONFIG DEFAULT_MSG BOOSTCONFIG_INCLUDE_DIRS) + +mark_as_advanced(BOOSTCONFIG_INCLUDE_DIRS BOOSTCONFIG_SEARCH_DIRS) \ No newline at end of file diff --git a/cmake/modules/FindOGLPLUS.cmake b/cmake/modules/FindOGLPLUS.cmake new file mode 100644 index 0000000000..6ba883ee2c --- /dev/null +++ b/cmake/modules/FindOGLPLUS.cmake @@ -0,0 +1,24 @@ +# +# Try to find OGLPLUS include path. +# Once done this will define +# +# OGLPLUS_INCLUDE_DIRS +# +# Created by Bradley Austin Davis on 2015/05/22 +# Copyright 2015 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 +# + +# setup hints for OGLPLUS search +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("oglplus") + +# locate header +find_path(OGLPLUS_INCLUDE_DIRS "oglplus/fwd.hpp" HINTS ${OGLPLUS_SEARCH_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OGLPLUS DEFAULT_MSG OGLPLUS_INCLUDE_DIRS) + +mark_as_advanced(OGLPLUS_INCLUDE_DIRS OGLPLUS_SEARCH_DIRS) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 66bb02bbca..bb9960643c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -128,6 +128,15 @@ add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) +add_dependency_external_projects(boostconfig) +find_package(BOOSTCONFIG REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) + +add_dependency_external_projects(oglplus) +find_package(OGLPLUS REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) + + add_dependency_external_projects(LibOVR) find_package(LibOVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f72be6ac5b..54f6be1ceb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1164,7 +1164,7 @@ void Application::keyPressEvent(QKeyEvent* event) { return; } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.keyPressEvent(event); bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier); @@ -1386,17 +1386,12 @@ void Application::keyPressEvent(QKeyEvent* event) { } -#define VR_MENU_ONLY_IN_HMD void Application::keyReleaseEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Alt && _altPressed && _window->isActiveWindow()) { -#ifdef VR_MENU_ONLY_IN_HMD - if (isHMDMode()) { -#endif + if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { + if (getActiveDisplayPlugin()->isStereo()) { VrMenu::toggle(); -#ifdef VR_MENU_ONLY_IN_HMD } -#endif } _keysPressed.remove(event->key()); @@ -4700,52 +4695,36 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti using DisplayPluginList = QVector; +static DisplayPlugin* PLUGIN_POOL[] = { + new LegacyDisplayPlugin(), +#ifdef DEBUG + new NullDisplayPlugin(), +#endif + new Tv3dDisplayPlugin(), + new WindowDisplayPlugin(), + nullptr +}; + // FIXME move to a plugin manager class static const DisplayPluginList & getDisplayPlugins() { static DisplayPluginList RENDER_PLUGINS; static bool init = false; if (!init) { init = true; - DisplayPluginPointer displayPlugin = DisplayPluginPointer(new LegacyDisplayPlugin()); // new WindowDisplayPlugin(); - if (displayPlugin->isSupported()) { - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - qApp->resizeGL(); - }); - addDisplayPluginToMenu(displayPlugin, true); - } - -#ifdef DEBUG - displayPlugin = DisplayPluginPointer(new NullDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - } -#endif - - displayPlugin = DisplayPluginPointer(new Tv3dDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - } - - displayPlugin = DisplayPluginPointer(new WindowDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - qApp->resizeGL(); - }); + for (int i = 0; PLUGIN_POOL[i]; ++i) { + DisplayPlugin * plugin = PLUGIN_POOL[i]; + if (plugin->isSupported()) { + plugin->init(); + QObject::connect(plugin, &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + qApp->resizeGL(); + }); + DisplayPluginPointer pluginPointer(plugin); + addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL); + RENDER_PLUGINS.push_back(pluginPointer); + } } } return RENDER_PLUGINS; @@ -4773,6 +4752,10 @@ void Application::updateDisplayMode() { newDisplayPlugin->deactivate(); _offscreenContext->makeCurrent(); } + + auto offscreenUi = DependencyManager::get(); + offscreenUi->setMouseTranslator(getActiveDisplayPlugin()->getMouseTranslator()); + updateCursorVisibility(); } Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.cpp b/interface/src/plugins/display/SimpleDisplayPlugin.cpp index af02b0e1ce..3c7ec2fb3f 100644 --- a/interface/src/plugins/display/SimpleDisplayPlugin.cpp +++ b/interface/src/plugins/display/SimpleDisplayPlugin.cpp @@ -10,12 +10,13 @@ #include "SimpleDisplayPlugin.h" #include #include +#include #include #include "DependencyManager.h" #include "TextureCache.h" #include "gpu/GLBackend.h" - +#include "OffscreenUi.h" void SimpleGlDisplayPlugin::activate() { makeCurrent(); @@ -87,3 +88,74 @@ void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& scene glFinish(); } +bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { + if (qApp->eventFilter(object, event)) { + return true; + } + + auto offscreenUi = DependencyManager::get(); + if (offscreenUi->eventFilter(object, event)) { + return true; + } + + switch (event->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::MouseMove: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + default: + break; + } + return false; +} + + +static QSurfaceFormat getPluginFormat() { + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); +#ifdef DEBUG + format.setOption(QSurfaceFormat::DebugContext); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + return format; +} + + +void GlWindowDisplayPlugin::activate() { + Q_ASSERT(nullptr == _window); + _window = new GlWindow(getPluginFormat(), QOpenGLContext::currentContext()); + _window->installEventFilter(this); + DependencyManager::get()->setProxyWindow(_window); +} + +void GlWindowDisplayPlugin::deactivate() { + Q_ASSERT(nullptr != _window); + _window->hide(); + _window->destroy(); + _window->deleteLater(); + _window = nullptr; +} + +QSize GlWindowDisplayPlugin::getDeviceSize() const { + return _window->geometry().size() * _window->devicePixelRatio(); +} + +glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { + return toGlm(_window->geometry().size()); +} + +bool GlWindowDisplayPlugin::hasFocus() const { + return _window->isActive(); +} diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.h b/interface/src/plugins/display/SimpleDisplayPlugin.h index 036b50d44a..ca86d85875 100644 --- a/interface/src/plugins/display/SimpleDisplayPlugin.h +++ b/interface/src/plugins/display/SimpleDisplayPlugin.h @@ -52,31 +52,11 @@ protected: class GlWindowDisplayPlugin : public SimpleDisplayPlugin { public: - virtual void activate() { - Q_ASSERT(nullptr == _window); - _window = new GlWindow(QOpenGLContext::currentContext()); - } - - virtual void deactivate() { - Q_ASSERT(nullptr != _window); - _window->hide(); - _window->destroy(); - _window->deleteLater(); - _window = nullptr; - } - - virtual QSize getDeviceSize() const final { - return _window->geometry().size() * _window->devicePixelRatio(); - } - - virtual glm::ivec2 getCanvasSize() const final { - return toGlm(_window->geometry().size()); - } - - virtual bool hasFocus() const { - return _window->isActive(); - } - - + virtual void activate(); + virtual void deactivate(); + virtual QSize getDeviceSize() const final; + virtual glm::ivec2 getCanvasSize() const final; + virtual bool hasFocus() const; + virtual bool eventFilter(QObject* object, QEvent* event); }; diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp index 0173a6fc33..5b35478b57 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp @@ -1,4 +1,3 @@ -// // Tv3dDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. @@ -10,6 +9,44 @@ #include "Tv3dDisplayPlugin.h" #include +#include +#include + +#include "gpu/Texture.h" +#include "gpu/GLBackend.h" +#include "PathUtils.h" + +#include "Application.h" +#include "ui/ApplicationOverlay.h" + + +#include +#define OGLPLUS_LOW_PROFILE 1 +#define OGLPLUS_USE_GLEW 1 +#define OGLPLUS_USE_BOOST_CONFIG 1 +#define OGLPLUS_NO_SITE_CONFIG 1 +#define OGLPLUS_USE_GLCOREARB_H 0 +#include + +#pragma warning(disable : 4068) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma warning( disable : 4244 4267 4065 4101) +#include +#include +#include +#include +#include +#include +#include +#pragma warning( default : 4244 4267 4065 4101) +#pragma clang diagnostic pop + +typedef std::shared_ptr ShapeWrapperPtr; +typedef std::shared_ptr BufferPtr; +typedef std::shared_ptr VertexArrayPtr; +typedef std::shared_ptr ProgramPtr; +typedef oglplus::Uniform Mat4Uniform; const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); @@ -17,84 +54,216 @@ const QString & Tv3dDisplayPlugin::getName() { return NAME; } +Tv3dDisplayPlugin::Tv3dDisplayPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + emit requestRender(); + }); +} + +gpu::TexturePointer _crosshairTexture; + + +void compileProgram(ProgramPtr & result, std::string vs, std::string fs) { + using namespace oglplus; + try { + result = ProgramPtr(new Program()); + // attach the shaders to the program + result->AttachShader( + VertexShader() + .Source(GLSLSource(vs)) + .Compile() + ); + result->AttachShader( + FragmentShader() + .Source(GLSLSource(fs)) + .Compile() + ); + result->Link(); + } catch (ProgramBuildError & err) { + qFatal((const char*)err.Message); + result.reset(); + } +} + + +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { + using namespace oglplus; + Vec3f a(1, 0, 0); + Vec3f b(0, 1, 0); + if (aspect > 1) { + b[1] /= aspect; + } else { + a[0] *= aspect; + } + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program) + ); +} + + +static const char * QUAD_VS = R"VS(#version 330 + +uniform mat4 Projection = mat4(1); +uniform mat4 ModelView = mat4(1); +uniform vec2 UvMultiplier = vec2(1); + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TexCoord; + +out vec2 vTexCoord; + +void main() { + gl_Position = Projection * ModelView * vec4(Position, 1); + vTexCoord = TexCoord * UvMultiplier; +} +)VS"; + +static const char * QUAD_FS = R"FS(#version 330 +uniform sampler2D sampler; +uniform float Alpha = 1.0; + +in vec2 vTexCoord; +out vec4 vFragColor; + +void main() { + vec4 c = texture(sampler, vTexCoord); + c.a = min(Alpha, c.a); + vFragColor = c; + //vFragColor = vec4(fract(vTexCoord), log(vTexCoord.x), 1.0); +} +)FS"; + +static ProgramPtr program; +static ShapeWrapperPtr plane; + void Tv3dDisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { + QSize size = getDeviceSize(); makeCurrent(); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + + if (!program) { + using namespace oglplus; + Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); + Context::Disable(Capability::Blend); + Context::Disable(Capability::DepthTest); + Context::Disable(Capability::CullFace); + + program = ProgramPtr(new oglplus::Program()); + compileProgram(program, QUAD_VS, QUAD_FS); + plane = loadPlane(program, 1.0f); + _crosshairTexture = DependencyManager::get()-> + getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); + } + + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); + glViewport(0, 0, size.width(), size.height()); + Mat4Uniform(*program, "ModelView").Set(mat4()); + Mat4Uniform(*program, "Projection").Set(mat4()); + glBindTexture(GL_TEXTURE_2D, sceneTexture); + plane->Draw(); - if (sceneTexture) { - glBindTexture(GL_TEXTURE_2D, sceneTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); + const float overlayAspect = aspect(toGlm(size)); + const GLfloat distance = 1.0f; + const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); + const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); + const GLfloat quadWidth = halfQuadWidth * 2.0f; + const GLfloat quadHeight = halfQuadHeight * 2.0f; + + vec3 quadSize(quadWidth, quadHeight, 1.0f); + quadSize = vec3(1.0f) / quadSize; + + using namespace oglplus; + + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + Mat4Uniform(*program, "Projection").Set(pr); + + MatrixStack mv; + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + + QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + r.moveLeft(r.width()); } - if (overlayTexture) { - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - - QSize size = getDeviceSize(); - QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - glViewport(r.x(), r.y(), r.width(), r.height()); - glScissor(r.x(), r.y(), r.width(), r.height()); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - - r.moveLeft(r.width()); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_BLEND); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); + glm::vec2 canvasSize = qApp->getCanvasSize(); + glm::vec2 mouse = qApp->getMouse(); + mouse /= canvasSize; + mouse *= 2.0f; + mouse -= 1.0f; + mouse.y *= -1.0f; + mv.translate(mouse); + mv.scale(0.1f); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + plane->Draw(); + r.moveLeft(r.width()); } - glDisable(GL_TEXTURE_2D); - Q_ASSERT(!glGetError()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - glFinish(); + Context::Disable(Capability::Blend); } + +void Tv3dDisplayPlugin::activate() { + GlWindowDisplayPlugin::activate(); + _window->installEventFilter(this); + _window->setFlags(Qt::FramelessWindowHint); + auto desktop = QApplication::desktop(); + _window->setGeometry(desktop->screenGeometry()); + _window->setCursor(Qt::BlankCursor); + _window->show(); + + _timer.start(8); +} + +void Tv3dDisplayPlugin::deactivate() { + makeCurrent(); + if (plane) { + plane.reset(); + program.reset(); + _crosshairTexture.reset(); + } + _timer.stop(); + GlWindowDisplayPlugin::deactivate(); +} +/* +std::function Tv3dDisplayPlugin::getMouseTranslator() { + return [=](const QPointF& point){ + QPointF result{ point }; + QSize size = getDeviceSize(); + result.rx() *= 2.0f; + if (result.x() > size.width()) { + result.rx() -= size.width(); + } + return result; + }; +} + +glm::ivec2 Tv3dDisplayPlugin::trueMouseToUiMouse(const glm::ivec2 & position) const { + ivec2 result{ position }; + uvec2 size = getCanvasSize(); + result.x *= 2; + result.x %= size.x; + return result; +} + +*/ + /* void Tv3dDisplayPlugin::activate() { GlWindowDisplayPlugin::activate(); - _window->setFlags(Qt::FramelessWindowHint); _window->setPosition(100, 100); _window->resize(512, 512); _window->setVisible(true); diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/interface/src/plugins/display/Tv3dDisplayPlugin.h index 5dbfc543b8..a748870abb 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.h +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.h @@ -11,18 +11,23 @@ #pragma once #include "SimpleDisplayPlugin.h" -#include "LegacyDisplayPlugin.h" +#include -class Tv3dDisplayPlugin : public LegacyDisplayPlugin { +class Tv3dDisplayPlugin : public GlWindowDisplayPlugin { Q_OBJECT public: static const QString NAME; virtual const QString & getName(); - + Tv3dDisplayPlugin(); virtual bool isStereo() const final { return true; } void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); - //virtual bool isMouseOnScreen() const { return true; } - //virtual bool isThrottled() const; - //virtual void preDisplay(); + virtual void activate(); + virtual void deactivate(); + + //virtual std::function getMouseTranslator(); + //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const; + +private: + QTimer _timer; }; diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp index 662c527821..b904a9d141 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.cpp +++ b/interface/src/plugins/display/WindowDisplayPlugin.cpp @@ -26,7 +26,6 @@ const QString & WindowDisplayPlugin::getName() { void WindowDisplayPlugin::activate() { GlWindowDisplayPlugin::activate(); - _window->installEventFilter(this); _window->show(); _timer.start(8); } @@ -36,23 +35,6 @@ void WindowDisplayPlugin::deactivate() { GlWindowDisplayPlugin::deactivate(); } -bool WindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::Resize: - case QEvent::MouseMove: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - default: - break; - } - return false; -} #if 0 diff --git a/interface/src/plugins/display/WindowDisplayPlugin.h b/interface/src/plugins/display/WindowDisplayPlugin.h index 1b1d3f81b9..7bc0d5163d 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.h +++ b/interface/src/plugins/display/WindowDisplayPlugin.h @@ -25,7 +25,6 @@ public: virtual void activate(); virtual void deactivate(); - virtual bool eventFilter(QObject* object, QEvent* event); private: QTimer _timer; }; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7c6620e9e1..ea5f74e1c8 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -394,6 +394,7 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { glEnable(GL_LIGHTING); } glPopMatrix(); } +#endif // Draws the FBO texture for 3DTV. void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) { @@ -442,7 +443,7 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float GLfloat y = -halfQuadHeight; glDisable(GL_DEPTH_TEST); - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + with_each_texture(getOverlayTexture(), _newUiTexture, [&] { DependencyManager::get()->renderQuad(glm::vec3(x, y + quadHeight, -distance), glm::vec3(x + quadWidth, y + quadHeight, -distance), glm::vec3(x + quadWidth, y, -distance), @@ -488,7 +489,6 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_LIGHTING); } -#endif void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index c18cbdbe30..d0d50dc114 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -18,6 +18,8 @@ class Overlays; class QOpenGLFramebufferObject; class QOpenGLTexture; +class PalmData; + const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; @@ -42,6 +44,10 @@ public: bool hasMagnifier() const { return _magnifier; } void toggleMagnifier() { _magnifier = !_magnifier; } + // FIXME: remove + void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov); + + // Converter from one frame of reference to another. // Frame of reference: // Direction: Ray that represents the spherical values diff --git a/libraries/render-utils/src/GlWindow.cpp b/libraries/render-utils/src/GlWindow.cpp index 011198e7c0..b395140518 100644 --- a/libraries/render-utils/src/GlWindow.cpp +++ b/libraries/render-utils/src/GlWindow.cpp @@ -38,14 +38,14 @@ GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext) _context->create(); } -static QOpenGLDebugLogger* logger{ nullptr }; - GlWindow::~GlWindow() { - if (logger) { +#ifdef DEBUG + if (_logger) { makeCurrent(); - delete logger; - logger = nullptr; + delete _logger; + _logger = nullptr; } +#endif _context->doneCurrent(); _context->deleteLater(); _context = nullptr; @@ -55,13 +55,14 @@ GlWindow::~GlWindow() { void GlWindow::makeCurrent() { _context->makeCurrent(this); #ifdef DEBUG - if (!logger) { - logger = new QOpenGLDebugLogger(this); - if (logger->initialize()) { - connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + if (!_logger) { + _logger = new QOpenGLDebugLogger(this); + if (_logger->initialize()) { + connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { qDebug() << message; }); - logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); + _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); + _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); } } #endif diff --git a/libraries/render-utils/src/GlWindow.h b/libraries/render-utils/src/GlWindow.h index 5d391d0d7b..69fb09932e 100644 --- a/libraries/render-utils/src/GlWindow.h +++ b/libraries/render-utils/src/GlWindow.h @@ -14,9 +14,9 @@ #include class QOpenGLContext; +class QOpenGLDebugLogger; class GlWindow : public QWindow { - QOpenGLContext * _context{ nullptr }; public: GlWindow(QOpenGLContext * shareContext = nullptr); GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext = nullptr); @@ -24,6 +24,11 @@ public: void makeCurrent(); void doneCurrent(); void swapBuffers(); +private: + QOpenGLContext * _context{ nullptr }; +#ifdef DEBUG + QOpenGLDebugLogger * _logger{ nullptr }; +#endif }; #endif \ No newline at end of file diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index dc9205a246..a3025bc3f6 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -50,7 +50,7 @@ bool OffscreenGlCanvas::makeCurrent() { connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { qDebug() << message; }); - _logger->enableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::HighSeverity); + _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); } } diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h index 545d2269b7..c9578f5a7c 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.h +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -30,7 +30,9 @@ public: protected: QOpenGLContext _context; QOffscreenSurface _offscreenSurface; +#ifdef DEBUG QOpenGLDebugLogger * _logger{ nullptr }; +#endif };