mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 08:14:48 +02:00
Working on display plugins
This commit is contained in:
parent
edfb1305af
commit
1b7efe9a02
25 changed files with 430 additions and 269 deletions
|
@ -90,6 +90,7 @@
|
|||
#include <UserActivityLogger.h>
|
||||
#include <UUID.h>
|
||||
#include <VrMenu.h>
|
||||
#include <ui/ApplicationOverlayCompositor.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "AudioClient.h"
|
||||
|
@ -101,6 +102,7 @@
|
|||
#include "Util.h"
|
||||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "GlWindow.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
#include "audio/AudioToolBox.h"
|
||||
|
@ -506,29 +508,39 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
|||
|
||||
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->setVisible(true);
|
||||
container->setFocus();
|
||||
_offscreenContext->makeCurrent();
|
||||
initializeGL();
|
||||
// initialization continues in initializeGL when OpenGL context is ready
|
||||
|
||||
|
||||
_menuBarHeight = Menu::getInstance()->height();
|
||||
|
||||
#if 0
|
||||
_fullscreenMenuWidget->setParent(_glWidget);
|
||||
#endif
|
||||
|
||||
_menuBarHeight = Menu::getInstance()->height();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
|
||||
setFullscreen(true); // Initialize menu bar show/hide
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
_toolWindow = new ToolWindow();
|
||||
_toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint);
|
||||
_toolWindow->setWindowTitle("Tools");
|
||||
|
||||
_offscreenContext->create();
|
||||
|
||||
_compositor = CompositorPtr(new ApplicationOverlayCompositor());
|
||||
_offscreenContext->makeCurrent();
|
||||
initializeGL();
|
||||
// initialization continues in initializeGL when OpenGL context is ready
|
||||
|
||||
// Tell our entity edit sender about our known jurisdictions
|
||||
_entityEditSender.setServerJurisdictions(&_entityServerJurisdictions);
|
||||
|
@ -949,15 +961,16 @@ void Application::paintGL() {
|
|||
// 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,
|
||||
// but may be better handled with a fence object
|
||||
glFinish();
|
||||
|
||||
|
||||
// glFinish();
|
||||
_offscreenContext->doneCurrent();
|
||||
Q_ASSERT(!QOpenGLContext::currentContext());
|
||||
displayPlugin->preDisplay();
|
||||
|
||||
displayPlugin->display(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)), finalFbo->getSize(),
|
||||
_applicationOverlay.getOverlayTexture(), getCanvasSize());
|
||||
GLuint finalTexture = _compositor->composite(displayPlugin,
|
||||
gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)), finalFbo->getSize(),
|
||||
_applicationOverlay.getOverlayTexture(), getCanvasSize());
|
||||
|
||||
displayPlugin->preDisplay();
|
||||
displayPlugin->display(finalTexture, finalFbo->getSize());
|
||||
displayPlugin->finishFrame();
|
||||
Q_ASSERT(!QOpenGLContext::currentContext());
|
||||
_offscreenContext->makeCurrent();
|
||||
|
@ -1427,7 +1440,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
|
||||
// Show/hide menu bar in fullscreen
|
||||
if (event->globalY() > _menuBarHeight) {
|
||||
|
@ -1438,6 +1451,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) {
|
|||
Menu::getInstance()->setFixedHeight(_menuBarHeight);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
_entities.mouseMoveEvent(event, deviceID);
|
||||
|
||||
|
@ -1764,6 +1778,7 @@ void Application::idle() {
|
|||
emit checkBackgroundDownloads();
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Application::setFullscreen(bool fullscreen) {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) {
|
||||
Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen);
|
||||
|
@ -1822,7 +1837,6 @@ void Application::setFullscreen(bool fullscreen) {
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void Application::setEnable3DTVMode(bool enable3DTVMode) {
|
||||
resizeGL();
|
||||
}
|
||||
|
@ -3006,8 +3020,11 @@ PickRay Application::computePickRay(float x, float y) const {
|
|||
if (isHMDMode()) {
|
||||
getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction);
|
||||
} else {
|
||||
auto frustum = activeRenderingThread ? getDisplayViewFrustum() : getViewFrustum();
|
||||
frustum->computePickRay(x, y, result.origin, result.direction);
|
||||
if (QThread::currentThread() == activeRenderingThread) {
|
||||
getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
} else {
|
||||
getViewFrustum()->computePickRay(x, y, result.origin, result.direction);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -3214,7 +3231,7 @@ void Application::displaySide(const Camera& theCamera, bool selfAvatarOnly) {
|
|||
skybox = skyStage->getSkybox();
|
||||
if (skybox) {
|
||||
gpu::Batch batch;
|
||||
model::Skybox::render(batch, _viewFrustum, *skybox);
|
||||
model::Skybox::render(batch, _displayViewFrustum, *skybox);
|
||||
|
||||
gpu::GLBackend::renderBatch(batch);
|
||||
glUseProgram(0);
|
||||
|
@ -4656,6 +4673,6 @@ void Application::addMenuItem(const QString& path, std::function<void()> onClick
|
|||
|
||||
}
|
||||
|
||||
QMainWindow* Application::getAppMainWindow() {
|
||||
return _window;
|
||||
GlWindow* Application::getVisibleWindow() {
|
||||
return _glWindow;
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@
|
|||
#include "DatagramProcessor.h"
|
||||
#include "Environment.h"
|
||||
#include "FileLogger.h"
|
||||
#include "GLCanvas.h"
|
||||
#include "Menu.h"
|
||||
#include "PacketHeaders.h"
|
||||
#include "Physics.h"
|
||||
|
@ -91,6 +90,9 @@ class MainWindow;
|
|||
class Node;
|
||||
class ProgramObject;
|
||||
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_GREEN = 1.0f;
|
||||
|
@ -137,6 +139,7 @@ class Application;
|
|||
|
||||
typedef bool (Application::* AcceptURLMethod)(const QString &);
|
||||
|
||||
|
||||
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface, PluginContainer {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -299,7 +302,7 @@ public:
|
|||
|
||||
// Plugin container support
|
||||
virtual void addMenuItem(const QString& path, std::function<void()> onClicked, bool checkable, bool checked, const QString& groupName);
|
||||
virtual QMainWindow* getAppMainWindow();
|
||||
virtual GlWindow* getVisibleWindow();
|
||||
|
||||
private:
|
||||
DisplayPlugin * getActiveDisplayPlugin();
|
||||
|
@ -446,8 +449,11 @@ private slots:
|
|||
|
||||
void connectedToDomain(const QString& hostname);
|
||||
|
||||
#if 0
|
||||
friend class HMDToolsDialog;
|
||||
void setFullscreen(bool fullscreen);
|
||||
#endif
|
||||
|
||||
void cameraMenuChanged();
|
||||
|
||||
void closeMirrorView();
|
||||
|
@ -544,6 +550,8 @@ private:
|
|||
ViewFrustum _shadowViewFrustum;
|
||||
quint64 _lastQueriedTime;
|
||||
|
||||
CompositorPtr _compositor;
|
||||
|
||||
float _trailingAudioLoudness;
|
||||
|
||||
OctreeQuery _octreeQuery; // NodeData derived class for querying octee cells from octree servers
|
||||
|
@ -653,6 +661,7 @@ private:
|
|||
QThread _settingsThread;
|
||||
QTimer _settingsTimer;
|
||||
|
||||
GlWindow* _glWindow{ nullptr };
|
||||
void checkSkeleton();
|
||||
|
||||
QWidget* _fullscreenMenuWidget = new QWidget();
|
||||
|
|
|
@ -98,9 +98,12 @@ void MainWindow::changeEvent(QEvent* event) {
|
|||
emit windowShown(true);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (isFullScreen() != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) {
|
||||
Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, isFullScreen());
|
||||
}
|
||||
#endif
|
||||
|
||||
} else if (event->type() == QEvent::ActivationChange) {
|
||||
if (isActiveWindow()) {
|
||||
emit windowShown(true);
|
||||
|
|
|
@ -239,6 +239,7 @@ Menu::Menu() {
|
|||
displayModeGroup->setExclusive(true);
|
||||
}
|
||||
|
||||
#if 0
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu,
|
||||
MenuOption::Fullscreen,
|
||||
#ifdef Q_OS_MAC
|
||||
|
@ -249,6 +250,7 @@ Menu::Menu() {
|
|||
false,
|
||||
qApp,
|
||||
SLOT(setFullscreen(bool)));
|
||||
#endif
|
||||
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPerson,
|
||||
0, // QML Qt::Key_P,
|
||||
|
@ -260,6 +262,7 @@ Menu::Menu() {
|
|||
0, // QML Qt::Key_H,
|
||||
false, qApp, SLOT(cameraMenuChanged()));
|
||||
|
||||
#if 0
|
||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools,
|
||||
#ifdef Q_OS_MAC
|
||||
Qt::META | Qt::Key_H,
|
||||
|
@ -269,6 +272,7 @@ Menu::Menu() {
|
|||
false,
|
||||
dialogsManager.data(),
|
||||
SLOT(hmdTools(bool)));
|
||||
#endif
|
||||
|
||||
addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
|
||||
dialogsManager.data(), SLOT(editAttachments()));
|
||||
|
|
|
@ -194,12 +194,10 @@ namespace MenuOption {
|
|||
const QString FilterSixense = "Smooth Sixense Movement";
|
||||
const QString FirstPerson = "First Person";
|
||||
const QString FrameTimer = "Show Timer";
|
||||
const QString Fullscreen = "Fullscreen";
|
||||
const QString FullscreenMirror = "Fullscreen Mirror";
|
||||
const QString GlowWhenSpeaking = "Glow When Speaking";
|
||||
const QString NamesAboveHeads = "Names Above Heads";
|
||||
const QString GoToUser = "Go To User";
|
||||
const QString HMDTools = "HMD Tools";
|
||||
const QString IncreaseAvatarSize = "Increase Avatar Size";
|
||||
const QString KeyboardMotorControl = "Enable Keyboard Motor Control";
|
||||
const QString LeapMotionOnHMD = "Leap Motion on HMD";
|
||||
|
|
209
interface/src/ui/ApplicationOverlayCompositor.cpp
Normal file
209
interface/src/ui/ApplicationOverlayCompositor.cpp
Normal 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);
|
||||
}
|
37
interface/src/ui/ApplicationOverlayCompositor.h
Normal file
37
interface/src/ui/ApplicationOverlayCompositor.h
Normal 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>;
|
|
@ -68,13 +68,12 @@ public:
|
|||
* OpenGL context
|
||||
*/
|
||||
virtual void preDisplay() = 0;
|
||||
|
||||
/**
|
||||
* Sends the scene texture and the overlay 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
|
||||
* Sends the scene texture to the display plugin.
|
||||
*/
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) = 0;
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) = 0;
|
||||
|
||||
/**
|
||||
* Called by the application immeidately after display. For OpenGL based
|
||||
* displays, this is the best place to put the buffer swap
|
||||
|
|
|
@ -7,32 +7,47 @@
|
|||
//
|
||||
#include "MainWindowOpenGLDisplayPlugin.h"
|
||||
|
||||
#include <GlWindow.h>
|
||||
#include <QOpenGLContext>
|
||||
#include <plugins/PluginContainer.h>
|
||||
#include <QWidget>
|
||||
#include <QMainWindow>
|
||||
|
||||
#include <GlWindow.h>
|
||||
#include <plugins/PluginContainer.h>
|
||||
|
||||
MainWindowOpenGLDisplayPlugin::MainWindowOpenGLDisplayPlugin() {
|
||||
}
|
||||
|
||||
void MainWindowOpenGLDisplayPlugin::activate(PluginContainer * container) {
|
||||
WindowOpenGLDisplayPlugin::activate(container);
|
||||
GlWindow* MainWindowOpenGLDisplayPlugin::createWindow(PluginContainer * container) {
|
||||
return container->getVisibleWindow();
|
||||
}
|
||||
|
||||
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) {
|
||||
WindowOpenGLDisplayPlugin::customizeContext(container);
|
||||
QWidget* widget = QWidget::createWindowContainer(_window);
|
||||
auto mainWindow = container->getAppMainWindow();
|
||||
mainWindow->setCentralWidget(widget);
|
||||
mainWindow->resize(mainWindow->geometry().size());
|
||||
_window->resize(_window->geometry().size());
|
||||
void MainWindowOpenGLDisplayPlugin::destroyWindow() {
|
||||
_window = nullptr;
|
||||
}
|
||||
|
||||
void MainWindowOpenGLDisplayPlugin::deactivate() {
|
||||
WindowOpenGLDisplayPlugin::deactivate();
|
||||
void MainWindowOpenGLDisplayPlugin::display(
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -9,17 +9,16 @@
|
|||
|
||||
#include "WindowOpenGLDisplayPlugin.h"
|
||||
|
||||
class GlWindow;
|
||||
class QSurfaceFormat;
|
||||
class QGLWidget;
|
||||
|
||||
class MainWindowOpenGLDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindowOpenGLDisplayPlugin();
|
||||
virtual void activate(PluginContainer * container) override;
|
||||
virtual void deactivate() override;
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
|
||||
|
||||
protected:
|
||||
virtual void customizeWindow(PluginContainer * container) override;
|
||||
virtual void customizeContext(PluginContainer * container) override;
|
||||
virtual GlWindow* createWindow(PluginContainer * container) override final;
|
||||
virtual void customizeWindow(PluginContainer * container) override final;
|
||||
virtual void destroyWindow() override final;
|
||||
};
|
||||
|
|
|
@ -49,8 +49,7 @@ QWindow* NullDisplayPlugin::getWindow() const {
|
|||
|
||||
void NullDisplayPlugin::preRender() {}
|
||||
void NullDisplayPlugin::preDisplay() {}
|
||||
void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) {}
|
||||
void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize) {}
|
||||
void NullDisplayPlugin::finishFrame() {}
|
||||
|
||||
void NullDisplayPlugin::activate(PluginContainer * container) {}
|
||||
|
|
|
@ -29,7 +29,6 @@ public:
|
|||
virtual QWindow* getWindow() const;
|
||||
virtual void preRender();
|
||||
virtual void preDisplay();
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize);
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize);
|
||||
virtual void finishFrame();
|
||||
};
|
||||
|
|
|
@ -29,12 +29,12 @@
|
|||
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
typedef std::shared_ptr<oglplus::Framebuffer> FramebufferPtr;
|
||||
typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr;
|
||||
typedef std::shared_ptr<oglplus::Buffer> BufferPtr;
|
||||
typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr;
|
||||
typedef std::shared_ptr<oglplus::Program> ProgramPtr;
|
||||
typedef oglplus::Uniform<mat4> Mat4Uniform;
|
||||
using FramebufferPtr = std::shared_ptr<oglplus::Framebuffer>;
|
||||
using ShapeWrapperPtr = std::shared_ptr<oglplus::shapes::ShapeWrapper>;
|
||||
using BufferPtr = std::shared_ptr<oglplus::Buffer>;
|
||||
using VertexArrayPtr = std::shared_ptr<oglplus::VertexArray>;
|
||||
using ProgramPtr = std::shared_ptr<oglplus::Program>;
|
||||
using Mat4Uniform = oglplus::Uniform<mat4>;
|
||||
|
||||
ProgramPtr loadDefaultShader();
|
||||
void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs);
|
||||
|
@ -56,8 +56,8 @@ template <
|
|||
struct FramebufferWrapper {
|
||||
uvec2 size;
|
||||
oglplus::Framebuffer fbo;
|
||||
C color{ 0 };
|
||||
D depth{ 0 };
|
||||
C color;
|
||||
D depth;
|
||||
|
||||
FramebufferWrapper() {}
|
||||
|
||||
|
@ -112,8 +112,7 @@ protected:
|
|||
virtual void initDone() = 0;
|
||||
};
|
||||
|
||||
|
||||
struct BasicFramebufferWrapper : public FramebufferWrapper < oglplus::Texture, oglplus::Renderbuffer > {
|
||||
struct BasicFramebufferWrapper : public FramebufferWrapper <oglplus::Texture, oglplus::Renderbuffer> {
|
||||
protected:
|
||||
virtual void initDepth() override {
|
||||
using namespace oglplus;
|
||||
|
@ -131,9 +130,9 @@ protected:
|
|||
.WrapS(TextureWrap::ClampToEdge)
|
||||
.WrapT(TextureWrap::ClampToEdge)
|
||||
.Image2D(
|
||||
0, PixelDataInternalFormat::RGBA8,
|
||||
size.x, size.y,
|
||||
0, PixelDataFormat::RGB, PixelDataType::UnsignedByte, nullptr
|
||||
0, PixelDataInternalFormat::RGBA8,
|
||||
size.x, size.y,
|
||||
0, PixelDataFormat::RGB, PixelDataType::UnsignedByte, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -146,4 +145,6 @@ protected:
|
|||
fbo.Complete(target);
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
using BasicFramebufferWrapperPtr = std::shared_ptr<BasicFramebufferWrapper>;
|
|
@ -8,11 +8,6 @@
|
|||
#include "OpenGLDisplayPlugin.h"
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <TextureCache.h>
|
||||
#include <PathUtils.h>
|
||||
|
||||
#include <QOpenGLContext>
|
||||
#include <QCursor>
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include <GLWindow.h>
|
||||
|
@ -50,8 +45,6 @@ void OpenGLDisplayPlugin::customizeContext(PluginContainer * container) {
|
|||
_program = loadDefaultShader();
|
||||
_plane = loadPlane(_program);
|
||||
Context::ClearColor(0, 0, 0, 1);
|
||||
_crosshairTexture = DependencyManager::get<TextureCache>()->
|
||||
getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
|
||||
}
|
||||
|
||||
void OpenGLDisplayPlugin::activate(PluginContainer * container) {
|
||||
|
@ -60,11 +53,11 @@ void OpenGLDisplayPlugin::activate(PluginContainer * container) {
|
|||
|
||||
void OpenGLDisplayPlugin::deactivate() {
|
||||
_timer.stop();
|
||||
|
||||
makeCurrent();
|
||||
Q_ASSERT(0 == glGetError());
|
||||
_plane.reset();
|
||||
_program.reset();
|
||||
_crosshairTexture.reset();
|
||||
doneCurrent();
|
||||
}
|
||||
|
||||
|
@ -109,25 +102,15 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
|
|||
}
|
||||
|
||||
void OpenGLDisplayPlugin::display(
|
||||
GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) {
|
||||
makeCurrent();
|
||||
Q_ASSERT(0 == glGetError());
|
||||
uvec2 size = toGlm(getDeviceSize());
|
||||
GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||
using namespace oglplus;
|
||||
|
||||
uvec2 size = toGlm(getDeviceSize());
|
||||
Context::Viewport(size.x, size.y);
|
||||
glClearColor(0, 1, 1, 1);
|
||||
Context::Clear().ColorBuffer().DepthBuffer();
|
||||
Context::Clear().ColorBuffer();
|
||||
|
||||
_program->Bind();
|
||||
Mat4Uniform(*_program, "ModelView").Set(mat4());
|
||||
Mat4Uniform(*_program, "Projection").Set(mat4());
|
||||
glBindTexture(GL_TEXTURE_2D, sceneTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, finalTexture);
|
||||
_plane->Use();
|
||||
_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());
|
||||
}
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
|
||||
#include <QTimer>
|
||||
|
||||
#include <gpu/Texture.h>
|
||||
|
||||
#include "DisplayPlugin.h"
|
||||
#include "OglplusHelpers.h"
|
||||
|
||||
class GlWindow;
|
||||
class QOpenGLContext;
|
||||
|
||||
class OpenGLDisplayPlugin : public DisplayPlugin {
|
||||
public:
|
||||
OpenGLDisplayPlugin();
|
||||
|
@ -29,9 +28,7 @@ public:
|
|||
|
||||
virtual bool eventFilter(QObject* receiver, QEvent* event) override;
|
||||
|
||||
void display(
|
||||
GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
|
||||
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override;
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -43,10 +40,9 @@ protected:
|
|||
virtual void doneCurrent() = 0;
|
||||
virtual void swapBuffers() = 0;
|
||||
|
||||
QTimer _timer;
|
||||
ProgramPtr _program;
|
||||
QTimer _timer;
|
||||
ProgramPtr _program;
|
||||
ShapeWrapperPtr _plane;
|
||||
gpu::TexturePointer _crosshairTexture;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <QGLContext>
|
||||
#include <QGLWidget>
|
||||
#include "plugins/PluginContainer.h"
|
||||
|
||||
#if 0
|
||||
WidgetOpenGLDisplayPlugin::WidgetOpenGLDisplayPlugin() {
|
||||
}
|
||||
|
||||
|
@ -105,4 +105,5 @@ void WidgetOpenGLDisplayPlugin::removeEventFilter(QObject* filter) {
|
|||
|
||||
QWindow* WidgetOpenGLDisplayPlugin::getWindow() const {
|
||||
return _widget->windowHandle();
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -42,7 +42,7 @@ void WindowOpenGLDisplayPlugin::initSurfaceFormat(QSurfaceFormat& format) {
|
|||
|
||||
void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) {
|
||||
OpenGLDisplayPlugin::activate(container);
|
||||
_window = new GlWindow(QOpenGLContext::currentContext());
|
||||
_window = createWindow(container);
|
||||
|
||||
QSurfaceFormat format;
|
||||
initSurfaceFormat(format);
|
||||
|
@ -57,6 +57,14 @@ void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) {
|
|||
|
||||
void WindowOpenGLDisplayPlugin::deactivate() {
|
||||
OpenGLDisplayPlugin::deactivate();
|
||||
destroyWindow();
|
||||
}
|
||||
|
||||
GlWindow* WindowOpenGLDisplayPlugin::createWindow(PluginContainer * container) {
|
||||
return new GlWindow(QOpenGLContext::currentContext());
|
||||
}
|
||||
|
||||
void WindowOpenGLDisplayPlugin::destroyWindow() {
|
||||
_window->deleteLater();
|
||||
_window = nullptr;
|
||||
}
|
||||
|
@ -87,4 +95,4 @@ void WindowOpenGLDisplayPlugin::removeEventFilter(QObject* filter) {
|
|||
|
||||
QWindow* WindowOpenGLDisplayPlugin::getWindow() const {
|
||||
return _window;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,14 @@ public:
|
|||
virtual void removeEventFilter(QObject* filter) override;
|
||||
|
||||
protected:
|
||||
virtual GlWindow* createWindow(PluginContainer * container);
|
||||
virtual void customizeWindow(PluginContainer * container) = 0;
|
||||
|
||||
virtual void destroyWindow();
|
||||
|
||||
virtual void makeCurrent() override;
|
||||
virtual void doneCurrent() override;
|
||||
virtual void swapBuffers() override;
|
||||
virtual void customizeWindow(PluginContainer * container) = 0;
|
||||
virtual void initSurfaceFormat(QSurfaceFormat& format);
|
||||
|
||||
GlWindow* _window{ nullptr };
|
||||
|
|
|
@ -30,13 +30,6 @@
|
|||
|
||||
#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
|
||||
// API to manage textures via ovrHmd_CreateSwapTextureSetGL,
|
||||
|
@ -44,7 +37,10 @@ using oglplus::DefaultFramebuffer;
|
|||
template <typename C>
|
||||
struct RiftFramebufferWrapper : public FramebufferWrapper<C, char> {
|
||||
ovrHmd hmd;
|
||||
RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {};
|
||||
RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {
|
||||
color = 0;
|
||||
depth = 0;
|
||||
};
|
||||
|
||||
void Resize(const uvec2 & size) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo));
|
||||
|
@ -181,6 +177,7 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) {
|
|||
Q_ASSERT(false);
|
||||
qFatal("Failed to acquire HMD");
|
||||
}
|
||||
|
||||
// Parent class relies on our _hmd intialization, so it must come after that.
|
||||
ovrLayerEyeFov& sceneLayer = getSceneLayer();
|
||||
memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
||||
|
@ -200,7 +197,6 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) {
|
|||
//uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality;
|
||||
//uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 };
|
||||
//uiLayer.QuadPoseCenter.Position = { 0, 0, -1 };
|
||||
|
||||
OculusBaseDisplayPlugin::activate(container);
|
||||
}
|
||||
|
||||
|
@ -209,9 +205,6 @@ void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) {
|
|||
|
||||
//_texture = DependencyManager::get<TextureCache>()->
|
||||
// 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());
|
||||
_mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd));
|
||||
_mirrorFbo->Init(mirrorSize);
|
||||
|
@ -233,7 +226,6 @@ void OculusWin32DisplayPlugin::deactivate() {
|
|||
makeCurrent();
|
||||
_sceneFbo.reset();
|
||||
_mirrorFbo.reset();
|
||||
_uiSurface.reset();
|
||||
doneCurrent();
|
||||
PerformanceTimer::setActive(false);
|
||||
|
||||
|
@ -244,11 +236,8 @@ void OculusWin32DisplayPlugin::deactivate() {
|
|||
ovr_Shutdown();
|
||||
}
|
||||
|
||||
void OculusWin32DisplayPlugin::display(
|
||||
GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) {
|
||||
void OculusWin32DisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||
using namespace oglplus;
|
||||
|
||||
// Need to make sure only the display plugin is responsible for
|
||||
// controlling vsync
|
||||
wglSwapIntervalEXT(0);
|
||||
|
@ -257,68 +246,19 @@ void OculusWin32DisplayPlugin::display(
|
|||
auto size = _sceneFbo->size;
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_2D, finalTexture);
|
||||
_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);
|
||||
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();
|
||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||
sceneLayer.RenderPose[eye] = _eyePoses[eye];
|
||||
});
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
void OculusWin32DisplayPlugin::finishFrame() {
|
||||
// swapBuffers();
|
||||
swapBuffers();
|
||||
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
|
||||
|
|
|
@ -26,12 +26,11 @@ public:
|
|||
virtual void activate(PluginContainer * container) 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;
|
||||
|
||||
protected:
|
||||
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
|
||||
virtual void customizeContext(PluginContainer * container) override;
|
||||
// Do not perform swap in finish
|
||||
virtual void finishFrame() override;
|
||||
|
@ -45,5 +44,4 @@ private:
|
|||
SwapFboPtr _sceneFbo;
|
||||
MirrorFboPtr _mirrorFbo;
|
||||
ovrLayerEyeFov _sceneLayer;
|
||||
ShapeWrapperPtr _uiSurface;
|
||||
};
|
||||
|
|
|
@ -26,11 +26,6 @@ const QString & InterleavedStereoDisplayPlugin::getName() {
|
|||
InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
|
||||
}
|
||||
|
||||
void InterleavedStereoDisplayPlugin::display(
|
||||
GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) {
|
||||
}
|
||||
|
||||
void InterleavedStereoDisplayPlugin::customizeContext(PluginContainer * container) {
|
||||
StereoDisplayPlugin::customizeContext(container);
|
||||
// Set up the stencil buffers? Or use a custom shader?
|
||||
|
|
|
@ -15,9 +15,6 @@ public:
|
|||
InterleavedStereoDisplayPlugin();
|
||||
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
|
||||
virtual void customizeContext(PluginContainer * container) override;
|
||||
|
||||
|
|
|
@ -26,83 +26,3 @@ const QString & SideBySideStereoDisplayPlugin::getName() {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin {
|
|||
public:
|
||||
SideBySideStereoDisplayPlugin();
|
||||
virtual const QString & getName() override;
|
||||
|
||||
void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
|
||||
GLuint overlayTexture, const glm::uvec2& overlaySize) override;
|
||||
private:
|
||||
static const QString NAME;
|
||||
};
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
#include <QString>
|
||||
|
||||
class QMainWindow;
|
||||
class GlWindow;
|
||||
|
||||
class PluginContainer {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue