Merge branch 'master' of github.com:highfidelity/hifi into fix-release-grab

This commit is contained in:
druiz17 2017-10-11 09:13:01 -07:00
commit 67944c40a1
50 changed files with 361 additions and 379 deletions

View file

@ -88,7 +88,7 @@ FocusScope {
return; return;
} }
var oldRecommendedRect = recommendedRect; var oldRecommendedRect = recommendedRect;
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
newRecommendedRectJS.width, newRecommendedRectJS.width,
newRecommendedRectJS.height); newRecommendedRectJS.height);
@ -271,7 +271,7 @@ FocusScope {
var oldRecommendedRect = recommendedRect; var oldRecommendedRect = recommendedRect;
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height }; var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
var newRecommendedRect = Controller.getRecommendedOverlayRect(); var newRecommendedRect = Controller.getRecommendedHUDRect();
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height }; var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
var windows = d.getTopLevelWindows(); var windows = d.getTopLevelWindows();
for (var i = 0; i < windows.length; ++i) { for (var i = 0; i < windows.length; ++i) {
@ -410,7 +410,7 @@ FocusScope {
return; return;
} }
var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedOverlayRect(); var newRecommendedRectJS = (typeof Controller === "undefined") ? Qt.rect(0,0,0,0) : Controller.getRecommendedHUDRect();
var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y, var newRecommendedRect = Qt.rect(newRecommendedRectJS.x, newRecommendedRectJS.y,
newRecommendedRectJS.width, newRecommendedRectJS.width,
newRecommendedRectJS.height); newRecommendedRectJS.height);
@ -442,7 +442,7 @@ FocusScope {
var oldRecommendedRect = recommendedRect; var oldRecommendedRect = recommendedRect;
var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height }; var oldRecommendedDimmensions = { x: oldRecommendedRect.width, y: oldRecommendedRect.height };
var newRecommendedRect = Controller.getRecommendedOverlayRect(); var newRecommendedRect = Controller.getRecommendedHUDRect();
var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height }; var newRecommendedDimmensions = { x: newRecommendedRect.width, y: newRecommendedRect.height };
repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions); repositionWindow(targetWindow, false, oldRecommendedRect, oldRecommendedDimmensions, newRecommendedRect, newRecommendedDimmensions);
} }
@ -459,7 +459,7 @@ FocusScope {
return; return;
} }
var recommended = Controller.getRecommendedOverlayRect(); var recommended = Controller.getRecommendedHUDRect();
var maxX = recommended.x + recommended.width; var maxX = recommended.x + recommended.width;
var maxY = recommended.y + recommended.height; var maxY = recommended.y + recommended.height;
var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y); var newPosition = Qt.vector2d(targetWindow.x, targetWindow.y);

View file

@ -168,7 +168,7 @@ Item {
PropertyChanges { PropertyChanges {
target: text target: text
color: "#ffffff" color: captionColorOverride !== "" ? captionColorOverride: "#ffffff"
text: tabletButton.hoverText text: tabletButton.hoverText
} }
@ -194,7 +194,7 @@ Item {
PropertyChanges { PropertyChanges {
target: text target: text
color: "#333333" color: captionColorOverride !== "" ? captionColorOverride: "#333333"
text: tabletButton.activeText text: tabletButton.activeText
} }
@ -225,7 +225,7 @@ Item {
PropertyChanges { PropertyChanges {
target: text target: text
color: "#333333" color: captionColorOverride !== "" ? captionColorOverride: "#333333"
text: tabletButton.activeHoverText text: tabletButton.activeHoverText
} }

View file

@ -1,30 +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;
float alpha;
};
layout(std140) uniform overlayBuffer {
OverlayData overlay;
};
in vec2 vTexCoord;
out vec4 FragColor;
void main() {
FragColor = texture(sampler, vTexCoord);
FragColor.a *= overlay.alpha;
if (FragColor.a <= 0.0) {
discard;
}
}

View file

@ -1,28 +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;
float alpha;
};
layout(std140) uniform overlayBuffer {
OverlayData overlay;
};
mat4 mvp = overlay.mvp;
layout(location = 0) in vec3 Position;
layout(location = 3) in vec2 TexCoord;
out vec2 vTexCoord;
void main() {
gl_Position = mvp * vec4(Position, 1);
vTexCoord = TexCoord;
}

View file

@ -5051,6 +5051,7 @@ void Application::update(float deltaTime) {
float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale(); float sensorToWorldScale = getMyAvatar()->getSensorToWorldScale();
appRenderArgs._sensorToWorldScale = sensorToWorldScale; appRenderArgs._sensorToWorldScale = sensorToWorldScale;
appRenderArgs._sensorToWorld = getMyAvatar()->getSensorToWorldMatrix();
{ {
PROFILE_RANGE(render, "/buildFrustrumAndArgs"); PROFILE_RANGE(render, "/buildFrustrumAndArgs");
{ {
@ -5092,6 +5093,7 @@ void Application::update(float deltaTime) {
ipdScale *= sensorToWorldScale; ipdScale *= sensorToWorldScale;
auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection(); auto baseProjection = appRenderArgs._renderArgs.getViewFrustum().getProjection();
if (getActiveDisplayPlugin()->isStereo()) { if (getActiveDisplayPlugin()->isStereo()) {
// Stereo modes will typically have a larger projection matrix overall, // Stereo modes will typically have a larger projection matrix overall,
// so we ask for the 'mono' projection matrix, which for stereo and HMD // so we ask for the 'mono' projection matrix, which for stereo and HMD
@ -7022,11 +7024,11 @@ glm::uvec2 Application::getUiSize() const {
return result; return result;
} }
QRect Application::getRecommendedOverlayRect() const { QRect Application::getRecommendedHUDRect() const {
auto uiSize = getUiSize(); auto uiSize = getUiSize();
QRect result(0, 0, uiSize.x, uiSize.y); QRect result(0, 0, uiSize.x, uiSize.y);
if (_displayPlugin) { if (_displayPlugin) {
result = getActiveDisplayPlugin()->getRecommendedOverlayRect(); result = getActiveDisplayPlugin()->getRecommendedHUDRect();
} }
return result; return result;
} }

View file

@ -160,7 +160,7 @@ public:
QRect getRenderingGeometry() const; QRect getRenderingGeometry() const;
glm::uvec2 getUiSize() const; glm::uvec2 getUiSize() const;
QRect getRecommendedOverlayRect() const; QRect getRecommendedHUDRect() const;
QSize getDeviceSize() const; QSize getDeviceSize() const;
bool hasFocus() const; bool hasFocus() const;

View file

@ -126,28 +126,18 @@ void Application::paintGL() {
renderArgs._context->setStereoViews(stereoEyeOffsets); renderArgs._context->setStereoViews(stereoEyeOffsets);
} }
renderArgs._hudOperator = displayPlugin->getHUDOperator();
renderArgs._hudTexture = _applicationOverlay.getOverlayTexture();
renderArgs._blitFramebuffer = finalFramebuffer; renderArgs._blitFramebuffer = finalFramebuffer;
runRenderFrame(&renderArgs); runRenderFrame(&renderArgs);
} }
gpu::Batch postCompositeBatch;
{
PROFILE_RANGE(render, "/postComposite");
PerformanceTimer perfTimer("postComposite");
renderArgs._batch = &postCompositeBatch;
renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()));
renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView());
_overlays.render3DHUDOverlays(&renderArgs);
}
auto frame = _gpuContext->endFrame(); auto frame = _gpuContext->endFrame();
frame->frameIndex = _renderFrameCount; frame->frameIndex = _renderFrameCount;
frame->framebuffer = finalFramebuffer; frame->framebuffer = finalFramebuffer;
frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) { frame->framebufferRecycler = [](const gpu::FramebufferPointer& framebuffer) {
DependencyManager::get<FramebufferCache>()->releaseFramebuffer(framebuffer); DependencyManager::get<FramebufferCache>()->releaseFramebuffer(framebuffer);
}; };
frame->overlay = _applicationOverlay.getOverlayTexture();
frame->postCompositeBatch = postCompositeBatch;
// deliver final scene rendering commands to the display plugin // deliver final scene rendering commands to the display plugin
{ {
PROFILE_RANGE(render, "/pluginOutput"); PROFILE_RANGE(render, "/pluginOutput");

View file

@ -91,8 +91,8 @@ glm::vec2 ControllerScriptingInterface::getViewportDimensions() const {
return qApp->getUiSize(); return qApp->getUiSize();
} }
QVariant ControllerScriptingInterface::getRecommendedOverlayRect() const { QVariant ControllerScriptingInterface::getRecommendedHUDRect() const {
auto rect = qApp->getRecommendedOverlayRect(); auto rect = qApp->getRecommendedHUDRect();
return qRectToVariant(rect); return qRectToVariant(rect);
} }

View file

@ -66,7 +66,7 @@ public slots:
virtual void releaseEntityClickEvents(); virtual void releaseEntityClickEvents();
virtual glm::vec2 getViewportDimensions() const; virtual glm::vec2 getViewportDimensions() const;
virtual QVariant getRecommendedOverlayRect() const; virtual QVariant getRecommendedHUDRect() const;
signals: signals:
void keyPressEvent(const KeyEvent& event); void keyPressEvent(const KeyEvent& event);

View file

@ -29,7 +29,7 @@ int DesktopScriptingInterface::getHeight() {
return size.height(); return size.height();
} }
void DesktopScriptingInterface::setOverlayAlpha(float alpha) { void DesktopScriptingInterface::setHUDAlpha(float alpha) {
qApp->getApplicationCompositor().setAlpha(alpha); qApp->getApplicationCompositor().setAlpha(alpha);
} }

View file

@ -22,7 +22,7 @@ class DesktopScriptingInterface : public QObject, public Dependency {
Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus Q_PROPERTY(int height READ getHeight) // Physical height of screen(s) including task bars and system menus
public: public:
Q_INVOKABLE void setOverlayAlpha(float alpha); Q_INVOKABLE void setHUDAlpha(float alpha);
Q_INVOKABLE void show(const QString& path, const QString& title); Q_INVOKABLE void show(const QString& path, const QString& title);
int getWidth(); int getWidth();

View file

@ -26,7 +26,8 @@ Base3DOverlay::Base3DOverlay() :
_isSolid(DEFAULT_IS_SOLID), _isSolid(DEFAULT_IS_SOLID),
_isDashedLine(DEFAULT_IS_DASHED_LINE), _isDashedLine(DEFAULT_IS_DASHED_LINE),
_ignoreRayIntersection(false), _ignoreRayIntersection(false),
_drawInFront(false) _drawInFront(false),
_drawHUDLayer(false)
{ {
} }
@ -38,6 +39,7 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
_isDashedLine(base3DOverlay->_isDashedLine), _isDashedLine(base3DOverlay->_isDashedLine),
_ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection), _ignoreRayIntersection(base3DOverlay->_ignoreRayIntersection),
_drawInFront(base3DOverlay->_drawInFront), _drawInFront(base3DOverlay->_drawInFront),
_drawHUDLayer(base3DOverlay->_drawHUDLayer),
_isGrabbable(base3DOverlay->_isGrabbable) _isGrabbable(base3DOverlay->_isGrabbable)
{ {
setTransform(base3DOverlay->getTransform()); setTransform(base3DOverlay->getTransform());
@ -125,13 +127,19 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
bool needRenderItemUpdate = false; bool needRenderItemUpdate = false;
auto drawInFront = properties["drawInFront"]; auto drawInFront = properties["drawInFront"];
if (drawInFront.isValid()) { if (drawInFront.isValid()) {
bool value = drawInFront.toBool(); bool value = drawInFront.toBool();
setDrawInFront(value); setDrawInFront(value);
needRenderItemUpdate = true; needRenderItemUpdate = true;
} }
auto drawHUDLayer = properties["drawHUDLayer"];
if (drawHUDLayer.isValid()) {
bool value = drawHUDLayer.toBool();
setDrawHUDLayer(value);
needRenderItemUpdate = true;
}
auto isGrabbable = properties["grabbable"]; auto isGrabbable = properties["grabbable"];
if (isGrabbable.isValid()) { if (isGrabbable.isValid()) {
setIsGrabbable(isGrabbable.toBool()); setIsGrabbable(isGrabbable.toBool());
@ -269,10 +277,10 @@ void Base3DOverlay::update(float duration) {
// then the correct transform used for rendering is computed in the update transaction and assigned. // then the correct transform used for rendering is computed in the update transaction and assigned.
if (_renderTransformDirty) { if (_renderTransformDirty) {
auto itemID = getRenderItemID(); auto itemID = getRenderItemID();
// Capture the render transform value in game loop before
auto latestTransform = evalRenderTransform();
_renderTransformDirty = false;
if (render::Item::isValidID(itemID)) { if (render::Item::isValidID(itemID)) {
// Capture the render transform value in game loop before
auto latestTransform = evalRenderTransform();
_renderTransformDirty = false;
render::ScenePointer scene = qApp->getMain3DScene(); render::ScenePointer scene = qApp->getMain3DScene();
render::Transaction transaction; render::Transaction transaction;
transaction.updateItem<Overlay>(itemID, [latestTransform](Overlay& data) { transaction.updateItem<Overlay>(itemID, [latestTransform](Overlay& data) {
@ -282,8 +290,6 @@ void Base3DOverlay::update(float duration) {
} }
}); });
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} else {
setRenderTransform(latestTransform);
} }
} }
} }

View file

@ -41,6 +41,7 @@ public:
bool getIsSolidLine() const { return !_isDashedLine; } bool getIsSolidLine() const { return !_isDashedLine; }
bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; } bool getIgnoreRayIntersection() const { return _ignoreRayIntersection; }
bool getDrawInFront() const { return _drawInFront; } bool getDrawInFront() const { return _drawInFront; }
bool getDrawHUDLayer() const { return _drawHUDLayer; }
bool getIsGrabbable() const { return _isGrabbable; } bool getIsGrabbable() const { return _isGrabbable; }
void setLineWidth(float lineWidth) { _lineWidth = lineWidth; } void setLineWidth(float lineWidth) { _lineWidth = lineWidth; }
@ -48,6 +49,7 @@ public:
void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; } void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; }
void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; } void setIgnoreRayIntersection(bool value) { _ignoreRayIntersection = value; }
virtual void setDrawInFront(bool value) { _drawInFront = value; } virtual void setDrawInFront(bool value) { _drawInFront = value; }
virtual void setDrawHUDLayer(bool value) { _drawHUDLayer = value; }
void setIsGrabbable(bool value) { _isGrabbable = value; } void setIsGrabbable(bool value) { _isGrabbable = value; }
virtual AABox getBounds() const override = 0; virtual AABox getBounds() const override = 0;
@ -81,6 +83,7 @@ protected:
bool _isDashedLine; bool _isDashedLine;
bool _ignoreRayIntersection; bool _ignoreRayIntersection;
bool _drawInFront; bool _drawInFront;
bool _drawHUDLayer;
bool _isGrabbable { false }; bool _isGrabbable { false };
mutable bool _renderTransformDirty{ true }; mutable bool _renderTransformDirty{ true };

