diff --git a/modules/base/rendering/pointcloud/renderablepointcloud.cpp b/modules/base/rendering/pointcloud/renderablepointcloud.cpp index bd83bc3044..a83f9fd6fd 100644 --- a/modules/base/rendering/pointcloud/renderablepointcloud.cpp +++ b/modules/base/rendering/pointcloud/renderablepointcloud.cpp @@ -55,14 +55,14 @@ namespace { constexpr std::string_view _loggerCat = "RenderablePointCloud"; - constexpr std::array UniformNames = { + constexpr std::array UniformNames = { "cameraViewMatrix", "projectionMatrix", "modelMatrix", "cameraPosition", "cameraLookUp", "renderOption", "maxAngularSize", "color", "opacity", "scaleExponent", "scaleFactor", "up", "right", "fadeInValue", "hasSpriteTexture", "spriteTexture", "useColorMap", "colorMapTexture", "cmapRangeMin", "cmapRangeMax", "nanColor", "useNanColor", "hideOutsideRange", "enableMaxSizeControl", "aboveRangeColor", "useAboveRangeColor", "belowRangeColor", "useBelowRangeColor", - "hasDvarScaling" + "hasDvarScaling", "enableOutline", "outlineColor", "outlineWeight" }; enum RenderOption { @@ -229,6 +229,30 @@ namespace { openspace::properties::Property::Visibility::AdvancedUser }; + constexpr openspace::properties::Property::PropertyInfo EnableOutlineInfo = { + "EnableOutline", + "Enable Point Outline", + "This setting determines if each point should have an outline or not. An outline " + "is only applied when rendering as colored points (not when using textures).", + openspace::properties::Property::Visibility::User + }; + + constexpr openspace::properties::Property::PropertyInfo OutlineColorInfo = { + "OutlineColor", + "Outline Color", + "This value defines the color of the outline. Darker colors will be " + "less visible if Additive Blending is enabled.", + openspace::properties::Property::Visibility::User + }; + + constexpr openspace::properties::Property::PropertyInfo OutlineWeightInfo = { + "OutlineWeight", + "Outline Weight", + "This setting determines the thickness of the outline. A value of 0 will " + "not show any outline, while a value of 1 will cover the whole point.", + openspace::properties::Property::Visibility::AdvancedUser + }; + // A RenderablePointCloud can be used to render point-based datasets in 3D space, // optionally including color mapping, a sprite texture and labels. There are several // properties that affect the visuals of the points, such as settings for scaling, @@ -336,6 +360,15 @@ namespace { // Settings related to the choice of color map, parameters, etc. std::optional colorMapping [[codegen::reference("colormappingcomponent")]]; + + // [[codegen::verbatim(EnableOutlineInfo.description)]] + std::optional enableOutline; + + // [[codegen::verbatim(OutlineColorInfo.description)]] + std::optional outlineColor; + + // [[codegen::verbatim(OutlineColorInfo.description)]] + std::optional outlineWeight; }; // Settings related to the coloring of the points, such as a fixed color, // color map, etc. @@ -419,10 +452,14 @@ RenderablePointCloud::SizeSettings::SizeMapping::SizeMapping() RenderablePointCloud::ColorSettings::ColorSettings(const ghoul::Dictionary& dictionary) : properties::PropertyOwner({ "Coloring", "Coloring", "" }) , pointColor(PointColorInfo, glm::vec3(1.f), glm::vec3(0.f), glm::vec3(1.f)) + , enableOutline(EnableOutlineInfo, false) + , outlineColor(OutlineColorInfo, glm::vec3(0.23f), glm::vec3(0.f), glm::vec3(1.f)) + , outlineWeight(OutlineWeightInfo, 0.2f, 0.f, 1.f) { const Parameters p = codegen::bake(dictionary); - if (p.coloring.has_value()) { + const bool hasColoring = p.coloring.has_value(); + if (hasColoring) { const Parameters::ColorSettings settings = *p.coloring; pointColor = settings.fixedColor.value_or(pointColor); @@ -435,6 +472,17 @@ RenderablePointCloud::ColorSettings::ColorSettings(const ghoul::Dictionary& dict } pointColor.setViewOption(properties::Property::ViewOptions::Color); addProperty(pointColor); + + enableOutline = p.coloring->enableOutline.value_or(enableOutline); + addProperty(enableOutline); + + outlineColor.setViewOption(properties::Property::ViewOptions::Color); + outlineColor = p.coloring->outlineColor.value_or(outlineColor); + addProperty(outlineColor); + + outlineWeight = p.coloring->outlineWeight.value_or(outlineWeight); + addProperty(outlineWeight); + } RenderablePointCloud::Fading::Fading(const ghoul::Dictionary& dictionary) @@ -735,6 +783,9 @@ void RenderablePointCloud::bindDataForPointRendering() { } _program->setUniform(_uniformCache.color, _colorSettings.pointColor); + _program->setUniform(_uniformCache.enableOutline, _colorSettings.enableOutline); + _program->setUniform(_uniformCache.outlineColor, _colorSettings.outlineColor); + _program->setUniform(_uniformCache.outlineWeight, _colorSettings.outlineWeight); bool useColorMap = _hasColorMapFile && _colorSettings.colorMapping->enabled && _colorSettings.colorMapping->texture(); diff --git a/modules/base/rendering/pointcloud/renderablepointcloud.h b/modules/base/rendering/pointcloud/renderablepointcloud.h index a14062461c..c1ec0b0be5 100644 --- a/modules/base/rendering/pointcloud/renderablepointcloud.h +++ b/modules/base/rendering/pointcloud/renderablepointcloud.h @@ -132,6 +132,9 @@ protected: explicit ColorSettings(const ghoul::Dictionary& dictionary); properties::Vec3Property pointColor; std::unique_ptr colorMapping; + properties::BoolProperty enableOutline; + properties::Vec3Property outlineColor; + properties::FloatProperty outlineWeight; }; ColorSettings _colorSettings; @@ -162,7 +165,7 @@ protected: right, fadeInValue, hasSpriteTexture, spriteTexture, useColormap, colorMapTexture, cmapRangeMin, cmapRangeMax, nanColor, useNanColor, hideOutsideRange, enableMaxSizeControl, aboveRangeColor, useAboveRangeColor, belowRangeColor, - useBelowRangeColor, hasDvarScaling + useBelowRangeColor, hasDvarScaling, enableOutline, outlineColor, outlineWeight ) _uniformCache; std::string _dataFile; diff --git a/modules/base/shaders/pointcloud/billboardpoint_fs.glsl b/modules/base/shaders/pointcloud/billboardpoint_fs.glsl index a117d53e6b..629d1ff7a3 100644 --- a/modules/base/shaders/pointcloud/billboardpoint_fs.glsl +++ b/modules/base/shaders/pointcloud/billboardpoint_fs.glsl @@ -49,6 +49,9 @@ uniform sampler1D colorMapTexture; uniform float cmapRangeMin; uniform float cmapRangeMax; uniform bool hideOutsideRange; +uniform bool enableOutline; +uniform vec3 outlineColor; +uniform float outlineWeight; uniform float fadeInValue; @@ -80,24 +83,26 @@ Fragment getFragment() { discard; } - if (!hasSpriteTexture) { - // Moving the origin to the center - vec2 st = (texCoord - vec2(0.5)) * 2.0; - if (length(st) > 1.0) { + // Moving the origin to the center and calculating the length + float lengthFromCenter = length((texCoord - vec2(0.5)) * 2.0); + if (!hasSpriteTexture) { + if (lengthFromCenter > 1.0) { discard; } } vec4 fullColor = vec4(1.0); - if (hasSpriteTexture) { - fullColor = texture(spriteTexture, texCoord); - } - if (useColorMap) { - fullColor *= sampleColorMap(gs_colorParameter); + fullColor = sampleColorMap(gs_colorParameter); } else { - fullColor.rgb *= color; + fullColor.rgb = color; + } + + if (hasSpriteTexture) { + fullColor *= texture(spriteTexture, texCoord); + } else if (enableOutline && (lengthFromCenter > (1.0 - outlineWeight))) { + fullColor.rgb = outlineColor; } fullColor.a *= opacity * fadeInValue;