diff --git a/interface/resources/shaders/hmd_ui_glow.frag b/interface/resources/shaders/hmd_ui_glow.frag index 9270842092..5dda76e89d 100644 --- a/interface/resources/shaders/hmd_ui_glow.frag +++ b/interface/resources/shaders/hmd_ui_glow.frag @@ -13,6 +13,9 @@ struct OverlayData { vec4 glowPoints; vec4 glowColors[2]; vec4 resolutionRadiusAlpha; + + vec4 extraGlowColor; + vec2 extraGlowPoint; }; layout(std140) uniform overlayBuffer { @@ -25,6 +28,9 @@ float alpha = overlay.resolutionRadiusAlpha.w; vec4 glowPoints = overlay.glowPoints; vec4 glowColors[2] = overlay.glowColors; +vec2 extraGlowPoint = overlay.extraGlowPoint; +vec4 extraGlowColor = overlay.extraGlowColor; + in vec3 vPosition; in vec2 vTexCoord; @@ -48,11 +54,16 @@ void main() { float glowIntensity = 0.0; float dist1 = distance(vTexCoord * aspect, glowPoints.xy * aspect); float dist2 = distance(vTexCoord * aspect, glowPoints.zw * aspect); - float dist = min(dist1, dist2); + float dist3 = distance(vTexCoord * aspect, extraGlowPoint * aspect); + float distX = min(dist1, dist2); + float dist = min(distX, dist3); vec3 glowColor = glowColors[0].rgb; if (dist2 < dist1) { glowColor = glowColors[1].rgb; } + if (dist3 < dist2) { + glowColor = extraGlowColor.rgb; + } if (dist <= radius) { glowIntensity = 1.0 - (dist / radius); diff --git a/interface/resources/shaders/hmd_ui_glow.vert b/interface/resources/shaders/hmd_ui_glow.vert index 54eb062590..71089d8608 100644 --- a/interface/resources/shaders/hmd_ui_glow.vert +++ b/interface/resources/shaders/hmd_ui_glow.vert @@ -11,6 +11,9 @@ struct OverlayData { vec4 glowPoints; vec4 glowColors[2]; vec4 resolutionRadiusAlpha; + + vec4 extraGlowColor; + vec2 extraGlowPoint; }; layout(std140) uniform overlayBuffer { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index 9d91b5b5e6..f417ae6a9b 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -341,6 +341,11 @@ void HmdDisplayPlugin::updateFrameData() { if (_currentFrame) { auto batchPose = _currentFrame->pose; + + // HACK o RAMA + //_handPoses[0] = _currentFrame->pose; + //_handPoses[1] = _currentFrame->pose; + auto currentPose = _currentPresentFrameInfo.presentPose; auto correction = glm::inverse(batchPose) * currentPose; getGLBackend()->setCameraCorrection(correction); @@ -350,11 +355,16 @@ void HmdDisplayPlugin::updateFrameData() { _presentHandLasers = _handLasers; _presentHandPoses = _handPoses; _presentUiModelTransform = _uiModelTransform; + + _presentExtraLaser = _extraLaser; + _presentExtraLaserPose = _extraLaserPose; + }); auto compositorHelper = DependencyManager::get(); glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix(); std::array handGlowPoints{ { vec2(-1), vec2(-1) } }; + vec2 extraGlowPoint(-1); // compute the glow point interesections for (size_t i = 0; i < NUMBER_OF_HANDS; ++i) { @@ -419,6 +429,55 @@ void HmdDisplayPlugin::updateFrameData() { handGlowPoints[i] = yawPitch; } + // compute the glow point interesections + if (_presentExtraLaser.valid()) { + const auto& handLaser = _presentExtraLaser; + + const vec3& laserDirection = handLaser.direction; + mat4 model = _presentExtraLaserPose; + vec3 castStart = vec3(model[3]); + vec3 castDirection = glm::quat_cast(model) * laserDirection; + if (glm::abs(glm::length2(castDirection) - 1.0f) > EPSILON) { + castDirection = glm::normalize(castDirection); + castDirection = glm::inverse(_presentUiModelTransform.getRotation()) * castDirection; + } + + // FIXME - no offset + vec3 grabPointOffset {0}; + castStart += glm::quat_cast(model) * grabPointOffset; + + // FIXME fetch the actual UI radius from... somewhere? + float uiRadius = 1.0f; + + // Find the intersection of the laser with he UI and use it to scale the model matrix + float distance; + if (glm::intersectRaySphere(castStart, castDirection, + _presentUiModelTransform.getTranslation(), uiRadius * uiRadius, distance)) { + + _presentExtraLaserPoints.first = castStart; + _presentExtraLaserPoints.second = _presentExtraLaserPoints.first + (castDirection * distance); + + vec3 intersectionPosition = castStart + (castDirection * distance) - _presentUiModelTransform.getTranslation(); + intersectionPosition = glm::inverse(_presentUiModelTransform.getRotation()) * intersectionPosition; + + // Take the interesection normal and convert it to a texture coordinate + vec2 yawPitch; + { + vec2 xdir = glm::normalize(vec2(intersectionPosition.x, -intersectionPosition.z)); + yawPitch.x = glm::atan(xdir.x, xdir.y); + yawPitch.y = (acosf(intersectionPosition.y) * -1.0f) + (float)M_PI_2; + } + vec2 halfFov = CompositorHelper::VIRTUAL_UI_TARGET_FOV / 2.0f; + + // Are we out of range + if (!glm::any(glm::greaterThan(glm::abs(yawPitch), halfFov))) { + yawPitch /= CompositorHelper::VIRTUAL_UI_TARGET_FOV; + yawPitch += 0.5f; + extraGlowPoint = yawPitch; + } + } + } + for_each_eye([&](Eye eye) { auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat; @@ -432,6 +491,8 @@ void HmdDisplayPlugin::updateFrameData() { uniforms.glowPoints = vec4(handGlowPoints[0], handGlowPoints[1]); uniforms.glowColors[0] = _presentHandLasers[0].color; uniforms.glowColors[1] = _presentHandLasers[1].color; + uniforms.extraGlowPoint = extraGlowPoint; + uniforms.extraGlowColor = _presentExtraLaser.color; } } @@ -607,6 +668,20 @@ bool HmdDisplayPlugin::setHandLaser(uint32_t hands, HandLaserMode mode, const ve return true; } +bool HmdDisplayPlugin::setExtraLaser(mat4 extraLaserPose, HandLaserMode mode, const vec4& color, const vec3& direction) { + HandLaserInfo info; + info.mode = mode; + info.color = color; + info.direction = direction; + withNonPresentThreadLock([&] { + _extraLaser = info; + _extraLaserPose = extraLaserPose; + }); + // FIXME defer to a child class plugin to determine if hand lasers are actually + // available based on the presence or absence of hand controllers + return true; +} + void HmdDisplayPlugin::compositeExtra() { // If neither hand laser is activated, exit if (!_presentHandLasers[0].valid() && !_presentHandLasers[1].valid()) { @@ -628,14 +703,23 @@ void HmdDisplayPlugin::compositeExtra() { return; } const auto& laser = _presentHandLasers[index]; + + const float glowIntensity = 1.0f; + const float glowWidth = 0.05f; if (laser.valid()) { const auto& points = _presentHandLaserPoints[index]; - geometryCache->renderGlowLine(batch, points.first, points.second, laser.color); + geometryCache->renderGlowLine(batch, points.first, points.second, laser.color, + glowIntensity, glowWidth, _glowLineID); } }); }); } +HmdDisplayPlugin::HmdDisplayPlugin() { + _glowLineID = DependencyManager::get()->allocateID(); +} + HmdDisplayPlugin::~HmdDisplayPlugin() { qDebug() << "Destroying HmdDisplayPlugin"; + DependencyManager::get()->releaseID(_glowLineID); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 505c200e3e..aac82f8495 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -23,6 +23,7 @@ class HmdDisplayPlugin : public OpenGLDisplayPlugin { using Parent = OpenGLDisplayPlugin; public: + HmdDisplayPlugin(); ~HmdDisplayPlugin(); bool isHmd() const override final { return true; } float getIPD() const override final { return _ipd; } @@ -38,6 +39,7 @@ public: virtual glm::mat4 getHeadPose() const override; bool setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) override; + bool setExtraLaser(mat4 extraLaserPose, HandLaserMode mode, const vec4& color, const vec3& direction) override; bool wantVsync() const override { return false; @@ -80,6 +82,12 @@ protected: std::array _presentHandPoses; std::array, 2> _presentHandLaserPoints; + HandLaserInfo _extraLaser; + HandLaserInfo _presentExtraLaser; + mat4 _extraLaserPose; + mat4 _presentExtraLaserPose; + std::pair _presentExtraLaserPoints; + std::array _eyeOffsets; std::array _eyeProjections; std::array _eyeInverseProjections; @@ -130,6 +138,9 @@ private: vec2 resolution { CompositorHelper::VIRTUAL_SCREEN_SIZE }; float radius { 0.005f }; float alpha { 1.0f }; + + vec4 extraGlowColor; + vec2 extraGlowPoint { -1 }; } uniforms; struct Vertex { @@ -145,4 +156,6 @@ private: void updatePipeline(); void render(HmdDisplayPlugin& plugin); } _overlayRenderer; + + int _glowLineID { -1 }; }; diff --git a/libraries/display-plugins/src/hmd_ui_glow.slf b/libraries/display-plugins/src/hmd_ui_glow.slf deleted file mode 100644 index 9270842092..0000000000 --- a/libraries/display-plugins/src/hmd_ui_glow.slf +++ /dev/null @@ -1,75 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 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 -// - -uniform sampler2D sampler; - -struct OverlayData { - mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -vec2 resolution = overlay.resolutionRadiusAlpha.xy; -float radius = overlay.resolutionRadiusAlpha.z; -float alpha = overlay.resolutionRadiusAlpha.w; -vec4 glowPoints = overlay.glowPoints; -vec4 glowColors[2] = overlay.glowColors; - -in vec3 vPosition; -in vec2 vTexCoord; - -out vec4 FragColor; - -float easeInOutCubic(float f) { - const float d = 1.0; - const float b = 0.0; - const float c = 1.0; - float t = f; - if ((t /= d / 2.0) < 1.0) return c / 2.0 * t * t * t + b; - return c / 2.0 * ((t -= 2.0) * t * t + 2.0) + b; -} - -void main() { - FragColor = texture(sampler, vTexCoord); - - vec2 aspect = resolution; - aspect /= resolution.x; - - float glowIntensity = 0.0; - float dist1 = distance(vTexCoord * aspect, glowPoints.xy * aspect); - float dist2 = distance(vTexCoord * aspect, glowPoints.zw * aspect); - float dist = min(dist1, dist2); - vec3 glowColor = glowColors[0].rgb; - if (dist2 < dist1) { - glowColor = glowColors[1].rgb; - } - - if (dist <= radius) { - glowIntensity = 1.0 - (dist / radius); - glowColor.rgb = pow(glowColor, vec3(1.0 - glowIntensity)); - glowIntensity = easeInOutCubic(glowIntensity); - glowIntensity = pow(glowIntensity, 0.5); - } - - if (alpha <= 0.0) { - if (glowIntensity <= 0.0) { - discard; - } - - FragColor = vec4(glowColor, glowIntensity); - return; - } - - FragColor.rgb = mix(FragColor.rgb, glowColor.rgb, glowIntensity); - FragColor.a *= alpha; -} \ No newline at end of file diff --git a/libraries/display-plugins/src/hmd_ui_glow.slv b/libraries/display-plugins/src/hmd_ui_glow.slv deleted file mode 100644 index 54eb062590..0000000000 --- a/libraries/display-plugins/src/hmd_ui_glow.slv +++ /dev/null @@ -1,32 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 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 -// - -struct OverlayData { - mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -mat4 mvp = overlay.mvp; - -layout(location = 0) in vec3 Position; -layout(location = 3) in vec2 TexCoord; - -out vec3 vPosition; -out vec2 vTexCoord; - -void main() { - gl_Position = mvp * vec4(Position, 1); - vTexCoord = TexCoord; - vPosition = Position; -} diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index eac08716a1..e97d4bff9a 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -115,6 +115,10 @@ public: return false; } + virtual bool setExtraLaser(mat4 extraLaserPose, HandLaserMode mode, const vec4& color, const vec3& direction) { + return false; + } + virtual bool suppressKeyboard() { return false; } virtual void unsuppressKeyboard() {}; virtual bool isKeyboardVisible() { return false; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 1ab300da02..77b729b7db 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1591,6 +1591,7 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm } +// FIXME -- there's a memory leak of GPU buffers in this method void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec4& color, float glowIntensity, float glowWidth, int id) {