Working on display plugins

This commit is contained in:
Brad Davis 2015-06-05 00:00:57 -07:00
parent edfb1305af
commit 1b7efe9a02
25 changed files with 430 additions and 269 deletions

View file

@ -90,6 +90,7 @@
#include <UserActivityLogger.h> #include <UserActivityLogger.h>
#include <UUID.h> #include <UUID.h>
#include <VrMenu.h> #include <VrMenu.h>
#include <ui/ApplicationOverlayCompositor.h>
#include "Application.h" #include "Application.h"
#include "AudioClient.h" #include "AudioClient.h"
@ -101,6 +102,7 @@
#include "Util.h" #include "Util.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
#include "GlWindow.h"
#include "avatar/AvatarManager.h" #include "avatar/AvatarManager.h"
#include "audio/AudioToolBox.h" #include "audio/AudioToolBox.h"
@ -506,29 +508,39 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
ResourceCache::setRequestLimit(3); ResourceCache::setRequestLimit(3);
_window->setCentralWidget(new QWidget()); _offscreenContext->create();
_offscreenContext->makeCurrent();
_glWindow = new GlWindow(_offscreenContext->getContext());
QWidget* container = QWidget::createWindowContainer(_glWindow);
container->setFocusPolicy(Qt::StrongFocus);
_window->setCentralWidget(container);
_window->restoreGeometry(); _window->restoreGeometry();
_window->setVisible(true); _window->setVisible(true);
container->setFocus();
_offscreenContext->makeCurrent();
initializeGL();
// initialization continues in initializeGL when OpenGL context is ready
_menuBarHeight = Menu::getInstance()->height();
#if 0 #if 0
_fullscreenMenuWidget->setParent(_glWidget); _fullscreenMenuWidget->setParent(_glWidget);
#endif
_menuBarHeight = Menu::getInstance()->height();
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
setFullscreen(true); // Initialize menu bar show/hide setFullscreen(true); // Initialize menu bar show/hide
} }
#endif
_toolWindow = new ToolWindow(); _toolWindow = new ToolWindow();
_toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint);
_toolWindow->setWindowTitle("Tools"); _toolWindow->setWindowTitle("Tools");
_offscreenContext->create();
_compositor = CompositorPtr(new ApplicationOverlayCompositor());
_offscreenContext->makeCurrent(); _offscreenContext->makeCurrent();
initializeGL();
// initialization continues in initializeGL when OpenGL context is ready
// Tell our entity edit sender about our known jurisdictions // Tell our entity edit sender about our known jurisdictions
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
@ -949,15 +961,16 @@ void Application::paintGL() {
// has completed before we start trying to read from it in another context. However // has completed before we start trying to read from it in another context. However
// once we have multi-threaded rendering, this will almost certainly be critical, // once we have multi-threaded rendering, this will almost certainly be critical,
// but may be better handled with a fence object // but may be better handled with a fence object
glFinish(); // glFinish();
_offscreenContext->doneCurrent(); _offscreenContext->doneCurrent();
Q_ASSERT(!QOpenGLContext::currentContext()); Q_ASSERT(!QOpenGLContext::currentContext());
displayPlugin->preDisplay();
displayPlugin->display(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)), finalFbo->getSize(), GLuint finalTexture = _compositor->composite(displayPlugin,
gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)), finalFbo->getSize(),
_applicationOverlay.getOverlayTexture(), getCanvasSize()); _applicationOverlay.getOverlayTexture(), getCanvasSize());
displayPlugin->preDisplay();
displayPlugin->display(finalTexture, finalFbo->getSize());
displayPlugin->finishFrame(); displayPlugin->finishFrame();
Q_ASSERT(!QOpenGLContext::currentContext()); Q_ASSERT(!QOpenGLContext::currentContext());
_offscreenContext->makeCurrent(); _offscreenContext->makeCurrent();
@ -1427,7 +1440,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
return; return;
} }
#if 0
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
// Show/hide menu bar in fullscreen // Show/hide menu bar in fullscreen
if (event->globalY() > _menuBarHeight) { if (event->globalY() > _menuBarHeight) {
@ -1438,6 +1451,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
Menu::getInstance()->setFixedHeight(_menuBarHeight); Menu::getInstance()->setFixedHeight(_menuBarHeight);
} }
} }
#endif
_entities.mouseMoveEvent(event, deviceID); _entities.mouseMoveEvent(event, deviceID);
@ -1764,6 +1778,7 @@ void Application::idle() {
emit checkBackgroundDownloads(); emit checkBackgroundDownloads();
} }
#if 0
void Application::setFullscreen(bool fullscreen) { void Application::setFullscreen(bool fullscreen) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) { if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) {
Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen); Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen);
@ -1822,7 +1837,6 @@ void Application::setFullscreen(bool fullscreen) {
} }
} }
#if 0
void Application::setEnable3DTVMode(bool enable3DTVMode) { void Application::setEnable3DTVMode(bool enable3DTVMode) {
resizeGL(); resizeGL();
} }
@ -3006,8 +3020,11 @@ PickRay Application::computePickRay(float x, float y) const {
if (isHMDMode()) { if (isHMDMode()) {
getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
} else { } else {
auto frustum = activeRenderingThread ? getDisplayViewFrustum() : getViewFrustum(); if (QThread::currentThread() == activeRenderingThread) {
frustum->computePickRay(x, y, result.origin, result.direction); getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction);
} else {
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
}
} }
return result; return result;
} }
@ -3214,7 +3231,7 @@ void Application::displaySide(const Camera& theCamera, bool selfAvatarOnly) {
skybox = skyStage->getSkybox(); skybox = skyStage->getSkybox();
if (skybox) { if (skybox) {
gpu::Batch batch; gpu::Batch batch;
model::Skybox::render(batch, _viewFrustum, *skybox); model::Skybox::render(batch, _displayViewFrustum, *skybox);
gpu::GLBackend::renderBatch(batch); gpu::GLBackend::renderBatch(batch);
glUseProgram(0); glUseProgram(0);
@ -4656,6 +4673,6 @@ void Application::addMenuItem(const QString& path, std::function<void()> onClick
} }
QMainWindow* Application::getAppMainWindow() { GlWindow* Application::getVisibleWindow() {
return _window; return _glWindow;
} }

View file

@ -48,7 +48,6 @@
#include "DatagramProcessor.h" #include "DatagramProcessor.h"
#include "Environment.h" #include "Environment.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "GLCanvas.h"
#include "Menu.h" #include "Menu.h"
#include "PacketHeaders.h" #include "PacketHeaders.h"
#include "Physics.h" #include "Physics.h"
@ -91,6 +90,9 @@ class MainWindow;
class Node; class Node;
class ProgramObject; class ProgramObject;
class ScriptEngine; class ScriptEngine;
class GlWindow;
class ApplicationOverlayCompositor;
using CompositorPtr = std::shared_ptr<ApplicationOverlayCompositor>;
static const float NODE_ADDED_RED = 0.0f; static const float NODE_ADDED_RED = 0.0f;
static const float NODE_ADDED_GREEN = 1.0f; static const float NODE_ADDED_GREEN = 1.0f;
@ -137,6 +139,7 @@ class Application;
typedef bool (Application::* AcceptURLMethod)(const QString &); typedef bool (Application::* AcceptURLMethod)(const QString &);
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface, PluginContainer { class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface, PluginContainer {
Q_OBJECT Q_OBJECT
@ -299,7 +302,7 @@ public:
// Plugin container support // Plugin container support
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName); virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName);
virtual QMainWindow* getAppMainWindow(); virtual GlWindow* getVisibleWindow();
private: private:
DisplayPlugin * getActiveDisplayPlugin(); DisplayPlugin * getActiveDisplayPlugin();
@ -446,8 +449,11 @@ private slots:
void connectedToDomain(const QString& hostname); void connectedToDomain(const QString& hostname);
#if 0
friend class HMDToolsDialog; friend class HMDToolsDialog;
void setFullscreen(bool fullscreen); void setFullscreen(bool fullscreen);
#endif
void cameraMenuChanged(); void cameraMenuChanged();
void closeMirrorView(); void closeMirrorView();
@ -544,6 +550,8 @@ private:
ViewFrustum _shadowViewFrustum; ViewFrustum _shadowViewFrustum;
quint64 _lastQueriedTime; quint64 _lastQueriedTime;
CompositorPtr _compositor;
float _trailingAudioLoudness; float _trailingAudioLoudness;
OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers
@ -653,6 +661,7 @@ private:
QThread _settingsThread; QThread _settingsThread;
QTimer _settingsTimer; QTimer _settingsTimer;
GlWindow* _glWindow{ nullptr };
void checkSkeleton(); void checkSkeleton();
QWidget* _fullscreenMenuWidget = new QWidget(); QWidget* _fullscreenMenuWidget = new QWidget();

View file

@ -98,9 +98,12 @@ void MainWindow::changeEvent(QEvent* event) {
emit windowShown(true); emit windowShown(true);
} }
#if 0
if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen()); Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen());
} }
#endif
} else if (event->type() == QEvent::ActivationChange) { } else if (event->type() == QEvent::ActivationChange) {
if (isActiveWindow()) { if (isActiveWindow()) {
emit windowShown(true); emit windowShown(true);

View file

@ -239,6 +239,7 @@ Menu::Menu() {
displayModeGroup->setExclusive(true); displayModeGroup->setExclusive(true);
} }
#if 0
addCheckableActionToQMenuAndActionHash(viewMenu, addCheckableActionToQMenuAndActionHash(viewMenu,
MenuOption::Fullscreen, MenuOption::Fullscreen,
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -249,6 +250,7 @@ Menu::Menu() {
false, false,
qApp, qApp,
SLOT(setFullscreen(bool))); SLOT(setFullscreen(bool)));
#endif
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson, addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson,
0, // QML Qt::Key_P, 0, // QML Qt::Key_P,
@ -260,6 +262,7 @@ Menu::Menu() {
0, // QML Qt::Key_H, 0, // QML Qt::Key_H,
false, qApp, SLOT(cameraMenuChanged())); false, qApp, SLOT(cameraMenuChanged()));
#if 0
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
Qt::META | Qt::Key_H, Qt::META | Qt::Key_H,
@ -269,6 +272,7 @@ Menu::Menu() {
false, false,
dialogsManager.data(), dialogsManager.data(),
SLOT(hmdTools(bool))); SLOT(hmdTools(bool)));
#endif
addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0, addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
dialogsManager.data(), SLOT(editAttachments())); dialogsManager.data(), SLOT(editAttachments()));

