diff --git a/modules/skybrowser/include/renderableskytarget.h b/modules/skybrowser/include/renderableskytarget.h index 1cc6972253..148e8e2a9d 100644 --- a/modules/skybrowser/include/renderableskytarget.h +++ b/modules/skybrowser/include/renderableskytarget.h @@ -50,6 +50,7 @@ public: void setRatio(float ratio); void setColor(glm::ivec3 color); void setVerticalFov(double fov); + void setBorderRadius(double radius); // Display void highlight(const glm::ivec3& addition); @@ -62,7 +63,8 @@ private: properties::FloatProperty _crossHairSize; properties::FloatProperty _showRectangleThreshold; properties::FloatProperty _lineWidth; - + + double _borderRadius = 0.0; double _verticalFov = 10.0; glm::ivec3 _borderColor = glm::ivec3(230); diff --git a/modules/skybrowser/include/targetbrowserpair.h b/modules/skybrowser/include/targetbrowserpair.h index 1dffd0b3ac..977836388a 100644 --- a/modules/skybrowser/include/targetbrowserpair.h +++ b/modules/skybrowser/include/targetbrowserpair.h @@ -77,6 +77,7 @@ public: void setVerticalFov(double vfov); void setEquatorialAim(const glm::dvec2& aim); void setBorderColor(const glm::ivec3& color); + void setBorderRadius(double radius); void setBrowserRatio(float ratio); void setVerticalFovWithScroll(float scroll); void setImageCollectionIsLoaded(bool isLoaded); diff --git a/modules/skybrowser/include/wwtcommunicator.h b/modules/skybrowser/include/wwtcommunicator.h index 7e40e116df..cc458fedd2 100644 --- a/modules/skybrowser/include/wwtcommunicator.h +++ b/modules/skybrowser/include/wwtcommunicator.h @@ -60,11 +60,13 @@ public: glm::dvec2 fieldsOfView() const; std::vector selectedImages() const; std::vector opacities() const; + double borderRadius() const; void setImageCollectionIsLoaded(bool isLoaded); void setVerticalFov(double vfov); void setEquatorialAim(glm::dvec2 equatorial); void setBorderColor(glm::ivec3 color); + void setBorderRadius(double radius); void setTargetRoll(double roll); void updateBorderColor() const; @@ -73,7 +75,8 @@ public: protected: void setIdInBrowser(const std::string& id) const; std::deque>::iterator findSelectedImage(int i); - + + double _borderRadius = 0; double _verticalFov = 10.0f; glm::ivec3 _borderColor = glm::ivec3(70); glm::dvec2 _equatorialAim = glm::dvec2(0.0); diff --git a/modules/skybrowser/shaders/target_fs.glsl b/modules/skybrowser/shaders/target_fs.glsl index 724b294588..844b68fc76 100644 --- a/modules/skybrowser/shaders/target_fs.glsl +++ b/modules/skybrowser/shaders/target_fs.glsl @@ -36,6 +36,7 @@ uniform float lineWidth; uniform float ratio; uniform vec4 lineColor; uniform float fov; +uniform float borderRadius; uniform bool additiveBlending; uniform float opacity; @@ -45,7 +46,6 @@ uniform vec3 multiplyColor; // This compensates for the optical illusion that vertical lines appear thinner const float VerticalThickness = 1.1; - float createLine(float lineCenter, float lineWidth, float coord) { // Calculate edges of line float startEdge = lineCenter - (lineWidth * 0.5); @@ -54,10 +54,6 @@ float createLine(float lineCenter, float lineWidth, float coord) { return step(startEdge, coord) - step(endEdge, coord); } -float createFilledRectangle(float width, float height, vec2 coord) { - return createLine(0.5, width, coord.x) * createLine(0.5, height, coord.y); -} - float createCrosshair(in float linewidth, in float ratio, in vec2 coord) { const float Center = 0.5; float crosshairVertical = createLine(Center, linewidth * VerticalThickness, coord.x); @@ -66,6 +62,13 @@ float createCrosshair(in float linewidth, in float ratio, in vec2 coord) { return crosshairHorizontal + crosshairVertical; } +float roundedRectangle(vec2 coord, vec2 size, vec4 radius) { + radius.xy = (coord.x > 0.0) ? radius.xy : radius.zw; + radius.x = (coord.y > 0.0) ? radius.x : radius.y; + + vec2 q = abs(coord) - size + radius.x; + return min(max(q.x, q.y),0.0) + length(max(q, 0.0)) - radius.x; +} Fragment getFragment() { float rectangle = 0.0; @@ -78,13 +81,34 @@ Fragment getFragment() { crosshair *= crossHairBox; if (showRectangle) { - float lineWidthX = lineWidth * 2 * VerticalThickness; float lineWidthY = lineWidth * 2; - float height = ((fov * 0.5)/maxWwtFov)-lineWidthX; + float lineWidthX = lineWidth * 2 * VerticalThickness; + float height = ((fov * 0.5)/maxWwtFov)-lineWidth; float width = (height * ratio) - lineWidthY; - float outerEdge = createFilledRectangle(width, height, vs_st); - float innerEdge = createFilledRectangle(width-lineWidthY, height-lineWidthX, vs_st); - rectangle = outerEdge - innerEdge; + vec2 size = vec2(width, height); + + // The radius of the corners (in pixels) clockwise starting in the top left + vec4 radius = vec4(clamp(borderRadius * 0.5 * min(height, width), 0.0, 0.5 * min(height, width))); + + // Calculate distance to edge + float distance = roundedRectangle(vs_st.xy - vec2(0.5), size / 2.0f, radius); + + // How soft the edges should be (in pixels) + // Higher values could be used to simulate a drop shadow + float edgeSoftness = 2.0f; + // Smooth the result (free antialiasing) + float smoothedAlpha = 1.0f - smoothstep(0.0f, edgeSoftness, distance); + + // Border + float borderThickness = lineWidth * 0.5; + float borderSoftness = 0.000f; + float borderAlpha = 1.0f-smoothstep(borderThickness - borderSoftness, borderThickness, abs(distance)); + + // Colors + float borderColor = 1.0; + float bgColor = 0.0; + + rectangle = mix(bgColor, mix(bgColor, borderColor, borderAlpha), smoothedAlpha); } float result = clamp(crosshair + rectangle, 0.0, 1.0); diff --git a/modules/skybrowser/skybrowsermodule.cpp b/modules/skybrowser/skybrowsermodule.cpp index 9bac48e218..8c158c4787 100644 --- a/modules/skybrowser/skybrowsermodule.cpp +++ b/modules/skybrowser/skybrowsermodule.cpp @@ -523,7 +523,8 @@ scripting::LuaLibrary SkyBrowserModule::luaLibrary() const { codegen::lua::ShowAllTargetsAndBrowsers, codegen::lua::PointSpaceCraft, codegen::lua::GetWwtImageCollectionUrl, - codegen::lua::StopAnimations + codegen::lua::StopAnimations, + codegen::lua::SetBorderRadius } }; } diff --git a/modules/skybrowser/skybrowsermodule_lua.inl b/modules/skybrowser/skybrowsermodule_lua.inl index 088dff0a33..a91f0c7cc2 100644 --- a/modules/skybrowser/skybrowsermodule_lua.inl +++ b/modules/skybrowser/skybrowsermodule_lua.inl @@ -628,6 +628,20 @@ namespace { } } +/** + * Takes an identifier to a sky browser and a radius value between 0 and 1, where 0 is + * rectangular and 1 is circular + */ +[[codegen::luawrap]] void setBorderRadius(std::string identifier, double radius) { + using namespace openspace; + + SkyBrowserModule* module = global::moduleEngine->module(); + TargetBrowserPair* pair = module->pair(identifier); + if (pair) { + pair->setBorderRadius(radius); + } +} + /** * Sets the screen space size of the sky browser to the numbers specified by the input * [x, y]. diff --git a/modules/skybrowser/src/renderableskytarget.cpp b/modules/skybrowser/src/renderableskytarget.cpp index ebfe9ab4b3..bc8413f6b6 100644 --- a/modules/skybrowser/src/renderableskytarget.cpp +++ b/modules/skybrowser/src/renderableskytarget.cpp @@ -151,6 +151,7 @@ void RenderableSkyTarget::render(const RenderData& data, RendererTasks&) { _shader->setUniform("ratio", _ratio); _shader->setUniform("lineColor", color); _shader->setUniform("fov", static_cast(_verticalFov)); + _shader->setUniform("borderRadius", static_cast(_borderRadius)); glm::dvec3 objectPositionWorld = glm::dvec3( glm::translate( @@ -231,4 +232,8 @@ void RenderableSkyTarget::setVerticalFov(double fov) { _verticalFov = fov; } +void RenderableSkyTarget::setBorderRadius(double radius) { + _borderRadius = radius; +} + } // namespace openspace diff --git a/modules/skybrowser/src/targetbrowserpair.cpp b/modules/skybrowser/src/targetbrowserpair.cpp index aa02d8766a..a0ed56d8df 100644 --- a/modules/skybrowser/src/targetbrowserpair.cpp +++ b/modules/skybrowser/src/targetbrowserpair.cpp @@ -196,6 +196,7 @@ ghoul::Dictionary TargetBrowserPair::dataAsDictionary() const { res.setValue("selectedImages", selectedImages()); res.setValue("scale", static_cast(_browser->scale())); res.setValue("opacities", _browser->opacities()); + res.setValue("borderRadius", _browser->borderRadius()); std::vector> copies = displayCopies(); std::vector> showCopies = _browser->showDisplayCopies(); @@ -278,6 +279,11 @@ void TargetBrowserPair::setBorderColor(const glm::ivec3& color) { _browser->setBorderColor(color); } +void TargetBrowserPair::setBorderRadius(double radius) { + _browser->setBorderRadius(radius); + _targetRenderable->setBorderRadius(radius); +} + void TargetBrowserPair::setBrowserRatio(float ratio) { _browser->setRatio(ratio); _targetRenderable->setRatio(ratio); diff --git a/modules/skybrowser/src/wwtcommunicator.cpp b/modules/skybrowser/src/wwtcommunicator.cpp index 05c025497e..b700ba8c12 100644 --- a/modules/skybrowser/src/wwtcommunicator.cpp +++ b/modules/skybrowser/src/wwtcommunicator.cpp @@ -94,6 +94,10 @@ std::vector WwtCommunicator::opacities() const { return opacities; } +double WwtCommunicator::borderRadius() const { + return _borderRadius; +} + void WwtCommunicator::setTargetRoll(double roll) { _targetRoll = roll; } @@ -105,7 +109,7 @@ void WwtCommunicator::setVerticalFov(double vfov) { void WwtCommunicator::setWebpageBorderColor(glm::ivec3 color) const { std::string stringColor = fmt::format("{},{},{}", color.x, color.y, color.z); - std::string scr = "document.body.style.backgroundColor = 'rgb(" + stringColor + ")';"; + std::string scr = "setBackgroundColor('rgb(" + stringColor + ")');"; executeJavascript(scr); } @@ -119,6 +123,12 @@ void WwtCommunicator::setBorderColor(glm::ivec3 color) { _borderColorIsDirty = true; } +void WwtCommunicator::setBorderRadius(double radius) { + _borderRadius = radius; + std::string scr = "setBorderRadius(" + std::to_string(radius) + ");"; + executeJavascript(scr); +} + void WwtCommunicator::updateBorderColor() const { setWebpageBorderColor(_borderColor); }