Merge pull request #5121 from ZappoMan/attemptRevertOverlaysBork2

REVERT recent changes to overlays that seem to be breaking stuff
This commit is contained in:
Philip Rosedale 2015-06-12 13:50:53 -07:00
commit b628df45bc
11 changed files with 497 additions and 348 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -955,7 +955,6 @@ void Application::paintGL() {
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();
displaySide(&renderArgs, _myCamera); displaySide(&renderArgs, _myCamera);
_applicationOverlay.displayOverlayTexture(&renderArgs);
glPopMatrix(); glPopMatrix();
if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) {
@ -972,6 +971,8 @@ void Application::paintGL() {
0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(),
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
_applicationOverlay.displayOverlayTexture();
} }
if (!OculusManager::isConnected() || OculusManager::allowSwap()) { if (!OculusManager::isConnected() || OculusManager::allowSwap()) {

View file

@ -615,10 +615,12 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
renderArgs->_renderSide = RenderArgs::MONO; renderArgs->_renderSide = RenderArgs::MONO;
qApp->displaySide(renderArgs, *_camera, false); qApp->displaySide(renderArgs, *_camera, false);
qApp->getApplicationOverlay().displayOverlayTextureHmd(renderArgs, *_camera); qApp->getApplicationOverlay().displayOverlayTextureHmd(*_camera);
}); });
_activeEye = ovrEye_Count; _activeEye = ovrEye_Count;
glPopMatrix();
gpu::FramebufferPointer finalFbo; gpu::FramebufferPointer finalFbo;
//Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture //Bind the output texture from the glow shader. If glow effect is disabled, we just grab the texture
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) { if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
@ -629,7 +631,6 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer(); finalFbo = DependencyManager::get<TextureCache>()->getPrimaryFramebuffer();
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
glPopMatrix();
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glPopMatrix(); glPopMatrix();

View file

@ -12,7 +12,6 @@
#include "InterfaceConfig.h" #include "InterfaceConfig.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GlowEffect.h> #include <GlowEffect.h>
#include "gpu/GLBackend.h" #include "gpu/GLBackend.h"
@ -107,20 +106,21 @@ void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) {
_activeEye = &eye; _activeEye = &eye;
glViewport(portalX, portalY, portalW, portalH); glViewport(portalX, portalY, portalW, portalH);
glScissor(portalX, portalY, portalW, portalH); glScissor(portalX, portalY, portalW, portalH);
glm::mat4 projection = glm::frustum<float>(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ);
float fov = atan(1.0f / projection[1][1]);
projection = glm::translate(projection, vec3(eye.modelTranslation, 0, 0));
eyeCamera.setProjection(projection);
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // reset projection matrix glLoadIdentity(); // reset projection matrix
glLoadMatrixf(glm::value_ptr(projection)); glFrustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); // set left view frustum
GLfloat p[4][4];
// Really?
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
float cotangent = p[1][1];
GLfloat fov = atan(1.0f / cotangent);
glTranslatef(eye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); glLoadIdentity();
renderArgs->_renderSide = RenderArgs::MONO; renderArgs->_renderSide = RenderArgs::MONO;
qApp->displaySide(renderArgs, eyeCamera, false); qApp->displaySide(renderArgs, eyeCamera, false);
qApp->getApplicationOverlay().displayOverlayTexture(renderArgs); qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov);
_activeEye = NULL; _activeEye = NULL;
}, [&]{ }, [&]{
// render right side view // render right side view

View file

@ -14,16 +14,13 @@
#include <QOpenGLFramebufferObject> #include <QOpenGLFramebufferObject>
#include <QOpenGLTexture> #include <QOpenGLTexture>
#include <glm/gtc/type_ptr.hpp>
#include <avatar/AvatarManager.h> #include <avatar/AvatarManager.h>
#include <DeferredLightingEffect.h>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <PathUtils.h>
#include <gpu/GLBackend.h> #include <gpu/GLBackend.h>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <OffscreenUi.h>
#include <CursorManager.h>
#include <PerfStat.h> #include <PerfStat.h>
#include <OffscreenUi.h>
#include "AudioClient.h" #include "AudioClient.h"
#include "audio/AudioIOStatsRenderer.h" #include "audio/AudioIOStatsRenderer.h"
@ -36,9 +33,6 @@
#include "Util.h" #include "Util.h"
#include "ui/Stats.h" #include "ui/Stats.h"
#include "../../libraries/render-utils/standardTransformPNTC_vert.h"
#include "../../libraries/render-utils/standardDrawTexture_frag.h"
// Used to animate the magnification windows // Used to animate the magnification windows
const float MAG_SPEED = 0.08f; const float MAG_SPEED = 0.08f;
@ -120,6 +114,27 @@ bool raySphereIntersect(const glm::vec3 &dir, const glm::vec3 &origin, float r,
} }
} }
void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) {
glPushMatrix(); {
glm::vec3 axis = glm::axis(orientation);
glRotatef(glm::degrees(glm::angle(orientation)), axis.x, axis.y, axis.z);
glm::vec3 topLeft = getPoint(reticleSize / 2.0f, -reticleSize / 2.0f);
glm::vec3 topRight = getPoint(-reticleSize / 2.0f, -reticleSize / 2.0f);
glm::vec3 bottomLeft = getPoint(reticleSize / 2.0f, reticleSize / 2.0f);
glm::vec3 bottomRight = getPoint(-reticleSize / 2.0f, reticleSize / 2.0f);
// TODO: this version of renderQuad() needs to take a color
glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], alpha };
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomLeft, bottomRight, topRight,
glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f),
reticleColor, _reticleQuad);
} glPopMatrix();
}
ApplicationOverlay::ApplicationOverlay() : ApplicationOverlay::ApplicationOverlay() :
_textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)), _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)),
_textureAspectRatio(1.0f), _textureAspectRatio(1.0f),
@ -133,8 +148,7 @@ ApplicationOverlay::ApplicationOverlay() :
_previousMagnifierBottomLeft(), _previousMagnifierBottomLeft(),
_previousMagnifierBottomRight(), _previousMagnifierBottomRight(),
_previousMagnifierTopLeft(), _previousMagnifierTopLeft(),
_previousMagnifierTopRight(), _previousMagnifierTopRight()
_framebufferObject(nullptr)
{ {
memset(_reticleActive, 0, sizeof(_reticleActive)); memset(_reticleActive, 0, sizeof(_reticleActive));
memset(_magActive, 0, sizeof(_reticleActive)); memset(_magActive, 0, sizeof(_reticleActive));
@ -181,17 +195,16 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
//Handle fading and deactivation/activation of UI //Handle fading and deactivation/activation of UI
// Render 2D overlay // Render 2D overlay
glMatrixMode(GL_PROJECTION);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
buildFramebufferObject(); _overlays.buildFramebufferObject();
_overlays.bind();
_framebufferObject->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, size.x, size.y); glViewport(0, 0, size.x, size.y);
glMatrixMode(GL_PROJECTION);
glPushMatrix(); { glPushMatrix(); {
const float NEAR_CLIP = -10000; const float NEAR_CLIP = -10000;
const float FAR_CLIP = 10000; const float FAR_CLIP = 10000;
@ -213,22 +226,6 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
renderPointers(); renderPointers();
renderDomainConnectionStatusBorder(); renderDomainConnectionStatusBorder();
if (_newUiTexture) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, _newUiTexture);
DependencyManager::get<GeometryCache>()->renderUnitQuad();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
glLoadIdentity();
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
} glPopMatrix(); } glPopMatrix();
@ -238,160 +235,258 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) {
glEnable(GL_LIGHTING); glEnable(GL_LIGHTING);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
_framebufferObject->release(); _overlays.release();
} }
gpu::PipelinePointer ApplicationOverlay::getDrawPipeline() { // A quick and dirty solution for compositing the old overlay
if (!_standardDrawPipeline) { // texture with the new one
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(standardTransformPNTC_vert))); template <typename F>
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(standardDrawTexture_frag))); void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) {
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps)); glEnable(GL_TEXTURE_2D);
gpu::Shader::makeProgram((*program)); glActiveTexture(GL_TEXTURE0);
if (firstPassTexture) {
auto state = gpu::StatePointer(new gpu::State()); glBindTexture(GL_TEXTURE_2D, firstPassTexture);
f();
// enable decal blend
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
_standardDrawPipeline.reset(gpu::Pipeline::create(program, state));
} }
if (secondPassTexture) {
return _standardDrawPipeline; glBindTexture(GL_TEXTURE_2D, secondPassTexture);
} f();
void ApplicationOverlay::bindCursorTexture(gpu::Batch& batch, uint8_t cursorIndex) {
auto& cursorManager = Cursor::Manager::instance();
auto cursor = cursorManager.getCursor(cursorIndex);
auto iconId = cursor->getIcon();
if (!_cursors.count(iconId)) {
auto iconPath = cursorManager.getIconImage(cursor->getIcon());
_cursors[iconId] = DependencyManager::get<TextureCache>()->
getImageTexture(iconPath);
} }
batch.setUniformTexture(0, _cursors[iconId]); glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
} }
#define CURSOR_PIXEL_SIZE 32.0f
// Draws the FBO texture for the screen // Draws the FBO texture for the screen
void ApplicationOverlay::displayOverlayTexture(RenderArgs* renderArgs) { void ApplicationOverlay::displayOverlayTexture() {
if (_alpha == 0.0f) { if (_alpha == 0.0f) {
return; return;
} }
glMatrixMode(GL_PROJECTION);
glPushMatrix(); {
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, qApp->getDeviceSize().width(), qApp->getDeviceSize().height());
renderArgs->_context->syncCache(); static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
DependencyManager::get<GeometryCache>()->renderQuad(
topLeft, bottomRight,
texCoordTopLeft, texCoordBottomRight,
glm::vec4(1.0f, 1.0f, 1.0f, _alpha));
});
gpu::Batch batch; if (!_crosshairTexture) {
Transform model; _crosshairTexture = DependencyManager::get<TextureCache>()->
//DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch, true); getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
batch.setPipeline(getDrawPipeline()); }
batch.setModelTransform(Transform());
batch.setProjectionTransform(mat4());
batch.setViewTransform(model);
batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
DependencyManager::get<GeometryCache>()->renderUnitQuad(batch, vec4(vec3(1), _alpha));
//draw the mouse pointer //draw the mouse pointer
glm::vec2 canvasSize = qApp->getCanvasSize(); glm::vec2 canvasSize = qApp->getCanvasSize();
glm::vec2 mouseSize = 32.0f / canvasSize;
auto mouseTopLeft = topLeft * mouseSize;
auto mouseBottomRight = bottomRight * mouseSize;
vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY());
mousePosition /= canvasSize;
mousePosition *= 2.0f;
mousePosition -= 1.0f;
mousePosition.y *= -1.0f;
// Get the mouse coordinates and convert to NDC [-1, 1] glEnable(GL_TEXTURE_2D);
vec2 mousePosition = vec2(qApp->getMouseX(), qApp->getMouseY()); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
mousePosition /= canvasSize; glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
mousePosition *= 2.0f; glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
mousePosition -= 1.0f; DependencyManager::get<GeometryCache>()->renderQuad(
mousePosition.y *= -1.0f; mouseTopLeft + mousePosition, mouseBottomRight + mousePosition,
model.setTranslation(vec3(mousePosition, 0)); texCoordTopLeft, texCoordBottomRight,
glm::vec2 mouseSize = CURSOR_PIXEL_SIZE / canvasSize; reticleColor);
model.setScale(vec3(mouseSize, 1.0f)); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
batch.setModelTransform(model); glDisable(GL_TEXTURE_2D);
bindCursorTexture(batch); } glPopMatrix();
glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
DependencyManager::get<GeometryCache>()->renderUnitQuad(batch, vec4(1));
renderArgs->_context->render(batch);
}
static gpu::BufferPointer _hemiVertices;
static gpu::BufferPointer _hemiIndices;
static int _hemiIndexCount{ 0 };
glm::vec2 getPolarCoordinates(const PalmData& palm) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto avatarOrientation = myAvatar->getOrientation();
auto eyePos = myAvatar->getDefaultEyePosition();
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
// Direction of the tip relative to the eye
glm::vec3 tipDirection = tip - eyePos;
// orient into avatar space
tipDirection = glm::inverse(avatarOrientation) * tipDirection;
// Normalize for trig functions
tipDirection = glm::normalize(tipDirection);
// Convert to polar coordinates
glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));
return polar;
} }
// Draws the FBO texture for Oculus rift. // Draws the FBO texture for Oculus rift.
void ApplicationOverlay::displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera) { void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) {
if (_alpha == 0.0f) { if (_alpha == 0.0f) {
return; return;
} }
renderArgs->_context->syncCache(); glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_LIGHTING);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.01f);
gpu::Batch batch;
batch.setPipeline(getDrawPipeline());
batch._glDisable(GL_DEPTH_TEST);
batch._glDisable(GL_CULL_FACE);
batch._glBindTexture(GL_TEXTURE_2D, _framebufferObject->texture());
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
batch._glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
batch.setProjectionTransform(whichCamera.getProjection());
batch.setViewTransform(Transform());
//Update and draw the magnifiers
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const quat& avatarOrientation = myAvatar->getOrientation(); const glm::quat& orientation = myAvatar->getOrientation();
quat hmdOrientation = qApp->getCamera()->getHmdRotation(); // Always display the HMD overlay relative to the camera position but
vec3 hmdPosition = glm::inverse(avatarOrientation) * qApp->getCamera()->getHmdPosition(); // remove the HMD pose offset. This results in an overlay that sticks with you
mat4 overlayXfm = glm::mat4_cast(glm::inverse(hmdOrientation)) * glm::translate(mat4(), -hmdPosition); // even in third person mode, but isn't drawn at a fixed distance.
batch.setModelTransform(Transform(overlayXfm)); glm::vec3 position = whichCamera.getPosition();
drawSphereSection(batch); position -= qApp->getCamera()->getHmdPosition();
const float scale = myAvatar->getScale() * _oculusUIRadius;
// glm::vec3 eyeOffset = setEyeOffsetPosition;
glMatrixMode(GL_MODELVIEW);
glPushMatrix(); {
glTranslatef(position.x, position.y, position.z);
glm::mat4 rotation = glm::toMat4(orientation);
glMultMatrixf(&rotation[0][0]);
glScalef(scale, scale, scale);
for (int i = 0; i < NUMBER_OF_RETICLES; i++) {
bindCursorTexture(batch); if (_magActive[i]) {
auto geometryCache = DependencyManager::get<GeometryCache>(); _magSizeMult[i] += MAG_SPEED;
vec3 reticleScale = vec3(Cursor::Manager::instance().getScale() * reticleSize); if (_magSizeMult[i] > 1.0f) {
//Controller Pointers _magSizeMult[i] = 1.0f;
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { }
PalmData& palm = myAvatar->getHand()->getPalms()[i]; } else {
if (palm.isActive()) { _magSizeMult[i] -= MAG_SPEED;
glm::vec2 polar = getPolarCoordinates(palm); if (_magSizeMult[i] < 0.0f) {
// Convert to quaternion _magSizeMult[i] = 0.0f;
mat4 pointerXfm = glm::mat4_cast(quat(vec3(polar.y, -polar.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1)); }
mat4 reticleXfm = overlayXfm * pointerXfm; }
reticleXfm = glm::scale(reticleXfm, reticleScale);
batch.setModelTransform(reticleXfm); if (_magSizeMult[i] > 0.0f) {
// Render reticle at location //Render magnifier, but dont show border for mouse magnifier
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad); glm::vec2 projection = screenToOverlay(glm::vec2(_reticlePosition[MOUSE].x(),
_reticlePosition[MOUSE].y()));
with_each_texture(_overlays.getTexture(), 0, [&] {
renderMagnifier(projection, _magSizeMult[i], i != MOUSE);
});
}
} }
}
//Mouse Pointer glDepthMask(GL_FALSE);
if (_reticleActive[MOUSE]) { glDisable(GL_ALPHA_TEST);
glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),
_reticlePosition[MOUSE].y()));
mat4 pointerXfm = glm::mat4_cast(quat(vec3(-projection.y, projection.x, 0.0f))) * glm::translate(mat4(), vec3(0, 0, -1));
mat4 reticleXfm = overlayXfm * pointerXfm;
reticleXfm = glm::scale(reticleXfm, reticleScale);
batch.setModelTransform(reticleXfm);
geometryCache->renderUnitQuad(batch, glm::vec4(1), _reticleQuad);
}
renderArgs->_context->render(batch); static float textureFOV = 0.0f, textureAspectRatio = 1.0f;
if (textureFOV != _textureFov ||
textureAspectRatio != _textureAspectRatio) {
textureFOV = _textureFov;
textureAspectRatio = _textureAspectRatio;
_overlays.buildVBO(_textureFov, _textureAspectRatio, 80, 80);
}
with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
_overlays.render();
});
if (!Application::getInstance()->isMouseHidden()) {
renderPointersOculus();
}
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_2D);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_LIGHTING);
} glPopMatrix();
} }
// Draws the FBO texture for 3DTV.
void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) {
if (_alpha == 0.0f) {
return;
}
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
const glm::vec3& viewMatrixTranslation = qApp->getViewMatrixTranslation();
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Transform to world space
glm::quat rotation = whichCamera.getRotation();
glm::vec3 axis2 = glm::axis(rotation);
glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z);
glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z);
// Translate to the front of the camera
glm::vec3 pos = whichCamera.getPosition();
glm::quat rot = myAvatar->getOrientation();
glm::vec3 axis = glm::axis(rot);
glTranslatef(pos.x, pos.y, pos.z);
glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z);
glm::vec4 overlayColor = {1.0f, 1.0f, 1.0f, _alpha};
//Render
const GLfloat distance = 1.0f;
const GLfloat halfQuadHeight = distance * tan(fov);
const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio;
const GLfloat quadWidth = halfQuadWidth * 2.0f;
const GLfloat quadHeight = halfQuadHeight * 2.0f;
GLfloat x = -halfQuadWidth;
GLfloat y = -halfQuadHeight;
glDisable(GL_DEPTH_TEST);
with_each_texture(_overlays.getTexture(), _newUiTexture, [&] {
DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x, y + quadHeight, -distance),
glm::vec3(x + quadWidth, y + quadHeight, -distance),
glm::vec3(x + quadWidth, y, -distance),
glm::vec3(x, y, -distance),
glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f),
glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 0.0f),
overlayColor);
});
if (!_crosshairTexture) {
_crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() +
"images/sixense-reticle.png");
}
//draw the mouse pointer
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glm::vec2 canvasSize = qApp->getCanvasSize();
const float reticleSize = 40.0f / canvasSize.x * quadWidth;
x -= reticleSize / 2.0f;
y += reticleSize / 2.0f;
const float mouseX = (qApp->getMouseX() / (float)canvasSize.x) * quadWidth;
const float mouseY = (1.0 - (qApp->getMouseY() / (float)canvasSize.y)) * quadHeight;
glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f };
DependencyManager::get<GeometryCache>()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance),
glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance),
glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance),
glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance),
glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f),
glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f),
reticleColor, _reticleQuad);
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_LIGHTING);
}
void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const {
cursorPos *= qApp->getCanvasSize(); cursorPos *= qApp->getCanvasSize();
@ -421,6 +516,22 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi
direction = glm::normalize(intersectionWithUi - origin); direction = glm::normalize(intersectionWithUi - origin);
} }
glm::vec2 getPolarCoordinates(const PalmData& palm) {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
auto avatarOrientation = myAvatar->getOrientation();
auto eyePos = myAvatar->getDefaultEyePosition();
glm::vec3 tip = myAvatar->getLaserPointerTipPosition(&palm);
// Direction of the tip relative to the eye
glm::vec3 tipDirection = tip - eyePos;
// orient into avatar space
tipDirection = glm::inverse(avatarOrientation) * tipDirection;
// Normalize for trig functions
tipDirection = glm::normalize(tipDirection);
// Convert to polar coordinates
glm::vec2 polar(glm::atan(tipDirection.x, -tipDirection.z), glm::asin(tipDirection.y));
return polar;
}
//Caculate the click location using one of the sixense controllers. Scale is not applied //Caculate the click location using one of the sixense controllers. Scale is not applied
QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const {
QPoint rv; QPoint rv;
@ -471,9 +582,13 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position,
//Renders optional pointers //Renders optional pointers
void ApplicationOverlay::renderPointers() { void ApplicationOverlay::renderPointers() {
//glEnable(GL_TEXTURE_2D); //lazily load crosshair texture
//glEnable(GL_BLEND); if (_crosshairTexture == 0) {
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//glActiveTexture(GL_TEXTURE0); //glActiveTexture(GL_TEXTURE0);
//bindCursorTexture(); //bindCursorTexture();
@ -635,6 +750,43 @@ void ApplicationOverlay::renderControllerPointers() {
} }
} }
void ApplicationOverlay::renderPointersOculus() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture));
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW);
//Controller Pointers
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) {
PalmData& palm = myAvatar->getHand()->getPalms()[i];
if (palm.isActive()) {
glm::vec2 polar = getPolarCoordinates(palm);
// Convert to quaternion
glm::quat orientation = glm::quat(glm::vec3(polar.y, -polar.x, 0.0f));
// Render reticle at location
renderReticle(orientation, _alpha);
}
}
//Mouse Pointer
if (_reticleActive[MOUSE]) {
glm::vec2 projection = screenToSpherical(glm::vec2(_reticlePosition[MOUSE].x(),
_reticlePosition[MOUSE].y()));
glm::quat orientation(glm::vec3(-projection.y, projection.x, 0.0f));
renderReticle(orientation, _alpha);
}
glEnable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
}
//Renders a small magnification of the currently bound texture at the coordinates //Renders a small magnification of the currently bound texture at the coordinates
void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) { void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) {
if (!_magnifier) { if (!_magnifier) {
@ -915,109 +1067,119 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() {
} }
} }
ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() :
_vertices(0),
_indices(0),
_framebufferObject(NULL),
_vbo(0, 0) {
}
void ApplicationOverlay::buildHemiVertices( ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() {
const float fov, const float aspectRatio, const int slices, const int stacks) { cleanupVBO();
static float textureFOV = 0.0f, textureAspectRatio = 1.0f; if (_framebufferObject != NULL) {
if (textureFOV == fov && textureAspectRatio == aspectRatio) { delete _framebufferObject;
return;
} }
}
textureFOV = fov; void ApplicationOverlay::TexturedHemisphere::bind() {
textureAspectRatio = aspectRatio; _framebufferObject->bind();
}
auto geometryCache = DependencyManager::get<GeometryCache>();
_hemiVertices = gpu::BufferPointer(new gpu::Buffer());
_hemiIndices = gpu::BufferPointer(new gpu::Buffer());
void ApplicationOverlay::TexturedHemisphere::release() {
_framebufferObject->release();
}
void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov,
const float aspectRatio,
const int slices,
const int stacks) {
if (fov >= PI) { if (fov >= PI) {
qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";
} }
// Cleanup old VBO if necessary
cleanupVBO();
//UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
vec3 pos; // Compute number of vertices needed
vec2 uv; _vertices = slices * stacks;
// Compute vertices positions and texture UV coordinate // Compute vertices positions and texture UV coordinate
// Create and write to buffer TextureVertex* vertexData = new TextureVertex[_vertices];
TextureVertex* vertexPtr = &vertexData[0];
for (int i = 0; i < stacks; i++) { for (int i = 0; i < stacks; i++) {
uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f
// abs(theta) <= fov / 2.0f // abs(theta) <= fov / 2.0f
float pitch = -fov * (uv.y - 0.5f); float pitch = -fov * (stacksRatio - 0.5f);
for (int j = 0; j < slices; j++) { for (int j = 0; j < slices; j++) {
uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f
// abs(phi) <= fov * aspectRatio / 2.0f // abs(phi) <= fov * aspectRatio / 2.0f
float yaw = -fov * aspectRatio * (uv.x - 0.5f); float yaw = -fov * aspectRatio * (slicesRatio - 0.5f);
pos = getPoint(yaw, pitch);
static const vec4 color(1); vertexPtr->position = getPoint(yaw, pitch);
_hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos); vertexPtr->uv.x = slicesRatio;
_hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv); vertexPtr->uv.y = stacksRatio;
_hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color); vertexPtr++;
} }
} }
// Create and write to buffer
glGenBuffers(1, &_vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
static const int BYTES_PER_VERTEX = sizeof(TextureVertex);
glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
delete[] vertexData;
// Compute number of indices needed // Compute number of indices needed
static const int VERTEX_PER_TRANGLE = 3; static const int VERTEX_PER_TRANGLE = 3;
static const int TRIANGLE_PER_RECTANGLE = 2; static const int TRIANGLE_PER_RECTANGLE = 2;
int numberOfRectangles = (slices - 1) * (stacks - 1); int numberOfRectangles = (slices - 1) * (stacks - 1);
_hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
// Compute indices order // Compute indices order
std::vector<GLushort> indices; GLushort* indexData = new GLushort[_indices];
GLushort* indexPtr = indexData;
for (int i = 0; i < stacks - 1; i++) { for (int i = 0; i < stacks - 1; i++) {
for (int j = 0; j < slices - 1; j++) { for (int j = 0; j < slices - 1; j++) {
GLushort bottomLeftIndex = i * slices + j; GLushort bottomLeftIndex = i * slices + j;
GLushort bottomRightIndex = bottomLeftIndex + 1; GLushort bottomRightIndex = bottomLeftIndex + 1;
GLushort topLeftIndex = bottomLeftIndex + slices; GLushort topLeftIndex = bottomLeftIndex + slices;
GLushort topRightIndex = topLeftIndex + 1; GLushort topRightIndex = topLeftIndex + 1;
// FIXME make a z-order curve for better vertex cache locality
indices.push_back(topLeftIndex);
indices.push_back(bottomLeftIndex);
indices.push_back(topRightIndex);
indices.push_back(topRightIndex); *(indexPtr++) = topLeftIndex;
indices.push_back(bottomLeftIndex); *(indexPtr++) = bottomLeftIndex;
indices.push_back(bottomRightIndex); *(indexPtr++) = topRightIndex;
*(indexPtr++) = topRightIndex;
*(indexPtr++) = bottomLeftIndex;
*(indexPtr++) = bottomRightIndex;
} }
} }
_hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]); // Create and write to buffer
glGenBuffers(1, &_vbo.second);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
static const int BYTES_PER_INDEX = sizeof(GLushort);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
delete[] indexData;
} }
void ApplicationOverlay::TexturedHemisphere::cleanupVBO() {
void ApplicationOverlay::drawSphereSection(gpu::Batch& batch) { if (_vbo.first != 0) {
buildHemiVertices(_textureFov, _textureAspectRatio, 80, 80); glDeleteBuffers(1, &_vbo.first);
static const int VERTEX_DATA_SLOT = 0; _vbo.first = 0;
static const int TEXTURE_DATA_SLOT = 1; }
static const int COLOR_DATA_SLOT = 2; if (_vbo.second != 0) {
gpu::Stream::FormatPointer streamFormat(new gpu::Stream::Format()); // 1 for everyone glDeleteBuffers(1, &_vbo.second);
streamFormat->setAttribute(gpu::Stream::POSITION, VERTEX_DATA_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); _vbo.second = 0;
streamFormat->setAttribute(gpu::Stream::TEXCOORD, TEXTURE_DATA_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); }
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_DATA_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA));
batch.setInputFormat(streamFormat);
static const int VERTEX_STRIDE = sizeof(vec3) + sizeof(vec2) + sizeof(vec4);
gpu::BufferView posView(_hemiVertices, 0, _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
gpu::BufferView uvView(_hemiVertices, sizeof(vec3), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::TEXCOORD)._element);
gpu::BufferView colView(_hemiVertices, sizeof(vec3) + sizeof(vec2), _hemiVertices->getSize(), VERTEX_STRIDE, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
batch.setInputBuffer(VERTEX_DATA_SLOT, posView);
batch.setInputBuffer(TEXTURE_DATA_SLOT, uvView);
batch.setInputBuffer(COLOR_DATA_SLOT, colView);
batch.setIndexBuffer(gpu::UINT16, _hemiIndices, 0);
batch.drawIndexed(gpu::TRIANGLES, _hemiIndexCount);
} }
void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() {
GLuint ApplicationOverlay::getOverlayTexture() {
return _framebufferObject->texture();
}
void ApplicationOverlay::buildFramebufferObject() {
auto canvasSize = qApp->getCanvasSize(); auto canvasSize = qApp->getCanvasSize();
QSize fboSize = QSize(canvasSize.x, canvasSize.y); QSize fboSize = QSize(canvasSize.x, canvasSize.y);
if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) { if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) {
// Already built // Already build
return; return;
} }
@ -1026,7 +1188,7 @@ void ApplicationOverlay::buildFramebufferObject() {
} }
_framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth);
glBindTexture(GL_TEXTURE_2D, getOverlayTexture()); glBindTexture(GL_TEXTURE_2D, getTexture());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
@ -1036,6 +1198,38 @@ void ApplicationOverlay::buildFramebufferObject() {
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
} }
//Renders a hemisphere with texture coordinates.
void ApplicationOverlay::TexturedHemisphere::render() {
if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) {
qDebug() << "TexturedHemisphere::render(): Incorrect initialisation";
return;
}
glBindBuffer(GL_ARRAY_BUFFER, _vbo.first);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
static const int STRIDE = sizeof(TextureVertex);
static const void* VERTEX_POINTER = 0;
static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3);
glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER);
glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER);
glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
GLuint ApplicationOverlay::TexturedHemisphere::getTexture() {
return _framebufferObject->texture();
}
glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) {
glm::vec2 result; glm::vec2 result;
// Compute yaw // Compute yaw

View file

@ -33,9 +33,9 @@ public:
~ApplicationOverlay(); ~ApplicationOverlay();
void renderOverlay(RenderArgs* renderArgs); void renderOverlay(RenderArgs* renderArgs);
void displayOverlayTexture(RenderArgs* renderArgs); void displayOverlayTexture();
void displayOverlayTextureStereo(RenderArgs* renderArgs, Camera& whichCamera, float aspectRatio, float fov); void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov);
void displayOverlayTextureHmd(RenderArgs* renderArgs, Camera& whichCamera); void displayOverlayTextureHmd(Camera& whichCamera);
QPoint getPalmClickLocation(const PalmData *palm) const; QPoint getPalmClickLocation(const PalmData *palm) const;
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
@ -59,7 +59,6 @@ public:
glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const; glm::vec2 screenToOverlay(const glm::vec2 & screenPos) const;
glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const; glm::vec2 overlayToScreen(const glm::vec2 & overlayPos) const;
void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const; void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const;
GLuint getOverlayTexture();
static glm::vec2 directionToSpherical(const glm::vec3 & direction); static glm::vec2 directionToSpherical(const glm::vec3 & direction);
static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos); static glm::vec3 sphericalToDirection(const glm::vec2 & sphericalPos);
@ -67,12 +66,38 @@ public:
static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos); static glm::vec2 sphericalToScreen(const glm::vec2 & sphericalPos);
private: private:
void buildHemiVertices(const float fov, const float aspectRatio, const int slices, const int stacks); // Interleaved vertex data
void drawSphereSection(gpu::Batch& batch); struct TextureVertex {
float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; glm::vec3 position;
QOpenGLFramebufferObject* _framebufferObject; glm::vec2 uv;
};
void renderPointers(); typedef QPair<GLuint, GLuint> VerticesIndices;
class TexturedHemisphere {
public:
TexturedHemisphere();
~TexturedHemisphere();
void bind();
void release();
GLuint getTexture();
void buildFramebufferObject();
void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks);
void render();
private:
void cleanupVBO();
GLuint _vertices;
GLuint _indices;
QOpenGLFramebufferObject* _framebufferObject;
VerticesIndices _vbo;
};
float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE;
void renderReticle(glm::quat orientation, float alpha);
void renderPointers();;
void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder); void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder);
void renderControllerPointers(); void renderControllerPointers();
@ -84,12 +109,10 @@ private:
void renderDomainConnectionStatusBorder(); void renderDomainConnectionStatusBorder();
void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0);
void buildFramebufferObject(); TexturedHemisphere _overlays;
float _textureFov; float _textureFov;
float _textureAspectRatio; float _textureAspectRatio;
int _hemiVerticesID{ GeometryCache::UNKNOWN_ID };
enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES };
bool _reticleActive[NUMBER_OF_RETICLES]; bool _reticleActive[NUMBER_OF_RETICLES];
@ -103,6 +126,8 @@ private:
float _oculusUIRadius; float _oculusUIRadius;
float _trailingAudioLoudness; float _trailingAudioLoudness;
gpu::TexturePointer _crosshairTexture;
QMap<uint16_t, gpu::TexturePointer> _cursors; QMap<uint16_t, gpu::TexturePointer> _cursors;
@ -124,10 +149,6 @@ private:
glm::vec3 _previousMagnifierTopLeft; glm::vec3 _previousMagnifierTopLeft;
glm::vec3 _previousMagnifierTopRight; glm::vec3 _previousMagnifierTopRight;
gpu::PipelinePointer _standardDrawPipeline;
gpu::PipelinePointer getDrawPipeline();
}; };
#endif // hifi_ApplicationOverlay_h #endif // hifi_ApplicationOverlay_h

View file

@ -133,11 +133,11 @@ void GLBackend::updateTransform() {
} }
if (_transform._invalidModel || _transform._invalidView) { if (_transform._invalidModel || _transform._invalidView) {
if (_transform._lastMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW);
_transform._lastMode = GL_MODELVIEW;
}
if (!_transform._model.isIdentity()) { if (!_transform._model.isIdentity()) {
if (_transform._lastMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW);
_transform._lastMode = GL_MODELVIEW;
}
Transform::Mat4 modelView; Transform::Mat4 modelView;
if (!_transform._view.isIdentity()) { if (!_transform._view.isIdentity()) {
Transform mvx; Transform mvx;
@ -147,12 +147,19 @@ void GLBackend::updateTransform() {
_transform._model.getMatrix(modelView); _transform._model.getMatrix(modelView);
} }
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
} else if (!_transform._view.isIdentity()) {
Transform::Mat4 modelView;
_transform._view.getInverseMatrix(modelView);
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
} else { } else {
glLoadIdentity(); if (!_transform._view.isIdentity()) {
if (_transform._lastMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW);
_transform._lastMode = GL_MODELVIEW;
}
Transform::Mat4 modelView;
_transform._view.getInverseMatrix(modelView);
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
} else {
// TODO: eventually do something about the matrix when neither view nor model is specified?
// glLoadIdentity();
}
} }
(void) CHECK_GL_ERROR(); (void) CHECK_GL_ERROR();
} }