View file

@ -194,12 +194,10 @@ namespace MenuOption {
const QString FilterSixense = "Smooth Sixense Movement"; const QString FilterSixense = "Smooth Sixense Movement";
const QString FirstPerson = "First Person"; const QString FirstPerson = "First Person";
const QString FrameTimer = "Show Timer"; const QString FrameTimer = "Show Timer";
const QString Fullscreen = "Fullscreen";
const QString FullscreenMirror = "Fullscreen Mirror"; const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowWhenSpeaking = "Glow When Speaking"; const QString GlowWhenSpeaking = "Glow When Speaking";
const QString NamesAboveHeads = "Names Above Heads"; const QString NamesAboveHeads = "Names Above Heads";
const QString GoToUser = "Go To User"; const QString GoToUser = "Go To User";
const QString HMDTools = "HMD Tools";
const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseAvatarSize = "Increase Avatar Size";
const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LeapMotionOnHMD = "Leap Motion on HMD";

View file

@ -0,0 +1,209 @@
#include "ApplicationOverlayCompositor.h"
#include <TextureCache.h>
#include <PathUtils.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <gpu/GLBackend.h>
#define DEFAULT_HMD_UI_ANGULAR_SIZE 72.0f
ApplicationOverlayCompositor::ApplicationOverlayCompositor() {
using namespace oglplus;
auto currentContext = QOpenGLContext::currentContext();
Q_ASSERT(currentContext);
_canvas.create(currentContext);
_canvas.makeCurrent();
Q_ASSERT(0 == glGetError());
currentContext = QOpenGLContext::currentContext();
Q_ASSERT(currentContext);
Context::ClearColor(0, 0, 0, 1);
Q_ASSERT(0 == glGetError());
Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha);
Q_ASSERT(0 == glGetError());
Context::Disable(Capability::Blend);
Q_ASSERT(0 == glGetError());
Context::Disable(Capability::DepthTest);
Q_ASSERT(0 == glGetError());
Context::Disable(Capability::CullFace);
Q_ASSERT(0 == glGetError());
_program = loadDefaultShader();
_plane = loadPlane(_program);
_program = loadDefaultShader();
_plane = loadPlane(_program);
_hmdUiSurface = loadSphereSection(_program, glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE));
_crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
GLuint ApplicationOverlayCompositor::composite(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
using namespace oglplus;
_canvas.makeCurrent();
if (!_fbo || sceneSize != _fbo->size) {
_fbo = BasicFramebufferWrapperPtr(new BasicFramebufferWrapper());
_fbo->Init(sceneSize);
}
_fbo->Bound(Framebuffer::Target::Draw, [&] {
Context::Clear().ColorBuffer();
if (plugin->isHmd()) {
compositeHmd(plugin, sceneTexture, sceneSize, overlayTexture, overlaySize);
} else if (plugin->isStereo()) {
compositeStereo(plugin, sceneTexture, sceneSize, overlayTexture, overlaySize);
} else {
composite2D(plugin, sceneTexture, sceneSize, overlayTexture, overlaySize);
}
});
GLuint result = GetName(_fbo->color);
_canvas.doneCurrent();
return result;
}
void ApplicationOverlayCompositor::composite2D(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
using namespace oglplus;
const uvec2 size = toGlm(plugin->getDeviceSize());
Q_ASSERT(0 == glGetError());
Context::Viewport(size.x, size.y);
_program->Bind();
Mat4Uniform(*_program, "ModelView").Set(mat4());
Mat4Uniform(*_program, "Projection").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture);
_plane->Use();
_plane->Draw();
Context::Enable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
_plane->Draw();
Context::Disable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, 0);
// FIXME add the cursor
Q_ASSERT(0 == glGetError());
}
template <typename F>
void sbs_for_each_eye(const uvec2& size, F f) {
QRect r(QPoint(0, 0), QSize(size.x / 2, size.y));
for_each_eye([&](Eye eye) {
oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height());
f(eye);
}, [&] {
r.moveLeft(r.width());
});
}
void ApplicationOverlayCompositor::compositeStereo(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
using namespace oglplus;
Q_ASSERT(0 == glGetError());
const uvec2 size = sceneSize;
Context::Viewport(size.x, size.y);
_program->Bind();
Mat4Uniform(*_program, "ModelView").Set(mat4());
Mat4Uniform(*_program, "Projection").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture);
_plane->Use();
_plane->Draw();
// FIXME the
const float screenAspect = aspect(size);
const GLfloat distance = 1.0f;
const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES);
const GLfloat halfQuadWidth = halfQuadHeight * screenAspect;
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), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP);
Mat4Uniform(*_program, "Projection").Set(pr);
// Position the camera relative to the overlay texture
MatrixStack mv;
mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0));
sbs_for_each_eye(size, [&](Eye eye) {
mv.withPush([&] {
// translate
mv.top() = plugin->getModelview(eye, mv.top());
Mat4Uniform(*_program, "ModelView").Set(mv.top());
_plane->Draw();
});
});
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glm::vec2 canvasSize = plugin->getCanvasSize();
glm::vec2 mouse = vec2(0); // toGlm(_window->mapFromGlobal(QCursor::pos()));
mouse /= canvasSize;
mouse *= 2.0f;
mouse -= 1.0f;
mouse.y *= -1.0f;
sbs_for_each_eye(size, [&](Eye eye) {
mv.withPush([&] {
// translate
mv.top() = plugin->getModelview(eye, mv.top());
mv.translate(mouse);
//mv.scale(0.05f);
mv.scale(vec3(0.025f, 0.05f, 1.0f));
Mat4Uniform(*_program, "ModelView").Set(mv.top());
_plane->Draw();
});
});
Context::Disable(Capability::Blend);
}
void ApplicationOverlayCompositor::compositeHmd(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
using namespace oglplus;
auto size = sceneSize;
Context::Viewport(size.x, size.y);
glClearColor(0, 0, 0, 0);
Context::Clear().ColorBuffer();
_program->Bind();
Mat4Uniform(*_program, "Projection").Set(mat4());
Mat4Uniform(*_program, "ModelView").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture);
_plane->Use();
_plane->Draw();
Context::Enable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
for_each_eye([&](Eye eye) {
Context::Viewport(eye == Left ? 0 : size.x / 2, 0, size.x / 2, size.y);
glm::mat4 m = plugin->getProjection(eye, glm::mat4());
Mat4Uniform(*_program, "Projection").Set(m);
Mat4Uniform(*_program, "ModelView").Set(glm::scale(glm::inverse(plugin->getModelview(eye, mat4())), vec3(1)));
_hmdUiSurface->Use();
_hmdUiSurface->Draw();
});
Context::Disable(Capability::Blend);
}

View file

@ -0,0 +1,37 @@
#pragma once
#include <gpu/Texture.h>
#include <display-plugins/DisplayPlugin.h>
#include <display-plugins/OglplusHelpers.h>
#include <OffscreenGlCanvas.h>
class ApplicationOverlayCompositor {
public:
ApplicationOverlayCompositor();
GLuint composite(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
private:
OffscreenGlCanvas _canvas;
BasicFramebufferWrapperPtr _fbo;
ProgramPtr _program;
ShapeWrapperPtr _plane;
ShapeWrapperPtr _hmdUiSurface;
gpu::TexturePointer _crosshairTexture;
void composite2D(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
void compositeStereo(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
void compositeHmd(DisplayPlugin* plugin,
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
};
using CompositorPtr = std::shared_ptr<ApplicationOverlayCompositor>;

View file

@ -68,13 +68,12 @@ public:
* OpenGL context * OpenGL context
*/ */
virtual void preDisplay() = 0; virtual void preDisplay() = 0;
/** /**
* Sends the scene texture and the overlay texture to the display plugin. * Sends the scene texture to the display plugin.
* The plugin is responsible for compositing these and adding rendering of
* additional elements like mouse and hydra pointers as required
*/ */
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) = 0;
GLuint overlayTexture, const glm::uvec2& overlaySize) = 0;
/** /**
* Called by the application immeidately after display. For OpenGL based * Called by the application immeidately after display. For OpenGL based
* displays, this is the best place to put the buffer swap * displays, this is the best place to put the buffer swap

View file

@ -7,32 +7,47 @@
// //
#include "MainWindowOpenGLDisplayPlugin.h" #include "MainWindowOpenGLDisplayPlugin.h"
#include <GlWindow.h>
#include <QOpenGLContext> #include <QOpenGLContext>
#include <plugins/PluginContainer.h>
#include <QWidget> #include <QWidget>
#include <QMainWindow> #include <QMainWindow>
#include <GlWindow.h>
#include <plugins/PluginContainer.h>
MainWindowOpenGLDisplayPlugin::MainWindowOpenGLDisplayPlugin() { MainWindowOpenGLDisplayPlugin::MainWindowOpenGLDisplayPlugin() {
} }
void MainWindowOpenGLDisplayPlugin::activate(PluginContainer * container) { GlWindow* MainWindowOpenGLDisplayPlugin::createWindow(PluginContainer * container) {
WindowOpenGLDisplayPlugin::activate(container); return container->getVisibleWindow();
} }
void MainWindowOpenGLDisplayPlugin::customizeWindow(PluginContainer * container) { void MainWindowOpenGLDisplayPlugin::customizeWindow(PluginContainer * container) {
// Can't set the central widget here, because it seems to mess up the context creation.
} }
void MainWindowOpenGLDisplayPlugin::customizeContext(PluginContainer * container) { void MainWindowOpenGLDisplayPlugin::destroyWindow() {
WindowOpenGLDisplayPlugin::customizeContext(container); _window = nullptr;
QWidget* widget = QWidget::createWindowContainer(_window);
auto mainWindow = container->getAppMainWindow();
mainWindow->setCentralWidget(widget);
mainWindow->resize(mainWindow->geometry().size());
_window->resize(_window->geometry().size());
} }
void MainWindowOpenGLDisplayPlugin::deactivate() { void MainWindowOpenGLDisplayPlugin::display(
WindowOpenGLDisplayPlugin::deactivate(); GLuint finalTexture, const glm::uvec2& sceneSize) {
OpenGLDisplayPlugin::display(finalTexture, sceneSize);
return;
using namespace oglplus;
glClearColor(0, 1, 0, 1);
uvec2 size = toGlm(getDeviceSize());
Context::Viewport(size.x, size.y);
Context::Clear().ColorBuffer();
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, finalTexture);
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();
} }

View file

@ -9,17 +9,16 @@
#include "WindowOpenGLDisplayPlugin.h" #include "WindowOpenGLDisplayPlugin.h"
class GlWindow; class QGLWidget;
class QSurfaceFormat;
class MainWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin { class MainWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin {
Q_OBJECT Q_OBJECT
public: public:
MainWindowOpenGLDisplayPlugin(); MainWindowOpenGLDisplayPlugin();
virtual void activate(PluginContainer * container) override; virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
virtual void deactivate() override;
protected: protected:
virtual void customizeWindow(PluginContainer * container) override; virtual GlWindow* createWindow(PluginContainer * container) override final;
virtual void customizeContext(PluginContainer * container) override; virtual void customizeWindow(PluginContainer * container) override final;
virtual void destroyWindow() override final;
}; };

View file

@ -49,8 +49,7 @@ QWindow* NullDisplayPlugin::getWindow() const {
void NullDisplayPlugin::preRender() {} void NullDisplayPlugin::preRender() {}
void NullDisplayPlugin::preDisplay() {} void NullDisplayPlugin::preDisplay() {}
void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize) {}
GLuint overlayTexture, const glm::uvec2& overlaySize) {}
void NullDisplayPlugin::finishFrame() {} void NullDisplayPlugin::finishFrame() {}
void NullDisplayPlugin::activate(PluginContainer * container) {} void NullDisplayPlugin::activate(PluginContainer * container) {}

View file

@ -29,7 +29,6 @@ public:
virtual QWindow* getWindow() const; virtual QWindow* getWindow() const;
virtual void preRender(); virtual void preRender();
virtual void preDisplay(); virtual void preDisplay();
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize);
GLuint overlayTexture, const glm::uvec2& overlaySize);
virtual void finishFrame(); virtual void finishFrame();
}; };

View file

@ -29,12 +29,12 @@
#include <NumericalConstants.h> #include <NumericalConstants.h>
typedef std::shared_ptr<oglplus::Framebuffer> FramebufferPtr; using FramebufferPtr = std::shared_ptr<oglplus::Framebuffer>;
typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr; using ShapeWrapperPtr = std::shared_ptr<oglplus::shapes::ShapeWrapper>;
typedef std::shared_ptr<oglplus::Buffer> BufferPtr; using BufferPtr = std::shared_ptr<oglplus::Buffer>;
typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr; using VertexArrayPtr = std::shared_ptr<oglplus::VertexArray>;
typedef std::shared_ptr<oglplus::Program> ProgramPtr; using ProgramPtr = std::shared_ptr<oglplus::Program>;
typedef oglplus::Uniform<mat4> Mat4Uniform; using Mat4Uniform = oglplus::Uniform<mat4>;
ProgramPtr loadDefaultShader(); ProgramPtr loadDefaultShader();
void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs); void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs);
@ -56,8 +56,8 @@ template <
struct FramebufferWrapper { struct FramebufferWrapper {
uvec2 size; uvec2 size;
oglplus::Framebuffer fbo; oglplus::Framebuffer fbo;
C color{ 0 }; C color;
D depth{ 0 }; D depth;
FramebufferWrapper() {} FramebufferWrapper() {}
@ -112,7 +112,6 @@ protected:
virtual void initDone() = 0; virtual void initDone() = 0;
}; };
struct BasicFramebufferWrapper : public FramebufferWrapper <oglplus::Texture, oglplus::Renderbuffer> { struct BasicFramebufferWrapper : public FramebufferWrapper <oglplus::Texture, oglplus::Renderbuffer> {
protected: protected:
virtual void initDepth() override { virtual void initDepth() override {
@ -147,3 +146,5 @@ protected:
}); });
} }
}; };
using BasicFramebufferWrapperPtr = std::shared_ptr<BasicFramebufferWrapper>;

View file

@ -8,11 +8,6 @@
#include "OpenGLDisplayPlugin.h" #include "OpenGLDisplayPlugin.h"
#include <QOpenGLContext> #include <QOpenGLContext>
#include <TextureCache.h>
#include <PathUtils.h>
#include <QOpenGLContext>
#include <QCursor>
#include <QCoreApplication> #include <QCoreApplication>
#include <GLWindow.h> #include <GLWindow.h>
@ -50,8 +45,6 @@ void OpenGLDisplayPlugin::customizeContext(PluginContainer * container) {
_program = loadDefaultShader(); _program = loadDefaultShader();
_plane = loadPlane(_program); _plane = loadPlane(_program);
Context::ClearColor(0, 0, 0, 1); Context::ClearColor(0, 0, 0, 1);
_crosshairTexture = DependencyManager::get<TextureCache>()->
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
} }
void OpenGLDisplayPlugin::activate(PluginContainer * container) { void OpenGLDisplayPlugin::activate(PluginContainer * container) {
@ -60,11 +53,11 @@ void OpenGLDisplayPlugin::activate(PluginContainer * container) {
void OpenGLDisplayPlugin::deactivate() { void OpenGLDisplayPlugin::deactivate() {
_timer.stop(); _timer.stop();
makeCurrent(); makeCurrent();
Q_ASSERT(0 == glGetError()); Q_ASSERT(0 == glGetError());
_plane.reset(); _plane.reset();
_program.reset(); _program.reset();
_crosshairTexture.reset();
doneCurrent(); doneCurrent();
} }
@ -109,25 +102,15 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
} }
void OpenGLDisplayPlugin::display( void OpenGLDisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint finalTexture, const glm::uvec2& sceneSize) {
GLuint overlayTexture, const glm::uvec2& overlaySize) {
makeCurrent();
Q_ASSERT(0 == glGetError());
uvec2 size = toGlm(getDeviceSize());
using namespace oglplus; using namespace oglplus;
uvec2 size = toGlm(getDeviceSize());
Context::Viewport(size.x, size.y); Context::Viewport(size.x, size.y);
glClearColor(0, 1, 1, 1); Context::Clear().ColorBuffer();
Context::Clear().ColorBuffer().DepthBuffer();
_program->Bind(); _program->Bind();
Mat4Uniform(*_program, "ModelView").Set(mat4()); glBindTexture(GL_TEXTURE_2D, finalTexture);
Mat4Uniform(*_program, "Projection").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture);
_plane->Use(); _plane->Use();
_plane->Draw(); _plane->Draw();
Context::Enable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
_plane->Draw();
Context::Disable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, 0);
Q_ASSERT(0 == glGetError());
} }

View file

@ -9,13 +9,12 @@
#include <QTimer> #include <QTimer>
#include <gpu/Texture.h>
#include "DisplayPlugin.h" #include "DisplayPlugin.h"
#include "OglplusHelpers.h" #include "OglplusHelpers.h"
class GlWindow; class GlWindow;
class QOpenGLContext; class QOpenGLContext;
class OpenGLDisplayPlugin : public DisplayPlugin { class OpenGLDisplayPlugin : public DisplayPlugin {
public: public:
OpenGLDisplayPlugin(); OpenGLDisplayPlugin();
@ -29,9 +28,7 @@ public:
virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual bool eventFilter(QObject* receiver, QEvent* event) override;
void display( virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
protected: protected:
@ -46,7 +43,6 @@ protected:
QTimer _timer; QTimer _timer;
ProgramPtr _program; ProgramPtr _program;
ShapeWrapperPtr _plane; ShapeWrapperPtr _plane;
gpu::TexturePointer _crosshairTexture;
}; };

View file

@ -17,7 +17,7 @@
#include <QGLContext> #include <QGLContext>
#include <QGLWidget> #include <QGLWidget>
#include "plugins/PluginContainer.h" #include "plugins/PluginContainer.h"
#if 0
WidgetOpenGLDisplayPlugin::WidgetOpenGLDisplayPlugin() { WidgetOpenGLDisplayPlugin::WidgetOpenGLDisplayPlugin() {
} }
@ -106,3 +106,4 @@ void WidgetOpenGLDisplayPlugin::removeEventFilter(QObject* filter) {
QWindow* WidgetOpenGLDisplayPlugin::getWindow() const { QWindow* WidgetOpenGLDisplayPlugin::getWindow() const {
return _widget->windowHandle(); return _widget->windowHandle();
} }
#endif

View file

@ -42,7 +42,7 @@ void WindowOpenGLDisplayPlugin::initSurfaceFormat(QSurfaceFormat& format) {
void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) { void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) {
OpenGLDisplayPlugin::activate(container); OpenGLDisplayPlugin::activate(container);
_window = new GlWindow(QOpenGLContext::currentContext()); _window = createWindow(container);
QSurfaceFormat format; QSurfaceFormat format;
initSurfaceFormat(format); initSurfaceFormat(format);
@ -57,6 +57,14 @@ void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) {
void WindowOpenGLDisplayPlugin::deactivate() { void WindowOpenGLDisplayPlugin::deactivate() {
OpenGLDisplayPlugin::deactivate(); OpenGLDisplayPlugin::deactivate();
destroyWindow();
}
GlWindow* WindowOpenGLDisplayPlugin::createWindow(PluginContainer * container) {
return new GlWindow(QOpenGLContext::currentContext());
}
void WindowOpenGLDisplayPlugin::destroyWindow() {
_window->deleteLater(); _window->deleteLater();
_window = nullptr; _window = nullptr;
} }

View file

@ -28,10 +28,14 @@ public:
virtual void removeEventFilter(QObject* filter) override; virtual void removeEventFilter(QObject* filter) override;
protected: protected:
virtual GlWindow* createWindow(PluginContainer * container);
virtual void customizeWindow(PluginContainer * container) = 0;
virtual void destroyWindow();
virtual void makeCurrent() override; virtual void makeCurrent() override;
virtual void doneCurrent() override; virtual void doneCurrent() override;
virtual void swapBuffers() override; virtual void swapBuffers() override;
virtual void customizeWindow(PluginContainer * container) = 0;
virtual void initSurfaceFormat(QSurfaceFormat& format); virtual void initSurfaceFormat(QSurfaceFormat& format);
GlWindow* _window{ nullptr }; GlWindow* _window{ nullptr };

View file

@ -30,13 +30,6 @@
#include "../OglplusHelpers.h" #include "../OglplusHelpers.h"
#define DEFAULT_HMD_UI_ANGULAR_SIZE 72.0f
using oglplus::Framebuffer;
using oglplus::DefaultFramebuffer;
// A base class for FBO wrappers that need to use the Oculus C // A base class for FBO wrappers that need to use the Oculus C
// API to manage textures via ovrHmd_CreateSwapTextureSetGL, // API to manage textures via ovrHmd_CreateSwapTextureSetGL,
@ -44,7 +37,10 @@ using oglplus::DefaultFramebuffer;
template <typename C> template <typename C>
struct RiftFramebufferWrapper : public FramebufferWrapper<C, char> { struct RiftFramebufferWrapper : public FramebufferWrapper<C, char> {
ovrHmd hmd; ovrHmd hmd;
RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {}; RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {
color = 0;
depth = 0;
};
void Resize(const uvec2 & size) { void Resize(const uvec2 & size) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo));
@ -181,6 +177,7 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) {
Q_ASSERT(false); Q_ASSERT(false);
qFatal("Failed to acquire HMD"); qFatal("Failed to acquire HMD");
} }
// Parent class relies on our _hmd intialization, so it must come after that. // Parent class relies on our _hmd intialization, so it must come after that.
ovrLayerEyeFov& sceneLayer = getSceneLayer(); ovrLayerEyeFov& sceneLayer = getSceneLayer();
memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov)); memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov));
@ -200,7 +197,6 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) {
//uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality; //uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality;
//uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 }; //uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 };
//uiLayer.QuadPoseCenter.Position = { 0, 0, -1 }; //uiLayer.QuadPoseCenter.Position = { 0, 0, -1 };
OculusBaseDisplayPlugin::activate(container); OculusBaseDisplayPlugin::activate(container);
} }
@ -209,9 +205,6 @@ void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) {
//_texture = DependencyManager::get<TextureCache>()-> //_texture = DependencyManager::get<TextureCache>()->
// getImageTexture(PathUtils::resourcesPath() + "/images/cube_texture.png"); // getImageTexture(PathUtils::resourcesPath() + "/images/cube_texture.png");
_uiSurface = loadSphereSection(_program, glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE), aspect(getCanvasSize()));
uvec2 mirrorSize = toGlm(_window->geometry().size()); uvec2 mirrorSize = toGlm(_window->geometry().size());
_mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd)); _mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd));
_mirrorFbo->Init(mirrorSize); _mirrorFbo->Init(mirrorSize);
@ -233,7 +226,6 @@ void OculusWin32DisplayPlugin::deactivate() {
makeCurrent(); makeCurrent();
_sceneFbo.reset(); _sceneFbo.reset();
_mirrorFbo.reset(); _mirrorFbo.reset();
_uiSurface.reset();
doneCurrent(); doneCurrent();
PerformanceTimer::setActive(false); PerformanceTimer::setActive(false);
@ -244,11 +236,8 @@ void OculusWin32DisplayPlugin::deactivate() {
ovr_Shutdown(); ovr_Shutdown();
} }
void OculusWin32DisplayPlugin::display( void OculusWin32DisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
using namespace oglplus; using namespace oglplus;
// Need to make sure only the display plugin is responsible for // Need to make sure only the display plugin is responsible for
// controlling vsync // controlling vsync
wglSwapIntervalEXT(0); wglSwapIntervalEXT(0);
@ -257,68 +246,19 @@ void OculusWin32DisplayPlugin::display(
auto size = _sceneFbo->size; auto size = _sceneFbo->size;
Context::Viewport(size.x, size.y); Context::Viewport(size.x, size.y);
glClearColor(0, 0, 0, 0);
Context::Clear().ColorBuffer();
_program->Bind(); _program->Bind();
Mat4Uniform(*_program, "Projection").Set(mat4()); Mat4Uniform(*_program, "Projection").Set(mat4());
Mat4Uniform(*_program, "ModelView").Set(mat4()); Mat4Uniform(*_program, "ModelView").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture); glBindTexture(GL_TEXTURE_2D, finalTexture);
_plane->Use(); _plane->Use();
_plane->Draw(); _plane->Draw();
Context::Enable(Capability::Blend);
glBindTexture(GL_TEXTURE_2D, overlayTexture);
for_each_eye([&](Eye eye) {
Context::Viewport(eye == Left ? 0 : size.x / 2, 0, size.x / 2, size.y);
Mat4Uniform(*_program, "Projection").Set(_compositeEyeProjections[eye]);
Mat4Uniform(*_program, "ModelView").Set(glm::scale(glm::inverse(getModelview(eye, mat4())), vec3(1)));
_uiSurface->Use();
_uiSurface->Draw();
}); });
Context::Disable(Capability::Blend);
});
/*
An alternative way to render the UI is to pass it specifically as a composition layer to
the Oculus SDK which should technically result in higher quality. However, the SDK doesn't
have a mechanism to present the image as a sphere section, which is our desired look.
*/
#if 0
ovrLayerQuad& uiLayer = getUiLayer();
if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) {
_uiFbo->Resize(overlaySize);
uiLayer.ColorTexture = _uiFbo->color;
uiLayer.Viewport.Size.w = overlaySize.x;
uiLayer.Viewport.Size.h = overlaySize.y;
float overlayAspect = aspect(overlaySize);
uiLayer.QuadSize.x = 1.0f;
uiLayer.QuadSize.y = 1.0f / overlayAspect;
}
_uiFbo->Bound([&] {
Q_ASSERT(0 == glGetError());
using namespace oglplus;
Context::Viewport(_uiFbo->size.x, _uiFbo->size.y);
glClearColor(0, 0, 0, 0);
Context::Clear().ColorBuffer();
_program->Bind();
glBindTexture(GL_TEXTURE_2D, overlayTexture);
_plane->Use();
_plane->Draw();
Q_ASSERT(0 == glGetError());
});
#endif
ovrLayerEyeFov& sceneLayer = getSceneLayer(); ovrLayerEyeFov& sceneLayer = getSceneLayer();
ovr_for_each_eye([&](ovrEyeType eye) { ovr_for_each_eye([&](ovrEyeType eye) {
sceneLayer.RenderPose[eye] = _eyePoses[eye]; sceneLayer.RenderPose[eye] = _eyePoses[eye];
}); });
auto windowSize = toGlm(getDeviceSize()); auto windowSize = toGlm(getDeviceSize());
/* /*
@ -377,6 +317,39 @@ bool OculusWin32DisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
otherwise the swapbuffer delay will interefere with the framerate of the headset otherwise the swapbuffer delay will interefere with the framerate of the headset
*/ */
void OculusWin32DisplayPlugin::finishFrame() { void OculusWin32DisplayPlugin::finishFrame() {
// swapBuffers(); swapBuffers();
doneCurrent(); doneCurrent();
}; };
#if 0
/*
An alternative way to render the UI is to pass it specifically as a composition layer to
the Oculus SDK which should technically result in higher quality. However, the SDK doesn't
have a mechanism to present the image as a sphere section, which is our desired look.
*/
ovrLayerQuad& uiLayer = getUiLayer();
if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) {
_uiFbo->Resize(overlaySize);
uiLayer.ColorTexture = _uiFbo->color;
uiLayer.Viewport.Size.w = overlaySize.x;
uiLayer.Viewport.Size.h = overlaySize.y;
float overlayAspect = aspect(overlaySize);
uiLayer.QuadSize.x = 1.0f;
uiLayer.QuadSize.y = 1.0f / overlayAspect;
}
_uiFbo->Bound([&] {
Q_ASSERT(0 == glGetError());
using namespace oglplus;
Context::Viewport(_uiFbo->size.x, _uiFbo->size.y);
glClearColor(0, 0, 0, 0);
Context::Clear().ColorBuffer();
_program->Bind();
glBindTexture(GL_TEXTURE_2D, overlayTexture);
_plane->Use();
_plane->Draw();
Q_ASSERT(0 == glGetError());
});
#endif

View file

@ -26,12 +26,11 @@ public:
virtual void activate(PluginContainer * container) override; virtual void activate(PluginContainer * container) override;
virtual void deactivate() override; virtual void deactivate() override;
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
virtual bool eventFilter(QObject* receiver, QEvent* event) override; virtual bool eventFilter(QObject* receiver, QEvent* event) override;
protected: protected:
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
virtual void customizeContext(PluginContainer * container) override; virtual void customizeContext(PluginContainer * container) override;
// Do not perform swap in finish // Do not perform swap in finish
virtual void finishFrame() override; virtual void finishFrame() override;
@ -45,5 +44,4 @@ private:
SwapFboPtr _sceneFbo; SwapFboPtr _sceneFbo;
MirrorFboPtr _mirrorFbo; MirrorFboPtr _mirrorFbo;
ovrLayerEyeFov _sceneLayer; ovrLayerEyeFov _sceneLayer;
ShapeWrapperPtr _uiSurface;
}; };

View file

@ -26,11 +26,6 @@ const QString & InterleavedStereoDisplayPlugin::getName() {
InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() { InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
} }
void InterleavedStereoDisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
}
void InterleavedStereoDisplayPlugin::customizeContext(PluginContainer * container) { void InterleavedStereoDisplayPlugin::customizeContext(PluginContainer * container) {
StereoDisplayPlugin::customizeContext(container); StereoDisplayPlugin::customizeContext(container);
// Set up the stencil buffers? Or use a custom shader? // Set up the stencil buffers? Or use a custom shader?

View file

@ -15,9 +15,6 @@ public:
InterleavedStereoDisplayPlugin(); InterleavedStereoDisplayPlugin();
virtual const QString & getName() override; virtual const QString & getName() override;
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
// initialize OpenGL context settings needed by the plugin // initialize OpenGL context settings needed by the plugin
virtual void customizeContext(PluginContainer * container) override; virtual void customizeContext(PluginContainer * container) override;

View file

@ -26,83 +26,3 @@ const QString & SideBySideStereoDisplayPlugin::getName() {
SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() { SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() {
} }
template <typename F>
void sbs_for_each_eye(const uvec2& size, F f) {
QRect r(QPoint(0, 0), QSize(size.x / 2, size.y));
for_each_eye([&](Eye eye) {
oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height());
f(eye);
}, [&] {
r.moveLeft(r.width());
});
}
void SideBySideStereoDisplayPlugin::display(
GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) {
makeCurrent();
Q_ASSERT(0 == glGetError());
uvec2 size = toGlm(getDeviceSize());
using namespace oglplus;
Context::Viewport(size.x, size.y);
Context::Clear().ColorBuffer();
_program->Bind();
Mat4Uniform(*_program, "ModelView").Set(mat4());
Mat4Uniform(*_program, "Projection").Set(mat4());
glBindTexture(GL_TEXTURE_2D, sceneTexture);
_plane->Use();
_plane->Draw();
// FIXME the
const float screenAspect = aspect(size);
const GLfloat distance = 1.0f;
const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES);
const GLfloat halfQuadWidth = halfQuadHeight * screenAspect;
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), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP);
Mat4Uniform(*_program, "Projection").Set(pr);
// Position the camera relative to the overlay texture
MatrixStack mv;
mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0));
sbs_for_each_eye(size, [&](Eye eye) {
mv.withPush([&] {
// translate
mv.top() = getModelview(eye, mv.top());
Mat4Uniform(*_program, "ModelView").Set(mv.top());
_plane->Draw();
});
});
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glm::vec2 canvasSize = getCanvasSize();
glm::vec2 mouse = toGlm(_window->mapFromGlobal(QCursor::pos()));
mouse /= canvasSize;
mouse *= 2.0f;
mouse -= 1.0f;
mouse.y *= -1.0f;
sbs_for_each_eye(size, [&](Eye eye) {
mv.withPush([&] {
// translate
mv.top() = getModelview(eye, mv.top());
mv.translate(mouse);
//mv.scale(0.05f);
mv.scale(vec3(0.025f, 0.05f, 1.0f));
Mat4Uniform(*_program, "ModelView").Set(mv.top());
_plane->Draw();
});
});
Context::Disable(Capability::Blend);
}

View file

@ -14,9 +14,6 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin {
public: public:
SideBySideStereoDisplayPlugin(); SideBySideStereoDisplayPlugin();
virtual const QString & getName() override; virtual const QString & getName() override;
void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
private: private:
static const QString NAME; static const QString NAME;
}; };

View file

@ -2,10 +2,10 @@
#include <QString> #include <QString>
class QMainWindow; class GlWindow;
class PluginContainer { class PluginContainer {
public: public:
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0;
virtual QMainWindow* getAppMainWindow() = 0; virtual GlWindow* getVisibleWindow() = 0;
}; };