View file

@ -263,7 +263,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
if (isTransparent()) { if (isTransparent()) {
builder.withTranslucent(); builder.withTranslucent();
} }
if (!getIsSolid() || shouldDrawHUDLayer()) { if (!getIsSolid()) {
builder.withUnlit().withDepthBias(); builder.withUnlit().withDepthBias();
} }
return builder.build(); return builder.build();

View file

@ -113,7 +113,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() {
if (isTransparent()) { if (isTransparent()) {
builder.withTranslucent(); builder.withTranslucent();
} }
if (!getIsSolid() || shouldDrawHUDLayer()) { if (!getIsSolid()) {
builder.withUnlit().withDepthBias(); builder.withUnlit().withDepthBias();
} }
return builder.build(); return builder.build();

View file

@ -132,7 +132,7 @@ void Image3DOverlay::render(RenderArgs* args) {
const render::ShapeKey Image3DOverlay::getShapeKey() { const render::ShapeKey Image3DOverlay::getShapeKey() {
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
if (_emissive || shouldDrawHUDLayer()) { if (_emissive) {
builder.withUnlit(); builder.withUnlit();
} }
if (isTransparent()) { if (isTransparent()) {

View file

@ -87,6 +87,10 @@ void ModelOverlay::update(float deltatime) {
_drawInFrontDirty = false; _drawInFrontDirty = false;
_model->setLayeredInFront(getDrawInFront(), scene); _model->setLayeredInFront(getDrawInFront(), scene);
} }
if (_drawInHUDDirty) {
_drawInHUDDirty = false;
_model->setLayeredInHUD(getDrawHUDLayer(), scene);
}
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} }
@ -111,6 +115,11 @@ void ModelOverlay::setDrawInFront(bool drawInFront) {
_drawInFrontDirty = true; _drawInFrontDirty = true;
} }
void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) {
Base3DOverlay::setDrawHUDLayer(drawHUDLayer);
_drawInHUDDirty = true;
}
void ModelOverlay::setProperties(const QVariantMap& properties) { void ModelOverlay::setProperties(const QVariantMap& properties) {
auto origPosition = getPosition(); auto origPosition = getPosition();
auto origRotation = getRotation(); auto origRotation = getRotation();

View file

@ -51,6 +51,7 @@ public:
void setVisible(bool visible) override; void setVisible(bool visible) override;
void setDrawInFront(bool drawInFront) override; void setDrawInFront(bool drawInFront) override;
void setDrawHUDLayer(bool drawHUDLayer) override;
protected: protected:
Transform evalRenderTransform() override; Transform evalRenderTransform() override;
@ -78,8 +79,6 @@ private:
bool _scaleToFit = { false }; bool _scaleToFit = { false };
float _loadPriority { 0.0f }; float _loadPriority { 0.0f };
bool _visibleDirty { false };
bool _drawInFrontDirty { false };
AnimationPointer _animation; AnimationPointer _animation;
QUrl _animationURL; QUrl _animationURL;
@ -97,6 +96,11 @@ private:
QUrl _jointMappingURL; QUrl _jointMappingURL;
bool _jointMappingCompleted { false }; bool _jointMappingCompleted { false };
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
bool _visibleDirty { false };
bool _drawInFrontDirty { false };
bool _drawInHUDDirty { false };
}; };
#endif // hifi_ModelOverlay_h #endif // hifi_ModelOverlay_h

View file

@ -32,7 +32,6 @@ Overlay::Overlay() :
_colorPulse(0.0f), _colorPulse(0.0f),
_color(DEFAULT_OVERLAY_COLOR), _color(DEFAULT_OVERLAY_COLOR),
_visible(true), _visible(true),
_drawHUDLayer(false),
_anchor(NO_ANCHOR) _anchor(NO_ANCHOR)
{ {
} }
@ -51,7 +50,6 @@ Overlay::Overlay(const Overlay* overlay) :
_colorPulse(overlay->_colorPulse), _colorPulse(overlay->_colorPulse),
_color(overlay->_color), _color(overlay->_color),
_visible(overlay->_visible), _visible(overlay->_visible),
_drawHUDLayer(overlay->_drawHUDLayer),
_anchor(overlay->_anchor) _anchor(overlay->_anchor)
{ {
} }
@ -90,11 +88,6 @@ void Overlay::setProperties(const QVariantMap& properties) {
setColorPulse(properties["colorPulse"].toFloat()); setColorPulse(properties["colorPulse"].toFloat());
} }
if (properties["drawHUDLayer"].isValid()) {
bool drawHUDLayer = properties["drawHUDLayer"].toBool();
setDrawHUDLayer(drawHUDLayer);
}
if (properties["visible"].isValid()) { if (properties["visible"].isValid()) {
bool visible = properties["visible"].toBool(); bool visible = properties["visible"].toBool();
setVisible(visible); setVisible(visible);
@ -170,13 +163,6 @@ float Overlay::getAlpha() {
return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel); return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel);
} }
void Overlay::setDrawHUDLayer(bool drawHUDLayer) {
if (drawHUDLayer != _drawHUDLayer) {
qApp->getOverlays().setOverlayDrawHUDLayer(getOverlayID(), drawHUDLayer);
_drawHUDLayer = drawHUDLayer;
}
}
// pulse travels from min to max, then max to min in one period. // pulse travels from min to max, then max to min in one period.
float Overlay::updatePulse() { float Overlay::updatePulse() {
if (_pulsePeriod <= 0.0f) { if (_pulsePeriod <= 0.0f) {

View file

@ -58,7 +58,6 @@ public:
virtual bool is3D() const = 0; virtual bool is3D() const = 0;
bool isLoaded() { return _isLoaded; } bool isLoaded() { return _isLoaded; }
bool getVisible() const { return _visible; } bool getVisible() const { return _visible; }
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; }; virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
xColor getColor(); xColor getColor();
float getAlpha(); float getAlpha();
@ -117,7 +116,6 @@ protected:
xColor _color; xColor _color;
bool _visible; // should the overlay be drawn at all bool _visible; // should the overlay be drawn at all
bool _drawHUDLayer; // should the overlay be drawn on the HUD layer
Anchor _anchor; Anchor _anchor;
unsigned int _stackOrder { 0 }; unsigned int _stackOrder { 0 };

View file

@ -37,29 +37,22 @@
#include "Web3DOverlay.h" #include "Web3DOverlay.h"
#include <QtQuick/QQuickWindow> #include <QtQuick/QQuickWindow>
#include "render/ShapePipeline.h"
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false);
void Overlays::cleanupAllOverlays() { void Overlays::cleanupAllOverlays() {
QMap<OverlayID, Overlay::Pointer> overlaysHUD; QMap<OverlayID, Overlay::Pointer> overlaysHUD;
QMap<OverlayID, Overlay::Pointer> overlays3DHUD;
QMap<OverlayID, Overlay::Pointer> overlaysWorld; QMap<OverlayID, Overlay::Pointer> overlaysWorld;
{ {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
overlaysHUD.swap(_overlaysHUD); overlaysHUD.swap(_overlaysHUD);
overlays3DHUD.swap(_overlays3DHUD);
overlaysWorld.swap(_overlaysWorld); overlaysWorld.swap(_overlaysWorld);
} }
foreach(Overlay::Pointer overlay, overlaysHUD) { foreach(Overlay::Pointer overlay, overlaysHUD) {
_overlaysToDelete.push_back(overlay); _overlaysToDelete.push_back(overlay);
} }
foreach(Overlay::Pointer overlay, overlays3DHUD) {
_overlaysToDelete.push_back(overlay);
}
foreach(Overlay::Pointer overlay, overlaysWorld) { foreach(Overlay::Pointer overlay, overlaysWorld) {
_overlaysToDelete.push_back(overlay); _overlaysToDelete.push_back(overlay);
} }
@ -73,8 +66,6 @@ void Overlays::init() {
#if OVERLAY_PANELS #if OVERLAY_PANELS
_scriptEngine = new QScriptEngine(); _scriptEngine = new QScriptEngine();
#endif #endif
_shapePlumber = std::make_shared<render::ShapePlumber>();
initOverlay3DPipelines(*_shapePlumber, true);
} }
void Overlays::update(float deltatime) { void Overlays::update(float deltatime) {
@ -83,9 +74,6 @@ void Overlays::update(float deltatime) {
foreach(const auto& thisOverlay, _overlaysHUD) { foreach(const auto& thisOverlay, _overlaysHUD) {
thisOverlay->update(deltatime); thisOverlay->update(deltatime);
} }
foreach(const auto& thisOverlay, _overlays3DHUD) {
thisOverlay->update(deltatime);
}
foreach(const auto& thisOverlay, _overlaysWorld) { foreach(const auto& thisOverlay, _overlaysWorld) {
thisOverlay->update(deltatime); thisOverlay->update(deltatime);
} }
@ -142,23 +130,6 @@ void Overlays::renderHUD(RenderArgs* renderArgs) {
} }
} }
void Overlays::render3DHUDOverlays(RenderArgs* renderArgs) {
PROFILE_RANGE(render_overlays, __FUNCTION__);
gpu::Batch& batch = *renderArgs->_batch;
auto textureCache = DependencyManager::get<TextureCache>();
QMutexLocker lock(&_mutex);
foreach(Overlay::Pointer thisOverlay, _overlays3DHUD) {
// Reset necessary batch pipeline settings between overlays
batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this??
batch.setModelTransform(Transform());
renderArgs->_shapePipeline = _shapePlumber->pickPipeline(renderArgs, thisOverlay->getShapeKey());
thisOverlay->render(renderArgs);
}
}
void Overlays::disable() { void Overlays::disable() {
_enabled = false; _enabled = false;
} }
@ -173,8 +144,6 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
if (_overlaysHUD.contains(id)) { if (_overlaysHUD.contains(id)) {
return _overlaysHUD[id]; return _overlaysHUD[id];
} else if (_overlays3DHUD.contains(id)) {
return _overlays3DHUD[id];
} else if (_overlaysWorld.contains(id)) { } else if (_overlaysWorld.contains(id)) {
return _overlaysWorld[id]; return _overlaysWorld[id];
} }
@ -232,7 +201,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
OverlayID thisID = OverlayID(QUuid::createUuid()); OverlayID thisID = OverlayID(QUuid::createUuid());
overlay->setOverlayID(thisID); overlay->setOverlayID(thisID);
overlay->setStackOrder(_stackOrder++); overlay->setStackOrder(_stackOrder++);
if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) { if (overlay->is3D()) {
{ {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
_overlaysWorld[thisID] = overlay; _overlaysWorld[thisID] = overlay;
@ -242,9 +211,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
render::Transaction transaction; render::Transaction transaction;
overlay->addToScene(overlay, scene, transaction); overlay->addToScene(overlay, scene, transaction);
scene->enqueueTransaction(transaction); scene->enqueueTransaction(transaction);
} else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) {
QMutexLocker locker(&_mutex);
_overlays3DHUD[thisID] = overlay;
} else { } else {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
_overlaysHUD[thisID] = overlay; _overlaysHUD[thisID] = overlay;
@ -253,28 +219,6 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
return thisID; return thisID;
} }
void Overlays::setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer) {
QMutexLocker locker(&_mutex);
if (drawHUDLayer && _overlaysWorld.contains(id)) {
std::shared_ptr<Overlay> overlay = _overlaysWorld.take(id);
render::ScenePointer scene = qApp->getMain3DScene();
render::Transaction transaction;
auto itemID = overlay->getRenderItemID();
if (render::Item::isValidID(itemID)) {
overlay->removeFromScene(overlay, scene, transaction);
scene->enqueueTransaction(transaction);
}
_overlays3DHUD[id] = overlay;
} else if (!drawHUDLayer && _overlays3DHUD.contains(id)) {
std::shared_ptr<Overlay> overlay = _overlays3DHUD.take(id);
render::ScenePointer scene = qApp->getMain3DScene();
render::Transaction transaction;
overlay->addToScene(overlay, scene, transaction);
scene->enqueueTransaction(transaction);
_overlaysWorld[id] = overlay;
}
}
OverlayID Overlays::cloneOverlay(OverlayID id) { OverlayID Overlays::cloneOverlay(OverlayID id) {
if (QThread::currentThread() != thread()) { if (QThread::currentThread() != thread()) {
OverlayID result; OverlayID result;
@ -361,8 +305,6 @@ void Overlays::deleteOverlay(OverlayID id) {
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
if (_overlaysHUD.contains(id)) { if (_overlaysHUD.contains(id)) {
overlayToDelete = _overlaysHUD.take(id); overlayToDelete = _overlaysHUD.take(id);
} else if (_overlays3DHUD.contains(id)) {
overlayToDelete = _overlays3DHUD.take(id);
} else if (_overlaysWorld.contains(id)) { } else if (_overlaysWorld.contains(id)) {
overlayToDelete = _overlaysWorld.take(id); overlayToDelete = _overlaysWorld.take(id);
} else { } else {
@ -771,7 +713,7 @@ bool Overlays::isAddedOverlay(OverlayID id) {
} }
QMutexLocker locker(&_mutex); QMutexLocker locker(&_mutex);
return _overlaysHUD.contains(id) || _overlays3DHUD.contains(id) || _overlaysWorld.contains(id); return _overlaysHUD.contains(id) || _overlaysWorld.contains(id);
} }
void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) { void Overlays::sendMousePressOnOverlay(const OverlayID& overlayID, const PointerEvent& event) {

View file

@ -90,7 +90,6 @@ public:
void init(); void init();
void update(float deltatime); void update(float deltatime);
void renderHUD(RenderArgs* renderArgs); void renderHUD(RenderArgs* renderArgs);
void render3DHUDOverlays(RenderArgs* renderArgs);
void disable(); void disable();
void enable(); void enable();
@ -103,8 +102,6 @@ public:
OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); } OverlayID addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
OverlayID addOverlay(const Overlay::Pointer& overlay); OverlayID addOverlay(const Overlay::Pointer& overlay);
void setOverlayDrawHUDLayer(const OverlayID& id, const bool drawHUDLayer);
bool mousePressEvent(QMouseEvent* event); bool mousePressEvent(QMouseEvent* event);
bool mouseDoublePressEvent(QMouseEvent* event); bool mouseDoublePressEvent(QMouseEvent* event);
bool mouseReleaseEvent(QMouseEvent* event); bool mouseReleaseEvent(QMouseEvent* event);
@ -334,11 +331,8 @@ private:
mutable QMutex _mutex { QMutex::Recursive }; mutable QMutex _mutex { QMutex::Recursive };
QMap<OverlayID, Overlay::Pointer> _overlaysHUD; QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
QMap<OverlayID, Overlay::Pointer> _overlays3DHUD;
QMap<OverlayID, Overlay::Pointer> _overlaysWorld; QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
render::ShapePlumberPointer _shapePlumber;
#if OVERLAY_PANELS #if OVERLAY_PANELS
QMap<OverlayID, OverlayPanel::Pointer> _panels; QMap<OverlayID, OverlayPanel::Pointer> _panels;
#endif #endif

View file

@ -34,7 +34,8 @@ namespace render {
template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) { template <> const ItemKey payloadGetKey(const Overlay::Pointer& overlay) {
auto builder = ItemKey::Builder().withTypeShape(); auto builder = ItemKey::Builder().withTypeShape();
if (overlay->is3D()) { if (overlay->is3D()) {
if (std::static_pointer_cast<Base3DOverlay>(overlay)->getDrawInFront()) { auto overlay3D = std::static_pointer_cast<Base3DOverlay>(overlay);
if (overlay3D->getDrawInFront() || overlay3D->getDrawHUDLayer()) {
builder.withLayered(); builder.withLayered();
} }
if (overlay->isTransparent()) { if (overlay->isTransparent()) {
@ -49,20 +50,17 @@ namespace render {
return overlay->getBounds(); return overlay->getBounds();
} }
template <> int payloadGetLayer(const Overlay::Pointer& overlay) { template <> int payloadGetLayer(const Overlay::Pointer& overlay) {
// Magic number while we are defining the layering mechanism:
const int LAYER_2D = 2;
const int LAYER_3D_FRONT = 1;
const int LAYER_3D = 0;
if (overlay->is3D()) { if (overlay->is3D()) {
auto overlay3D = std::dynamic_pointer_cast<Base3DOverlay>(overlay); auto overlay3D = std::dynamic_pointer_cast<Base3DOverlay>(overlay);
if (overlay3D->getDrawInFront()) { if (overlay3D->getDrawInFront()) {
return LAYER_3D_FRONT; return Item::LAYER_3D_FRONT;
} else if (overlay3D->getDrawHUDLayer()) {
return Item::LAYER_3D_HUD;
} else { } else {
return LAYER_3D; return Item::LAYER_3D;
} }
} else { } else {
return LAYER_2D; return Item::LAYER_2D;
} }
} }
template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) {

View file

@ -55,7 +55,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() {
if (isTransparent()) { if (isTransparent()) {
builder.withTranslucent(); builder.withTranslucent();
} }
if (!getIsSolid() || shouldDrawHUDLayer()) { if (!getIsSolid()) {
builder.withUnlit().withDepthBias(); builder.withUnlit().withDepthBias();
} }
return builder.build(); return builder.build();

View file

@ -60,7 +60,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() {
if (isTransparent()) { if (isTransparent()) {
builder.withTranslucent(); builder.withTranslucent();
} }
if (!getIsSolid() || shouldDrawHUDLayer()) { if (!getIsSolid()) {
builder.withUnlit().withDepthBias(); builder.withUnlit().withDepthBias();
} }
return builder.build(); return builder.build();

View file

@ -74,6 +74,7 @@ public:
void setModelTransform(const Transform& transform) { _modelTransform = transform; } void setModelTransform(const Transform& transform) { _modelTransform = transform; }
const Transform& getModelTransform() const { return _modelTransform; } const Transform& getModelTransform() const { return _modelTransform; }
glm::mat4 getUiTransform() const;
float getAlpha() const { return _alpha; } float getAlpha() const { return _alpha; }
void setAlpha(float alpha) { if (alpha != _alpha) { emit alphaChanged(); _alpha = alpha; } } void setAlpha(float alpha) { if (alpha != _alpha) { emit alphaChanged(); _alpha = alpha; } }
@ -122,7 +123,6 @@ protected slots:
void sendFakeMouseEvent(); void sendFakeMouseEvent();
private: private:
glm::mat4 getUiTransform() const;
void updateTooltips(); void updateTooltips();
DisplayPluginPointer _currentDisplayPlugin; DisplayPluginPointer _currentDisplayPlugin;

View file

@ -307,7 +307,7 @@ bool OpenGLDisplayPlugin::activate() {
auto compositorHelper = DependencyManager::get<CompositorHelper>(); auto compositorHelper = DependencyManager::get<CompositorHelper>();
connect(compositorHelper.data(), &CompositorHelper::alphaChanged, [this] { connect(compositorHelper.data(), &CompositorHelper::alphaChanged, [this] {
auto compositorHelper = DependencyManager::get<CompositorHelper>(); auto compositorHelper = DependencyManager::get<CompositorHelper>();
auto animation = new QPropertyAnimation(this, "overlayAlpha"); auto animation = new QPropertyAnimation(this, "hudAlpha");
animation->setDuration(200); animation->setDuration(200);
animation->setEndValue(compositorHelper->getAlpha()); animation->setEndValue(compositorHelper->getAlpha());
animation->start(); animation->start();
@ -415,7 +415,7 @@ void OpenGLDisplayPlugin::customizeContext() {
state->setBlendFunction(true, state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
_overlayPipeline = gpu::Pipeline::create(program, state); _hudPipeline = gpu::Pipeline::create(program, state);
} }
{ {
@ -437,7 +437,7 @@ void OpenGLDisplayPlugin::customizeContext() {
void OpenGLDisplayPlugin::uncustomizeContext() { void OpenGLDisplayPlugin::uncustomizeContext() {
_presentPipeline.reset(); _presentPipeline.reset();
_cursorPipeline.reset(); _cursorPipeline.reset();
_overlayPipeline.reset(); _hudPipeline.reset();
_compositeFramebuffer.reset(); _compositeFramebuffer.reset();
withPresentThreadLock([&] { withPresentThreadLock([&] {
_currentFrame.reset(); _currentFrame.reset();
@ -562,22 +562,23 @@ void OpenGLDisplayPlugin::updateFrameData() {
}); });
} }
void OpenGLDisplayPlugin::compositeOverlay() { std::function<void(gpu::Batch&, const gpu::TexturePointer&)> OpenGLDisplayPlugin::getHUDOperator() {
render([&](gpu::Batch& batch){ return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
batch.enableStereo(false); if (_hudPipeline) {
batch.setFramebuffer(_compositeFramebuffer); batch.enableStereo(false);
batch.setPipeline(_overlayPipeline); batch.setPipeline(_hudPipeline);
batch.setResourceTexture(0, _currentFrame->overlay); batch.setResourceTexture(0, hudTexture);
if (isStereo()) { if (isStereo()) {
for_each_eye([&](Eye eye) { for_each_eye([&](Eye eye) {
batch.setViewportTransform(eyeViewport(eye)); batch.setViewportTransform(eyeViewport(eye));
batch.draw(gpu::TRIANGLE_STRIP, 4);
});
} else {
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize()));
batch.draw(gpu::TRIANGLE_STRIP, 4); batch.draw(gpu::TRIANGLE_STRIP, 4);
}); }
} else {
batch.setViewportTransform(ivec4(uvec2(0), _compositeFramebuffer->getSize()));
batch.draw(gpu::TRIANGLE_STRIP, 4);
} }
}); };
} }
void OpenGLDisplayPlugin::compositePointer() { void OpenGLDisplayPlugin::compositePointer() {
@ -626,29 +627,15 @@ void OpenGLDisplayPlugin::compositeLayers() {
compositeScene(); compositeScene();
} }
// Clear the depth framebuffer after drawing the scene so that the HUD elements can depth test against each other
render([&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(_compositeFramebuffer);
batch.clearDepthFramebuffer((float) UINT32_MAX);
});
#ifdef HIFI_ENABLE_NSIGHT_DEBUG #ifdef HIFI_ENABLE_NSIGHT_DEBUG
if (false) // do not compositeoverlay if running nsight debug if (false) // do not draw the HUD if running nsight debug
#endif #endif
{ {
PROFILE_RANGE_EX(render_detail, "compositeOverlay", 0xff0077ff, (uint64_t)presentCount()) PROFILE_RANGE_EX(render_detail, "handleHUDBatch", 0xff0077ff, (uint64_t)presentCount())
compositeOverlay(); auto hudOperator = getHUDOperator();
} withPresentThreadLock([&] {
_hudOperator = hudOperator;
// Only render HUD layer 3D overlays in HMD mode
if (isHmd()) {
PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount())
render([&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(_compositeFramebuffer);
}); });
_gpuContext->executeBatch(_currentFrame->postCompositeBatch);
} }
{ {
@ -656,13 +643,7 @@ void OpenGLDisplayPlugin::compositeLayers() {
compositeExtra(); compositeExtra();
} }
// Clear the depth buffer again and draw the pointer last so it's on top of everything // Draw the pointer last so it's on top of everything
render([&](gpu::Batch& batch) {
batch.enableStereo(false);
batch.setFramebuffer(_compositeFramebuffer);
batch.clearDepthFramebuffer((float) UINT32_MAX);
});
auto compositorHelper = DependencyManager::get<CompositorHelper>(); auto compositorHelper = DependencyManager::get<CompositorHelper>();
if (compositorHelper->getReticleVisible()) { if (compositorHelper->getReticleVisible()) {
PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount()) PROFILE_RANGE_EX(render_detail, "compositePointer", 0xff0077ff, (uint64_t)presentCount())
@ -844,7 +825,7 @@ void OpenGLDisplayPlugin::assertIsPresentThread() const {
bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) { bool OpenGLDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
withNonPresentThreadLock([&] { withNonPresentThreadLock([&] {
_compositeOverlayAlpha = _overlayAlpha; _compositeHUDAlpha = _hudAlpha;
}); });
return Parent::beginFrameRender(frameIndex); return Parent::beginFrameRender(frameIndex);
} }
@ -887,8 +868,7 @@ OpenGLDisplayPlugin::~OpenGLDisplayPlugin() {
void OpenGLDisplayPlugin::updateCompositeFramebuffer() { void OpenGLDisplayPlugin::updateCompositeFramebuffer() {
auto renderSize = getRecommendedRenderSize(); auto renderSize = getRecommendedRenderSize();
if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) { if (!_compositeFramebuffer || _compositeFramebuffer->getSize() != renderSize) {
auto depthFormat = gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::DEPTH_STENCIL); _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, renderSize.x, renderSize.y));
_compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OpenGLDisplayPlugin::composite", gpu::Element::COLOR_RGBA_32, depthFormat, renderSize.x, renderSize.y));
} }
} }

View file

@ -22,6 +22,8 @@
#include <SimpleMovingAverage.h> #include <SimpleMovingAverage.h>
#include <shared/RateCounter.h> #include <shared/RateCounter.h>
#include <gpu/Batch.h>
namespace gpu { namespace gpu {
namespace gl { namespace gl {
class GLBackend; class GLBackend;
@ -30,7 +32,7 @@ namespace gpu {
class OpenGLDisplayPlugin : public DisplayPlugin { class OpenGLDisplayPlugin : public DisplayPlugin {
Q_OBJECT Q_OBJECT
Q_PROPERTY(float overlayAlpha MEMBER _overlayAlpha) Q_PROPERTY(float hudAlpha MEMBER _hudAlpha)
using Parent = DisplayPlugin; using Parent = DisplayPlugin;
protected: protected:
using Mutex = std::mutex; using Mutex = std::mutex;
@ -93,7 +95,7 @@ protected:
virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; } virtual QThread::Priority getPresentPriority() { return QThread::HighPriority; }
virtual void compositeLayers(); virtual void compositeLayers();
virtual void compositeScene(); virtual void compositeScene();
virtual void compositeOverlay(); virtual std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
virtual void compositePointer(); virtual void compositePointer();
virtual void compositeExtra() {}; virtual void compositeExtra() {};
@ -137,12 +139,12 @@ protected:
gpu::FramePointer _currentFrame; gpu::FramePointer _currentFrame;
gpu::Frame* _lastFrame { nullptr }; gpu::Frame* _lastFrame { nullptr };
gpu::FramebufferPointer _compositeFramebuffer; gpu::FramebufferPointer _compositeFramebuffer;
gpu::PipelinePointer _overlayPipeline; gpu::PipelinePointer _hudPipeline;
gpu::PipelinePointer _simplePipeline; gpu::PipelinePointer _simplePipeline;
gpu::PipelinePointer _presentPipeline; gpu::PipelinePointer _presentPipeline;
gpu::PipelinePointer _cursorPipeline; gpu::PipelinePointer _cursorPipeline;
gpu::TexturePointer _displayTexture{}; gpu::TexturePointer _displayTexture{};
float _compositeOverlayAlpha { 1.0f }; float _compositeHUDAlpha { 1.0f };
struct CursorData { struct CursorData {
QImage image; QImage image;
@ -176,6 +178,6 @@ protected:
// Any resource shared by the main thread and the presentation thread must // Any resource shared by the main thread and the presentation thread must
// be serialized through this mutex // be serialized through this mutex
mutable Mutex _presentMutex; mutable Mutex _presentMutex;
float _overlayAlpha{ 1.0f }; float _hudAlpha{ 1.0f };
}; };

View file

@ -33,6 +33,9 @@
#include "../Logging.h" #include "../Logging.h"
#include "../CompositorHelper.h" #include "../CompositorHelper.h"
#include "render-utils/hmd_ui_vert.h"
#include "render-utils/hmd_ui_frag.h"
static const QString MONO_PREVIEW = "Mono Preview"; static const QString MONO_PREVIEW = "Mono Preview";
static const QString DISABLE_PREVIEW = "Disable Preview"; static const QString DISABLE_PREVIEW = "Disable Preview";
static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate";
@ -46,19 +49,11 @@ static const glm::mat4 IDENTITY_MATRIX;
//#define LIVE_SHADER_RELOAD 1 //#define LIVE_SHADER_RELOAD 1
extern glm::vec3 getPoint(float yaw, float pitch); extern glm::vec3 getPoint(float yaw, float pitch);
static QString readFile(const QString& filename) {
QFile file(filename);
file.open(QFile::Text | QFile::ReadOnly);
QString result;
result.append(QTextStream(&file).readAll());
return result;
}
glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const { glm::uvec2 HmdDisplayPlugin::getRecommendedUiSize() const {
return CompositorHelper::VIRTUAL_SCREEN_SIZE; return CompositorHelper::VIRTUAL_SCREEN_SIZE;
} }
QRect HmdDisplayPlugin::getRecommendedOverlayRect() const { QRect HmdDisplayPlugin::getRecommendedHUDRect() const {
return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT; return CompositorHelper::VIRTUAL_SCREEN_RECOMMENDED_OVERLAY_RECT;
} }
@ -108,7 +103,7 @@ void HmdDisplayPlugin::internalDeactivate() {
void HmdDisplayPlugin::customizeContext() { void HmdDisplayPlugin::customizeContext() {
Parent::customizeContext(); Parent::customizeContext();
_overlayRenderer.build(); _hudRenderer.build();
} }
void HmdDisplayPlugin::uncustomizeContext() { void HmdDisplayPlugin::uncustomizeContext() {
@ -121,7 +116,7 @@ void HmdDisplayPlugin::uncustomizeContext() {
batch.setFramebuffer(_compositeFramebuffer); batch.setFramebuffer(_compositeFramebuffer);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0)); batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, vec4(0));
}); });
_overlayRenderer = OverlayRenderer(); _hudRenderer = HUDRenderer();
_previewTexture.reset(); _previewTexture.reset();
Parent::uncustomizeContext(); Parent::uncustomizeContext();
} }
@ -171,7 +166,7 @@ float HmdDisplayPlugin::getLeftCenterPixel() const {
void HmdDisplayPlugin::internalPresent() { void HmdDisplayPlugin::internalPresent() {
PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) PROFILE_RANGE_EX(render, __FUNCTION__, 0xff00ff00, (uint64_t)presentCount())
// Composite together the scene, overlay and mouse cursor // Composite together the scene, hud and mouse cursor
hmdPresent(); hmdPresent();
if (_displayTexture) { if (_displayTexture) {
@ -344,17 +339,9 @@ void HmdDisplayPlugin::updateFrameData() {
auto correction = glm::inverse(batchPose) * currentPose; auto correction = glm::inverse(batchPose) * currentPose;
getGLBackend()->setCameraCorrection(correction); getGLBackend()->setCameraCorrection(correction);
} }
auto compositorHelper = DependencyManager::get<CompositorHelper>();
glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix();
for_each_eye([&](Eye eye) {
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat;
_overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView;
});
} }
void HmdDisplayPlugin::OverlayRenderer::build() { void HmdDisplayPlugin::HUDRenderer::build() {
vertices = std::make_shared<gpu::Buffer>(); vertices = std::make_shared<gpu::Buffer>();
indices = std::make_shared<gpu::Buffer>(); indices = std::make_shared<gpu::Buffer>();
@ -410,38 +397,20 @@ void HmdDisplayPlugin::OverlayRenderer::build() {
format = std::make_shared<gpu::Stream::Format>(); // 1 for everyone format = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV));
uniformBuffers[0] = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr); uniformsBuffer = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
uniformBuffers[1] = std::make_shared<gpu::Buffer>(sizeof(Uniforms), nullptr);
updatePipeline(); updatePipeline();
} }
void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { void HmdDisplayPlugin::HUDRenderer::updatePipeline() {
static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert";
static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag";
#if LIVE_SHADER_RELOAD
static qint64 vsBuiltAge = 0;
static qint64 fsBuiltAge = 0;
QFileInfo vsInfo(vsFile);
QFileInfo fsInfo(fsFile);
auto vsAge = vsInfo.lastModified().toMSecsSinceEpoch();
auto fsAge = fsInfo.lastModified().toMSecsSinceEpoch();
if (!pipeline || vsAge > vsBuiltAge || fsAge > fsBuiltAge) {
vsBuiltAge = vsAge;
fsBuiltAge = fsAge;
#else
if (!pipeline) { if (!pipeline) {
#endif auto vs = gpu::Shader::createVertex(std::string(hmd_ui_vert));
QString vsSource = readFile(vsFile); auto ps = gpu::Shader::createPixel(std::string(hmd_ui_frag));
QString fsSource = readFile(fsFile);
auto vs = gpu::Shader::createVertex(vsSource.toLocal8Bit().toStdString());
auto ps = gpu::Shader::createPixel(fsSource.toLocal8Bit().toStdString());
auto program = gpu::Shader::createProgram(vs, ps); auto program = gpu::Shader::createProgram(vs, ps);
gpu::gl::GLBackend::makeProgram(*program, gpu::Shader::BindingSet()); gpu::gl::GLBackend::makeProgram(*program, gpu::Shader::BindingSet());
this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer"); uniformsLocation = program->getUniformBuffers().findLocation("hudBuffer");
gpu::StatePointer state = gpu::StatePointer(new gpu::State()); gpu::StatePointer state = gpu::StatePointer(new gpu::State());
state->setDepthTest(gpu::State::DepthTest(false, false, gpu::LESS_EQUAL)); state->setDepthTest(gpu::State::DepthTest(true, true, gpu::LESS_EQUAL));
state->setBlendFunction(true, state->setBlendFunction(true,
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
@ -450,30 +419,29 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
} }
} }
void HmdDisplayPlugin::OverlayRenderer::render(HmdDisplayPlugin& plugin) { std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::HUDRenderer::render(HmdDisplayPlugin& plugin) {
updatePipeline(); updatePipeline();
for_each_eye([&](Eye eye){ return [this](gpu::Batch& batch, const gpu::TexturePointer& hudTexture) {
uniforms.mvp = mvps[eye]; if (pipeline) {
uniformBuffers[eye]->setSubData(0, uniforms); batch.setPipeline(pipeline);
});
plugin.render([&](gpu::Batch& batch) { batch.setInputFormat(format);
batch.enableStereo(false); gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element);
batch.setFramebuffer(plugin._compositeFramebuffer); gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
batch.setPipeline(pipeline); batch.setInputBuffer(gpu::Stream::POSITION, posView);
batch.setInputFormat(format); batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView);
gpu::BufferView posView(vertices, VERTEX_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::POSITION)._element); batch.setIndexBuffer(gpu::UINT16, indices, 0);
gpu::BufferView uvView(vertices, TEXTURE_OFFSET, vertices->getSize(), VERTEX_STRIDE, format->getAttributes().at(gpu::Stream::TEXCOORD)._element);
batch.setInputBuffer(gpu::Stream::POSITION, posView); uniformsBuffer->setSubData(0, uniforms);
batch.setInputBuffer(gpu::Stream::TEXCOORD, uvView); batch.setUniformBuffer(uniformsLocation, uniformsBuffer);
batch.setIndexBuffer(gpu::UINT16, indices, 0);
batch.setResourceTexture(0, plugin._currentFrame->overlay); auto compositorHelper = DependencyManager::get<CompositorHelper>();
// FIXME use stereo information input to set both MVPs in the uniforms batch.setModelTransform(compositorHelper->getUiTransform());
for_each_eye([&](Eye eye) { batch.setResourceTexture(0, hudTexture);
batch.setUniformBuffer(uniformsLocation, uniformBuffers[eye]);
batch.setViewportTransform(plugin.eyeViewport(eye));
batch.drawIndexed(gpu::TRIANGLES, indexCount); batch.drawIndexed(gpu::TRIANGLES, indexCount);
}); }
}); };
} }
void HmdDisplayPlugin::compositePointer() { void HmdDisplayPlugin::compositePointer() {
@ -500,12 +468,8 @@ void HmdDisplayPlugin::compositePointer() {
}); });
} }
void HmdDisplayPlugin::compositeOverlay() { std::function<void(gpu::Batch&, const gpu::TexturePointer&)> HmdDisplayPlugin::getHUDOperator() {
if (!_currentFrame || !_currentFrame->overlay) { return _hudRenderer.render(*this);
return;
}
_overlayRenderer.render(*this);
} }
HmdDisplayPlugin::~HmdDisplayPlugin() { HmdDisplayPlugin::~HmdDisplayPlugin() {

View file

@ -33,7 +33,7 @@ public:
glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; } glm::uvec2 getRecommendedRenderSize() const override final { return _renderTargetSize; }
bool isDisplayVisible() const override { return isHmdMounted(); } bool isDisplayVisible() const override { return isHmdMounted(); }
QRect getRecommendedOverlayRect() const override final; QRect getRecommendedHUDRect() const override final;
virtual glm::mat4 getHeadPose() const override; virtual glm::mat4 getHeadPose() const override;
@ -53,7 +53,7 @@ protected:
bool internalActivate() override; bool internalActivate() override;
void internalDeactivate() override; void internalDeactivate() override;
void compositeOverlay() override; std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator() override;
void compositePointer() override; void compositePointer() override;
void internalPresent() override; void internalPresent() override;
void customizeContext() override; void customizeContext() override;
@ -91,7 +91,7 @@ private:
gpu::TexturePointer _previewTexture; gpu::TexturePointer _previewTexture;
glm::vec2 _lastWindowSize; glm::vec2 _lastWindowSize;
struct OverlayRenderer { struct HUDRenderer {
gpu::Stream::FormatPointer format; gpu::Stream::FormatPointer format;
gpu::BufferPointer vertices; gpu::BufferPointer vertices;
gpu::BufferPointer indices; gpu::BufferPointer indices;
@ -99,12 +99,9 @@ private:
gpu::PipelinePointer pipeline; gpu::PipelinePointer pipeline;
int32_t uniformsLocation { -1 }; int32_t uniformsLocation { -1 };
// FIXME this is stupid, use the built in transformation pipeline gpu::BufferPointer uniformsBuffer;
std::array<gpu::BufferPointer, 2> uniformBuffers;
std::array<mat4, 2> mvps;
struct Uniforms { struct Uniforms {
mat4 mvp;
float alpha { 1.0f }; float alpha { 1.0f };
} uniforms; } uniforms;
@ -119,6 +116,6 @@ private:
void build(); void build();
void updatePipeline(); void updatePipeline();
void render(HmdDisplayPlugin& plugin); std::function<void(gpu::Batch&, const gpu::TexturePointer&)> render(HmdDisplayPlugin& plugin);
} _overlayRenderer; } _hudRenderer;
}; };

View file

@ -92,7 +92,7 @@ public:
void captureNamedDrawCallInfo(std::string name); void captureNamedDrawCallInfo(std::string name);
Batch(); Batch();
explicit Batch(const Batch& batch); Batch(const Batch& batch);
~Batch(); ~Batch();
void clear(); void clear();

View file

@ -32,14 +32,10 @@ namespace gpu {
Mat4 pose; Mat4 pose;
/// The collection of batches which make up the frame /// The collection of batches which make up the frame
Batches batches; Batches batches;
/// Single batch containing overlays to be drawn in the composite framebuffer
Batch postCompositeBatch;
/// The main thread updates to buffers that are applicable for this frame. /// The main thread updates to buffers that are applicable for this frame.
BufferUpdates bufferUpdates; BufferUpdates bufferUpdates;
/// The destination framebuffer in which the results will be placed /// The destination framebuffer in which the results will be placed
FramebufferPointer framebuffer; FramebufferPointer framebuffer;
/// The destination texture containing the 2D overlay
TexturePointer overlay;
/// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE /// How to process the framebuffer when the frame dies. MUST BE THREAD SAFE
FramebufferRecycler framebufferRecycler; FramebufferRecycler framebufferRecycler;

View file

@ -74,9 +74,7 @@ glm::uvec2 rectifyToSparseSize(const glm::uvec2& size) {
namespace image { namespace image {
enum { QImage::Format QIMAGE_HDR_FORMAT = QImage::Format_RGB30;
QIMAGE_HDR_FORMAT = QImage::Format_RGB30
};
TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) { TextureUsage::TextureLoader TextureUsage::getTextureLoaderForType(Type type, const QVariantMap& options) {
switch (type) { switch (type) {
@ -440,10 +438,8 @@ void generateHDRMips(gpu::Texture* texture, const QImage& image, const std::atom
auto mipFormat = texture->getStoredMipFormat(); auto mipFormat = texture->getStoredMipFormat();
std::function<glm::vec3(uint32)> unpackFunc; std::function<glm::vec3(uint32)> unpackFunc;
nvtt::TextureType textureType = nvtt::TextureType_2D;
nvtt::InputFormat inputFormat = nvtt::InputFormat_RGBA_32F; nvtt::InputFormat inputFormat = nvtt::InputFormat_RGBA_32F;
nvtt::WrapMode wrapMode = nvtt::WrapMode_Mirror; nvtt::WrapMode wrapMode = nvtt::WrapMode_Mirror;
nvtt::RoundMode roundMode = nvtt::RoundMode_None;
nvtt::AlphaMode alphaMode = nvtt::AlphaMode_None; nvtt::AlphaMode alphaMode = nvtt::AlphaMode_None;
nvtt::CompressionOptions compressionOptions; nvtt::CompressionOptions compressionOptions;

View file

@ -34,3 +34,12 @@ void DisplayPlugin::waitForPresent() {
} }
} }
} }
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> DisplayPlugin::getHUDOperator() {
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> hudOperator;
{
QMutexLocker locker(&_presentMutex);
hudOperator = _hudOperator;
}
return hudOperator;
}

View file

@ -156,8 +156,8 @@ public:
return aspect(getRecommendedRenderSize()); return aspect(getRecommendedRenderSize());
} }
// The recommended bounds for primary overlay placement // The recommended bounds for primary HUD placement
virtual QRect getRecommendedOverlayRect() const { virtual QRect getRecommendedHUDRect() const {
const int DESKTOP_SCREEN_PADDING = 50; const int DESKTOP_SCREEN_PADDING = 50;
auto recommendedSize = getRecommendedUiSize() - glm::uvec2(DESKTOP_SCREEN_PADDING); auto recommendedSize = getRecommendedUiSize() - glm::uvec2(DESKTOP_SCREEN_PADDING);
return QRect(0, 0, recommendedSize.x, recommendedSize.y); return QRect(0, 0, recommendedSize.x, recommendedSize.y);
@ -204,8 +204,9 @@ public:
void waitForPresent(); void waitForPresent();
static const QString& MENU_PATH(); std::function<void(gpu::Batch&, const gpu::TexturePointer&)> getHUDOperator();
static const QString& MENU_PATH();
signals: signals:
void recommendedFramebufferSizeChanged(const QSize& size); void recommendedFramebufferSizeChanged(const QSize& size);
@ -217,6 +218,8 @@ protected:
gpu::ContextPointer _gpuContext; gpu::ContextPointer _gpuContext;
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator { std::function<void(gpu::Batch&, const gpu::TexturePointer&)>() };
private: private:
QMutex _presentMutex; QMutex _presentMutex;
QWaitCondition _presentCondition; QWaitCondition _presentCondition;

View file

@ -385,7 +385,7 @@ ItemKey ModelMeshPartPayload::getKey() const {
builder.withInvisible(); builder.withInvisible();
} }
if (model->isLayeredInFront()) { if (model->isLayeredInFront() || model->isLayeredInHUD()) {
builder.withLayered(); builder.withLayered();
} }
@ -404,15 +404,15 @@ ItemKey ModelMeshPartPayload::getKey() const {
} }
int ModelMeshPartPayload::getLayer() const { int ModelMeshPartPayload::getLayer() const {
// MAgic number while we are defining the layering mechanism:
const int LAYER_3D_FRONT = 1;
const int LAYER_3D = 0;
ModelPointer model = _model.lock(); ModelPointer model = _model.lock();
if (model && model->isLayeredInFront()) { if (model) {
return LAYER_3D_FRONT; if (model->isLayeredInFront()) {
} else { return Item::LAYER_3D_FRONT;
return LAYER_3D; } else if (model->isLayeredInHUD()) {
return Item::LAYER_3D_HUD;
}
} }
return Item::LAYER_3D;
} }
ShapeKey ModelMeshPartPayload::getShapeKey() const { ShapeKey ModelMeshPartPayload::getShapeKey() const {

View file

@ -603,6 +603,21 @@ void Model::setLayeredInFront(bool layered, const render::ScenePointer& scene) {
} }
} }
void Model::setLayeredInHUD(bool layered, const render::ScenePointer& scene) {
if (_isLayeredInHUD != layered) {
_isLayeredInHUD = layered;
render::Transaction transaction;
foreach(auto item, _modelMeshRenderItemsMap.keys()) {
transaction.resetItem(item, _modelMeshRenderItemsMap[item]);
}
foreach(auto item, _collisionRenderItemsMap.keys()) {
transaction.resetItem(item, _collisionRenderItemsMap[item]);
}
scene->enqueueTransaction(transaction);
}
}
bool Model::addToScene(const render::ScenePointer& scene, bool Model::addToScene(const render::ScenePointer& scene,
render::Transaction& transaction, render::Transaction& transaction,
render::Item::Status::Getters& statusGetters) { render::Item::Status::Getters& statusGetters) {

View file

@ -84,6 +84,7 @@ public:
// new Scene/Engine rendering support // new Scene/Engine rendering support
void setVisibleInScene(bool newValue, const render::ScenePointer& scene); void setVisibleInScene(bool newValue, const render::ScenePointer& scene);
void setLayeredInFront(bool layered, const render::ScenePointer& scene); void setLayeredInFront(bool layered, const render::ScenePointer& scene);
void setLayeredInHUD(bool layered, const render::ScenePointer& scene);
bool needsFixupInScene() const; bool needsFixupInScene() const;
bool needsReload() const { return _needsReload; } bool needsReload() const { return _needsReload; }
@ -101,6 +102,7 @@ public:
bool isVisible() const { return _isVisible; } bool isVisible() const { return _isVisible; }
bool isLayeredInFront() const { return _isLayeredInFront; } bool isLayeredInFront() const { return _isLayeredInFront; }
bool isLayeredInHUD() const { return _isLayeredInHUD; }
virtual void updateRenderItems(); virtual void updateRenderItems();
void setRenderItemsNeedUpdate(); void setRenderItemsNeedUpdate();
@ -411,6 +413,7 @@ protected:
int _renderInfoHasTransparent { false }; int _renderInfoHasTransparent { false };
bool _isLayeredInFront { false }; bool _isLayeredInFront { false };
bool _isLayeredInHUD { false };
private: private:
float _loadingPriority { 0.0f }; float _loadingPriority { 0.0f };

View file

@ -186,15 +186,20 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
task.addJob<DrawBounds>("DrawZones", zones); task.addJob<DrawBounds>("DrawZones", zones);
} }
// Overlays // Layered Overlays
const auto overlayOpaquesInputs = DrawOverlay3D::Inputs(overlayOpaques, lightingModel).asVarying(); const auto filteredOverlaysOpaque = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredOpaque", overlayOpaques, Item::LAYER_3D_FRONT);
const auto overlayTransparentsInputs = DrawOverlay3D::Inputs(overlayTransparents, lightingModel).asVarying(); const auto filteredOverlaysTransparent = task.addJob<FilterLayeredItems>("FilterOverlaysLayeredTransparent", overlayTransparents, Item::LAYER_3D_FRONT);
task.addJob<DrawOverlay3D>("DrawOverlay3DOpaque", overlayOpaquesInputs, true); const auto overlaysInFrontOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(0);
task.addJob<DrawOverlay3D>("DrawOverlay3DTransparent", overlayTransparentsInputs, false); const auto overlaysInFrontTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(0);
{ // Debug the bounds of the rendered Overlay items, still look at the zbuffer const auto overlayInFrontOpaquesInputs = DrawOverlay3D::Inputs(overlaysInFrontOpaque, lightingModel).asVarying();
task.addJob<DrawBounds>("DrawOverlayOpaqueBounds", overlayOpaques); const auto overlayInFrontTransparentsInputs = DrawOverlay3D::Inputs(overlaysInFrontTransparent, lightingModel).asVarying();
task.addJob<DrawBounds>("DrawOverlayTransparentBounds", overlayTransparents); task.addJob<DrawOverlay3D>("DrawOverlayInFrontOpaque", overlayInFrontOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayInFrontTransparent", overlayInFrontTransparentsInputs, false);
{ // Debug the bounds of the rendered Overlay items that are marked drawInFront, still look at the zbuffer
task.addJob<DrawBounds>("DrawOverlayInFrontOpaqueBounds", overlaysInFrontOpaque);
task.addJob<DrawBounds>("DrawOverlayInFrontTransparentBounds", overlaysInFrontTransparent);
} }
// Debugging stages // Debugging stages
@ -233,6 +238,22 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren
// AA job to be revisited // AA job to be revisited
task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer); task.addJob<Antialiasing>("Antialiasing", primaryFramebuffer);
// Composite the HUD and HUD overlays
task.addJob<CompositeHUD>("HUD");
const auto overlaysHUDOpaque = filteredOverlaysOpaque.getN<FilterLayeredItems::Outputs>(1);
const auto overlaysHUDTransparent = filteredOverlaysTransparent.getN<FilterLayeredItems::Outputs>(1);
const auto overlayHUDOpaquesInputs = DrawOverlay3D::Inputs(overlaysHUDOpaque, lightingModel).asVarying();
const auto overlayHUDTransparentsInputs = DrawOverlay3D::Inputs(overlaysHUDTransparent, lightingModel).asVarying();
task.addJob<DrawOverlay3D>("DrawOverlayHUDOpaque", overlayHUDOpaquesInputs, true);
task.addJob<DrawOverlay3D>("DrawOverlayHUDTransparent", overlayHUDTransparentsInputs, false);
{ // Debug the bounds of the rendered Overlay items that are marked drawHUDLayer, still look at the zbuffer
task.addJob<DrawBounds>("DrawOverlayHUDOpaqueBounds", overlaysHUDOpaque);
task.addJob<DrawBounds>("DrawOverlayHUDTransparentBounds", overlaysHUDTransparent);
}
task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer); task.addJob<EndGPURangeTimer>("ToneAndPostRangeTimer", toneAndPostRangeTimer);
// Blit! // Blit!
@ -407,6 +428,18 @@ void DrawOverlay3D::run(const RenderContextPointer& renderContext, const Inputs&
} }
} }
void CompositeHUD::run(const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_context);
// Grab the HUD texture
gpu::doInBatch(renderContext->args->_context, [&](gpu::Batch& batch) {
if (renderContext->args->_hudOperator) {
renderContext->args->_hudOperator(batch, renderContext->args->_hudTexture);
}
});
}
void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) { void Blit::run(const RenderContextPointer& renderContext, const gpu::FramebufferPointer& srcFramebuffer) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_context); assert(renderContext->args->_context);

View file

@ -155,6 +155,14 @@ protected:
bool _opaquePass { true }; bool _opaquePass { true };
}; };
class CompositeHUD {
public:
using JobModel = render::Job::Model<CompositeHUD>;
CompositeHUD() {}
void run(const render::RenderContextPointer& renderContext);
};
class Blit { class Blit {
public: public:
using JobModel = render::Job::ModelI<Blit, gpu::FramebufferPointer>; using JobModel = render::Job::ModelI<Blit, gpu::FramebufferPointer>;

View file

@ -0,0 +1,37 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// hmd_ui.frag
// fragment shader
//
// Created by Sam Gondelman on 9/28/17.
// Copyright 2017 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 hudTexture;
struct HUDData {
float alpha;
};
layout(std140) uniform hudBuffer {
HUDData hud;
};
in vec2 _texCoord0;
out vec4 fragColor0;
void main() {
vec4 color = texture(hudTexture, _texCoord0);
color.a *= hud.alpha;
if (color.a <= 0.0) {
discard;
}
fragColor0 = color;
}

View file

@ -0,0 +1,36 @@
<@include gpu/Config.slh@>
<$VERSION_HEADER$>
// Generated on <$_SCRIBE_DATE$>
//
// hmd_ui.vert
// vertex shader
//
// Created by Sam Gondelman on 9/28/17.
// Copyright 2017 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/Inputs.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
struct HUDData {
float alpha;
};
layout(std140) uniform hudBuffer {
HUDData hud;
};
out vec2 _texCoord0;
void main() {
_texCoord0 = inTexCoord0.st;
// standard transform
TransformCamera cam = getTransformCamera();
TransformObject obj = getTransformObject();
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
}

View file

@ -121,6 +121,9 @@ namespace render {
RenderDetails _details; RenderDetails _details;
render::ScenePointer _scene; render::ScenePointer _scene;
int8_t _cameraMode { -1 }; int8_t _cameraMode { -1 };
std::function<void(gpu::Batch&, const gpu::TexturePointer&)> _hudOperator;
gpu::TexturePointer _hudTexture;
}; };
} }

View file

@ -21,19 +21,24 @@
using namespace render; using namespace render;
void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { void FilterLayeredItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs) {
auto& scene = renderContext->_scene; auto& scene = renderContext->_scene;
// Clear previous values ItemBounds matchedItems;
outItems.clear(); ItemBounds nonMatchItems;
// For each item, filter it into one bucket // For each item, filter it into one bucket
for (auto& itemBound : inItems) { for (auto& itemBound : inItems) {
auto& item = scene->getItem(itemBound.id); auto& item = scene->getItem(itemBound.id);
if (item.getLayer() == _keepLayer) { if (item.getLayer() == _keepLayer) {
outItems.emplace_back(itemBound); matchedItems.emplace_back(itemBound);
} else {
nonMatchItems.emplace_back(itemBound);
} }
} }
outputs.edit0() = matchedItems;
outputs.edit1() = nonMatchItems;
} }
void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { void SliceItems::run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) {

View file

@ -65,15 +65,15 @@ namespace render {
// Filter the items belonging to the job's keep layer // Filter the items belonging to the job's keep layer
class FilterLayeredItems { class FilterLayeredItems {
public: public:
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, ItemBounds>; using Outputs = render::VaryingSet2<ItemBounds, ItemBounds>;
using JobModel = Job::ModelIO<FilterLayeredItems, ItemBounds, Outputs>;
FilterLayeredItems() {}
FilterLayeredItems(int keepLayer) : FilterLayeredItems(int keepLayer) :
_keepLayer(keepLayer) {} _keepLayer(keepLayer) {}
int _keepLayer { 0 }; int _keepLayer;
void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); void run(const RenderContextPointer& renderContext, const ItemBounds& inItems, Outputs& outputs);
}; };
// SliceItems job config defining the slice range // SliceItems job config defining the slice range

View file

@ -29,6 +29,11 @@ const float Item::Status::Value::CYAN = 180.0f;
const float Item::Status::Value::BLUE = 240.0f; const float Item::Status::Value::BLUE = 240.0f;
const float Item::Status::Value::MAGENTA = 300.0f; const float Item::Status::Value::MAGENTA = 300.0f;
const int Item::LAYER_2D = 0;
const int Item::LAYER_3D = 1;
const int Item::LAYER_3D_FRONT = 2;
const int Item::LAYER_3D_HUD = 3;
void Item::Status::Value::setScale(float scale) { void Item::Status::Value::setScale(float scale) {
_scale = (std::numeric_limits<unsigned short>::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f)); _scale = (std::numeric_limits<unsigned short>::max() -1) * 0.5f * (1.0f + std::max(std::min(scale, 1.0f), 0.0f));
} }

View file

@ -356,9 +356,14 @@ public:
// Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace()) // Get the bound of the item expressed in world space (or eye space depending on the key.isWorldSpace())
const Bound getBound() const { return _payload->getBound(); } const Bound getBound() const { return _payload->getBound(); }
// Get the layer where the item belongs. 0 by default meaning NOT LAYERED // Get the layer where the item belongs.
int getLayer() const { return _payload->getLayer(); } int getLayer() const { return _payload->getLayer(); }
static const int LAYER_2D;
static const int LAYER_3D;
static const int LAYER_3D_FRONT;
static const int LAYER_3D_HUD;
// Render call for the item // Render call for the item
void render(RenderArgs* args) const { _payload->render(args); } void render(RenderArgs* args) const { _payload->render(args); }

View file

@ -178,15 +178,26 @@ Column {
onCheckedChanged: { mainViewTask.getConfig("DrawTransparentBounds")["enabled"] = checked } onCheckedChanged: { mainViewTask.getConfig("DrawTransparentBounds")["enabled"] = checked }
} }
CheckBox { CheckBox {
text: "Overlay Opaques" text: "Opaques in Front"
checked: mainViewTask.getConfig("DrawOverlayOpaqueBounds")["enabled"] checked: mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"]
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayOpaqueBounds")["enabled"] = checked } onCheckedChanged: { mainViewTask.getConfig("DrawOverlayInFrontOpaqueBounds")["enabled"] = checked }
} }
CheckBox { CheckBox {
text: "Overlay Transparents" text: "Transparents in Front"
checked: mainViewTask.getConfig("DrawOverlayTransparentBounds")["enabled"] checked: mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"]
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayTransparentBounds")["enabled"] = checked } onCheckedChanged: { mainViewTask.getConfig("DrawOverlayInFrontTransparentBounds")["enabled"] = checked }
} }
CheckBox {
text: "Opaques in HUD"
checked: mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"]
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] = checked }
}
CheckBox {
text: "Transparents in HUD"
checked: mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"]
onCheckedChanged: { mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked }
}
} }
Column { Column {
CheckBox { CheckBox {

View file

@ -31,7 +31,7 @@
glow: 1.0, glow: 1.0,
lineWidth: 5, lineWidth: 5,
ignoreRayIntersection: true, // always ignore this ignoreRayIntersection: true, // always ignore this
drawHUDLayer: true, // Even when burried inside of something, show it. drawHUDLayer: true,
parentID: AVATAR_SELF_ID parentID: AVATAR_SELF_ID
}; };
var halfEnd = { var halfEnd = {
@ -40,7 +40,7 @@
color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE,
alpha: 0.9, alpha: 0.9,
ignoreRayIntersection: true, ignoreRayIntersection: true,
drawHUDLayer: true, // Even when burried inside of something, show it. drawHUDLayer: true,
visible: true visible: true
}; };
var fullPath = { var fullPath = {
@ -52,7 +52,7 @@
glow: 1.0, glow: 1.0,
lineWidth: 5, lineWidth: 5,
ignoreRayIntersection: true, // always ignore this ignoreRayIntersection: true, // always ignore this
drawHUDLayer: true, // Even when burried inside of something, show it. drawHUDLayer: true,
parentID: AVATAR_SELF_ID parentID: AVATAR_SELF_ID
}; };
var fullEnd = { var fullEnd = {
@ -61,7 +61,7 @@
color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE,
alpha: 0.9, alpha: 0.9,
ignoreRayIntersection: true, ignoreRayIntersection: true,
drawHUDLayer: true, // Even when burried inside of something, show it. drawHUDLayer: true,
visible: true visible: true
}; };
var holdPath = { var holdPath = {
@ -73,7 +73,7 @@
glow: 1.0, glow: 1.0,
lineWidth: 5, lineWidth: 5,
ignoreRayIntersection: true, // always ignore this ignoreRayIntersection: true, // always ignore this
drawHUDLayer: true, // Even when burried inside of something, show it. drawHUDLayer: true,
parentID: AVATAR_SELF_ID parentID: AVATAR_SELF_ID
}; };

View file

@ -370,7 +370,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
return Math.min(Math.max(value, min), max); return Math.min(Math.max(value, min), max);
} }
var recommendedRect = Controller.getRecommendedOverlayRect(); var recommendedRect = Controller.getRecommendedHUDRect();
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height }; var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions(); that.windowDimensions = recommendedDimmensions; // Controller.getViewportDimensions();
that.origin = { x: recommendedRect.x, y: recommendedRect.y }; that.origin = { x: recommendedRect.x, y: recommendedRect.y };
@ -378,7 +378,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
// For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen". // For example, maybe we want "keep the same percentage to whatever two edges are closest to the edge of screen".
// If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below. // If we change that, the places to do so are onResizeViewport, save (maybe), and the initial move based on Settings, below.
that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients. that.onResizeViewport = function (newSize) { // Can be overridden or extended by clients.
var recommendedRect = Controller.getRecommendedOverlayRect(); var recommendedRect = Controller.getRecommendedHUDRect();
var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height }; var recommendedDimmensions = { x: recommendedRect.width, y: recommendedRect.height };
var originRelativeX = (that.x - that.origin.x - that.offset.x); var originRelativeX = (that.x - that.origin.x - that.offset.x);
var originRelativeY = (that.y - that.origin.y - that.offset.y); var originRelativeY = (that.y - that.origin.y - that.offset.y);
@ -396,7 +396,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
// code once the new toolbar position is well established with users. // code once the new toolbar position is well established with users.
this.isNewPositionKey = optionalPersistenceKey + '.isNewPosition'; this.isNewPositionKey = optionalPersistenceKey + '.isNewPosition';
this.save = function () { this.save = function () {
var recommendedRect = Controller.getRecommendedOverlayRect(); var recommendedRect = Controller.getRecommendedHUDRect();
var screenSize = { x: recommendedRect.width, y: recommendedRect.height }; var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
if (screenSize.x > 0 && screenSize.y > 0) { if (screenSize.x > 0 && screenSize.y > 0) {
// Guard against invalid screen size that can occur at shut-down. // Guard against invalid screen size that can occur at shut-down.
@ -443,7 +443,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y); that.move(that.dragOffsetX + event.x, that.dragOffsetY + event.y);
}; };
that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport. that.checkResize = function () { // Can be overriden or extended, but usually not. See onResizeViewport.
var recommendedRect = Controller.getRecommendedOverlayRect(); var recommendedRect = Controller.getRecommendedHUDRect();
var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height }; var currentWindowSize = { x: recommendedRect.width, y: recommendedRect.height };
if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) { if ((currentWindowSize.x !== that.windowDimensions.x) || (currentWindowSize.y !== that.windowDimensions.y)) {
@ -471,7 +471,7 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit
var savedFraction = isNewPosition ? JSON.parse(Settings.getValue(this.fractionKey) || "0") : 0; var savedFraction = isNewPosition ? JSON.parse(Settings.getValue(this.fractionKey) || "0") : 0;
Settings.setValue(this.isNewPositionKey, true); Settings.setValue(this.isNewPositionKey, true);
var recommendedRect = Controller.getRecommendedOverlayRect(); var recommendedRect = Controller.getRecommendedHUDRect();
var screenSize = { x: recommendedRect.width, y: recommendedRect.height }; var screenSize = { x: recommendedRect.width, y: recommendedRect.height };
if (savedFraction) { if (savedFraction) {
// If we have saved data, keep the toolbar at the same proportion of the screen width/height. // If we have saved data, keep the toolbar at the same proportion of the screen width/height.