View file

@ -1179,21 +1179,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
batch.draw(gpu::QUADS, 4, 0); batch.draw(gpu::QUADS, 4, 0);
} }
void GeometryCache::renderUnitQuad(const glm::vec4& color, int id) {
gpu::Batch batch;
renderUnitQuad(batch, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {
static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
static const glm::vec2 texCoordTopLeft(0.0f, 1.0f);
static const glm::vec2 texCoordBottomRight(1.0f, 0.0f);
renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color, id);
}
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id) { const glm::vec4& color, int id) {

View file

@ -155,9 +155,6 @@ public:
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID); void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderUnitQuad(const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID) void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); } { renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID) void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)

View file

@ -1,24 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
// standardDrawTexture.frag
// fragment shader
//
// Created by Sam Gateau on 6/10/15.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the texture
uniform sampler2D colorMap;
varying vec2 varTexcoord;
varying vec4 varColor;
void main(void) {
vec4 color = texture2D(colorMap, varTexcoord);
gl_FragColor = color * varColor;
}

View file

@ -1,33 +0,0 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// standardTransformPNTC.slv
// vertex shader
//
// Created by Sam Gateau on 6/10/2015.
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
varying vec3 varNormal;
varying vec2 varTexcoord;
varying vec4 varColor;
void main(void) {
varTexcoord = gl_MultiTexCoord0.xy;
varColor = gl_Color;
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, gl_Vertex, gl_Position)$>
<$transformModelToEyeDir(cam, obj, gl_Normal, varNormal)$>
varNormal = normalize(varNormal);
}