New ScreenSpaceText objects (#3794)

* First version of new screenspacetext and screenspacetextdate
* Code restructuring and adding new types
 - ScreenSpaceFramebuffer -> ScreenSpaceRenderableFramebuffer
 - ScreenSpaceText -> ScreenSpaceRenderableText
 - Add new user-facing ScreenSpaceText
 - Add examples
* Add documentation for new ScreenSpace objects
* Add visual tests to new screenspace objects
* Address PR comments
This commit is contained in:
Alexander Bock
2025-09-26 15:35:05 +02:00
committed by GitHub
parent ccadf2a53b
commit 32cff07bf8
33 changed files with 946 additions and 52 deletions

View File

@@ -1,6 +1,6 @@
-- No Decorations
-- This example adds a new DashboardItem that shows the current in-game simulation date
-- without any additional text surrounding the current date
-- without any additional text surrounding the current date.
local Item = {
Identifier = "DashboardItemDate_Example_NoDecoration",

View File

@@ -0,0 +1,16 @@
-- Basic
-- This example creates a screen space renderable that shows the current simulation time.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example",
Name = "ScreenSpace Date Example - Basic"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,18 @@
-- Day of Year
-- This example creates a screen space renderable that shows the current simulation time
-- with the current year and the number of days that have passed in the year.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_DayOfYear",
Name = "ScreenSpace Date Example - Day of Year",
TimeFormat = "YYYY DOY"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,19 @@
-- Font
-- This example creates a screen space renderable that shows the current simulation time
-- with a non-standard font. This is using one of the fonts that is loaded by default in the
-- openspace.cfg file.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_Font",
Name = "ScreenSpace Date Example - Font",
FontName = "Light"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,21 @@
-- Font Size
-- This example creates a screen space renderable that shows the current simulation time
-- with a larger font. The FontSize parameter is increased to improve the fidelity of the
-- text being rendered. The Scale parameter will make the text show up larger on the
-- screen.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_FontSize",
Name = "ScreenSpace Date Example - Font Size",
Scale = 0.5,
FontSize = 72
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,18 @@
-- No Decorations
-- This example creates a screen space renderable that shows the current simulation time
-- without any additional text surrounding the current date.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_NoDecoration",
Name = "ScreenSpace Date Example - No Decoration",
FormatString = "{}"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,18 @@
-- Timezone
-- This example creates a screen space renderable that shows the current simulation time
-- with a timezone of UTC-7 (=PDT)
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_Timezone",
Name = "ScreenSpace Date Example - Timezone",
TimeFormat = "YYYY MON DD HR:MN:SC.### PDT ::UTC-7"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,18 @@
-- Year Month Day
-- This example creates a screen space renderable that shows the current simulation time
-- with a resolution of days.
local Object = {
Type = "ScreenSpaceDate",
Identifier = "ScreenSpaceDate_Example_YearMonthDay",
Name = "ScreenSpace Date Example - Year/Month/Day",
TimeFormat = "YYYY MON DD"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -7,7 +7,7 @@ local inset = {
Type = "ScreenSpaceInsetBlackout",
Name = "ScreenSpaceInsetBlackout Example - Basic",
Blackoutshape = {
-- Must always contain four corners in the following order:
-- Must always contain four corners in the following order:
-- top-left, top-right, bottom-right, bottom-left
Corners = { {0.0, 1.0}, {1.0, 1.0}, {1.0, 0.0}, {0.0, 0.0} }
},

View File

@@ -0,0 +1,16 @@
-- Basic
-- This example creates a screen space renderable that displays a static text.
local Object = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example",
Text = "Example Text"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,19 @@
-- Basic
-- This example creates a screen space renderable that displays a static text with a
-- non-standard font. This is using one of the fonts that is loaded by default in the
-- openspace.cfg file.
local Object = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example_Font",
Text = "Example Text - Font",
FontName = "Light"
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -0,0 +1,20 @@
-- Basic
-- This example creates a screen space renderable that displays a static text with a
-- larger font. The FontSize parameter is increased to improve the fidelity of the text
-- being rendered. The Scale parameter will make the text show up larger on the screen.
local Object = {
Type = "ScreenSpaceText",
Identifier = "ScreenSpaceText_Example_FontSize",
Text = "Example Text - Font Size",
Scale = 0.5,
FontSize = 72
}
asset.onInitialize(function()
openspace.addScreenSpaceRenderable(Object)
end)
asset.onDeinitialize(function()
openspace.removeScreenSpaceRenderable(Object)
end)

View File

@@ -22,8 +22,8 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#ifndef __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__
#define __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__
#include <openspace/rendering/screenspacerenderable.h>
@@ -44,19 +44,18 @@ namespace documentation { struct Documentation; }
* an attached texture. The texture is then used on a screen space plane that works both
* in fisheye and flat screens.
*/
class ScreenSpaceFramebuffer : public ScreenSpaceRenderable {
class ScreenSpaceRenderableFramebuffer : public ScreenSpaceRenderable {
public:
using RenderFunction = std::function<void()>;
explicit ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceFramebuffer() override;
explicit ScreenSpaceRenderableFramebuffer(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceRenderableFramebuffer() override;
void initializeGL() override;
void deinitializeGL() override;
void render(const RenderData& renderData) override;
bool isReady() const override;
void setSize(glm::vec2 size);
void addRenderFunction(RenderFunction renderFunction);
void removeAllRenderFunctions();
@@ -79,4 +78,4 @@ private:
} //namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEFRAMEBUFFER___H__
#endif // __OPENSPACE_CORE___SCREENSPACEFRAMEBUFFER___H__

View File

@@ -0,0 +1,77 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___SCREENSPACERENDERABLETEXT___H__
#define __OPENSPACE_CORE___SCREENSPACERENDERABLETEXT___H__
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/properties/misc/stringproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <ghoul/font/fontrenderer.h>
namespace ghoul { class Dictionary; }
namespace ghoul::opengl {
class FramebufferObject;
class Texture;
} // namespace ghoul::opengl
namespace ghoul::fontrendering { class Font; }
namespace openspace {
namespace documentation { struct Documentation; }
class ScreenSpaceRenderableText : public ScreenSpaceRenderable {
public:
explicit ScreenSpaceRenderableText(const ghoul::Dictionary& dictionary);
void initializeGL() override;
void deinitializeGL() override;
bool isReady() const override;
void update() override;
void render(const RenderData& renderData) override;
static documentation::Documentation Documentation();
protected:
std::string _buffer;
private:
void updateFramebuffer();
void bindTexture() override;
properties::StringProperty _fontName;
properties::FloatProperty _fontSize;
std::shared_ptr<ghoul::fontrendering::Font> _font;
std::unique_ptr<ghoul::fontrendering::FontRenderer> _fontRenderer;
std::unique_ptr<ghoul::opengl::FramebufferObject> _framebuffer;
std::unique_ptr<ghoul::opengl::Texture> _texture;
};
} //namespace openspace
#endif // __OPENSPACE_CORE___SCREENSPACERENDERABLETEXT___H__

View File

@@ -71,11 +71,12 @@ set(HEADER_FILES
rendering/renderabletrailorbit.h
rendering/renderabletrailtrajectory.h
rendering/screenspacedashboard.h
rendering/screenspaceframebuffer.h
rendering/screenspacedate.h
rendering/screenspaceimagelocal.h
rendering/screenspaceimageonline.h
rendering/screenspaceinsetblackout.h
rendering/screenspacerenderablerenderable.h
rendering/screenspacetext.h
rendering/screenspacetimevaryingimageonline.h
rotation/timelinerotation.h
rotation/constantrotation.h
@@ -149,11 +150,12 @@ set(SOURCE_FILES
rendering/renderabletrailtrajectory.cpp
rendering/screenspacedashboard.cpp
rendering/screenspacedashboard_lua.inl
rendering/screenspaceframebuffer.cpp
rendering/screenspacedate.cpp
rendering/screenspaceimagelocal.cpp
rendering/screenspaceimageonline.cpp
rendering/screenspaceinsetblackout.cpp
rendering/screenspacerenderablerenderable.cpp
rendering/screenspacetext.cpp
rendering/screenspacetimevaryingimageonline.cpp
rotation/timelinerotation.cpp
rotation/constantrotation.cpp

View File

@@ -67,11 +67,12 @@
#include <modules/base/rendering/renderableprism.h>
#include <modules/base/rendering/renderabletimevaryingsphere.h>
#include <modules/base/rendering/screenspacedashboard.h>
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <modules/base/rendering/screenspaceimageonline.h>
#include <modules/base/rendering/screenspaceinsetblackout.h>
#include <modules/base/rendering/screenspacerenderablerenderable.h>
#include <modules/base/rendering/screenspacedate.h>
#include <modules/base/rendering/screenspacetext.h>
#include <modules/base/rendering/screenspacetimevaryingimageonline.h>
#include <modules/base/rotation/constantrotation.h>
#include <modules/base/rotation/fixedrotation.h>
@@ -115,7 +116,6 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
ghoul_assert(fSsRenderable, "ScreenSpaceRenderable factory was not created");
fSsRenderable->registerClass<ScreenSpaceDashboard>("ScreenSpaceDashboard");
fSsRenderable->registerClass<ScreenSpaceFramebuffer>("ScreenSpaceFramebuffer");
fSsRenderable->registerClass<ScreenSpaceImageLocal>("ScreenSpaceImageLocal");
fSsRenderable->registerClass<ScreenSpaceImageOnline>("ScreenSpaceImageOnline");
fSsRenderable->registerClass<ScreenSpaceInsetBlackout>("ScreenSpaceInsetBlackout");
@@ -125,6 +125,8 @@ void BaseModule::internalInitialize(const ghoul::Dictionary&) {
fSsRenderable->registerClass<ScreenSpaceTimeVaryingImageOnline>(
"ScreenSpaceTimeVaryingImageOnline"
);
fSsRenderable->registerClass<ScreenSpaceDate>("ScreenSpaceDate");
fSsRenderable->registerClass<ScreenSpaceText>("ScreenSpaceText");
ghoul::TemplateFactory<DashboardItem>* fDashboard =
@@ -308,11 +310,12 @@ std::vector<documentation::Documentation> BaseModule::documentations() const {
SizeMappingComponent::Documentation(),
ScreenSpaceDashboard::Documentation(),
ScreenSpaceFramebuffer::Documentation(),
ScreenSpaceDate::Documentation(),
ScreenSpaceImageLocal::Documentation(),
ScreenSpaceImageOnline::Documentation(),
ScreenSpaceInsetBlackout::Documentation(),
ScreenSpaceRenderableRenderable::Documentation(),
ScreenSpaceText::Documentation(),
ScreenSpaceTimeVaryingImageOnline::Documentation(),
ConstantRotation::Documentation(),

View File

@@ -69,7 +69,7 @@ documentation::Documentation ScreenSpaceDashboard::Documentation() {
}
ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
: ScreenSpaceFramebuffer(dictionary)
: ScreenSpaceRenderableFramebuffer(dictionary)
, _useMainDashboard(UseMainInfo, false)
{
const Parameters p = codegen::bake<Parameters>(dictionary);
@@ -98,7 +98,7 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
}
void ScreenSpaceDashboard::initializeGL() {
ScreenSpaceFramebuffer::initializeGL();
ScreenSpaceRenderableFramebuffer::initializeGL();
addRenderFunction([this]() {
glm::vec2 penPosition = glm::vec2(0.f, _size.value().x);

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEDASHBOARD___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEDASHBOARD___H__
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <openspace/rendering/screenspacerenderableframebuffer.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/rendering/dashboard.h>
@@ -40,7 +40,7 @@ namespace openspace {
namespace documentation { struct Documentation; }
namespace scripting { struct LuaLibrary; }
class ScreenSpaceDashboard : public ScreenSpaceFramebuffer {
class ScreenSpaceDashboard : public ScreenSpaceRenderableFramebuffer {
public:
explicit ScreenSpaceDashboard(const ghoul::Dictionary& dictionary);
virtual ~ScreenSpaceDashboard() override = default;

View File

@@ -0,0 +1,108 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspacedate.h>
#include <openspace/util/spicemanager.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
namespace {
constexpr openspace::properties::Property::PropertyInfo FormatStringInfo = {
"FormatString",
"Format string",
"The format text describing how this dashboard item renders its text. This text "
"must contain exactly one {} which is a placeholder that will contain the date "
"in the format as specified by `TimeFormat`.",
openspace::properties::Property::Visibility::AdvancedUser
};
constexpr openspace::properties::Property::PropertyInfo TimeFormatInfo = {
"TimeFormat",
"Time format",
"The format string used for formatting the date/time before being passed to the "
"string in FormatString. See "
"https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html for full "
"information about how to structure this format.",
openspace::properties::Property::Visibility::User
};
// This `ScreenSpaceRenderable` shows the current in-game simulation time. The
// `FormatString` and the `TimeFormat` options provide the ability to customize the
// output that is printed. See these two parameters for more information on how to
// structure the inputs.
struct [[codegen::Dictionary(ScreenSpaceTextDate)]] Parameters {
// [[codegen::verbatim(FormatStringInfo.description)]]
std::optional<std::string> formatString;
// [[codegen::verbatim(TimeFormatInfo.description)]]
std::optional<std::string> timeFormat;
};
#include "screenspacedate_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceDate::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_date",
ScreenSpaceRenderableText::Documentation()
);
}
ScreenSpaceDate::ScreenSpaceDate(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderableText(dictionary)
, _formatString(FormatStringInfo, "Date: {}")
, _timeFormat(TimeFormatInfo, "YYYY MON DD HR:MN:SC.### UTC ::RND")
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_formatString = p.formatString.value_or(_formatString);
addProperty(_formatString);
_timeFormat = p.timeFormat.value_or(_timeFormat);
addProperty(_timeFormat);
}
void ScreenSpaceDate::update() {
std::string time = SpiceManager::ref().dateFromEphemerisTime(
global::timeManager->time().j2000Seconds(),
_timeFormat.value().c_str()
);
try {
// @CPP26(abock): This can be replaced with std::runtime_format
_buffer = std::vformat(_formatString.value(), std::make_format_args(time));
}
catch (const std::format_error&) {
LERRORC("ScreenSpaceDate", "Illegal format string");
}
ScreenSpaceRenderableText::update();
}
} // namespace openspace

View File

@@ -0,0 +1,49 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACEDATE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACEDATE___H__
#include <openspace/rendering/screenspacerenderabletext.h>
#include <openspace/properties/misc/stringproperty.h>
namespace openspace {
class ScreenSpaceDate : public ScreenSpaceRenderableText {
public:
explicit ScreenSpaceDate(const ghoul::Dictionary& dictionary);
void update() override;
static documentation::Documentation Documentation();
private:
properties::StringProperty _formatString;
properties::StringProperty _timeFormat;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACEDATE___H__

View File

@@ -143,13 +143,13 @@ namespace openspace {
documentation::Documentation ScreenSpaceRenderableRenderable::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_renderable",
ScreenSpaceFramebuffer::Documentation()
ScreenSpaceRenderableFramebuffer::Documentation()
);
}
ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable(
const ghoul::Dictionary& dictionary)
: ScreenSpaceFramebuffer(dictionary)
: ScreenSpaceRenderableFramebuffer(dictionary)
, _time(
TimeInfo,
0.0,
@@ -232,7 +232,7 @@ ScreenSpaceRenderableRenderable::ScreenSpaceRenderableRenderable(
ScreenSpaceRenderableRenderable::~ScreenSpaceRenderableRenderable() {}
void ScreenSpaceRenderableRenderable::initialize() {
ScreenSpaceFramebuffer::initialize();
ScreenSpaceRenderableFramebuffer::initialize();
_transform.translation->initialize();
_transform.rotation->initialize();
_transform.scale->initialize();
@@ -240,7 +240,7 @@ void ScreenSpaceRenderableRenderable::initialize() {
}
void ScreenSpaceRenderableRenderable::initializeGL() {
ScreenSpaceFramebuffer::initializeGL();
ScreenSpaceRenderableFramebuffer::initializeGL();
_renderable->initializeGL();
@@ -288,7 +288,7 @@ void ScreenSpaceRenderableRenderable::deinitializeGL() {
_renderable->deinitializeGL();
_renderable->deinitialize();
ScreenSpaceFramebuffer::deinitializeGL();
ScreenSpaceRenderableFramebuffer::deinitializeGL();
}
void ScreenSpaceRenderableRenderable::update() {

View File

@@ -25,7 +25,7 @@
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACERENDERABLERENDERABLE___H__
#include <modules/base//rendering/screenspaceframebuffer.h>
#include <openspace/rendering/screenspacerenderableframebuffer.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
@@ -43,7 +43,7 @@ class Translation;
namespace documentation { struct Documentation; }
class ScreenSpaceRenderableRenderable : public ScreenSpaceFramebuffer {
class ScreenSpaceRenderableRenderable : public ScreenSpaceRenderableFramebuffer {
public:
using RenderFunction = std::function<void()>;

View File

@@ -0,0 +1,71 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspacetext.h>
#include <ghoul/opengl/framebufferobject.h>
#include <ghoul/opengl/texture.h>
namespace {
constexpr openspace::properties::Property::PropertyInfo TextInfo = {
"Text",
"Text",
"The text to be displayed.",
openspace::properties::Property::Visibility::User
};
// This `ScreenSpaceRenderable` shows a static text that can be changed via a
// property.
struct [[codegen::Dictionary(DashboardItemText)]] Parameters {
// [[codegen::verbatim(TextInfo.description)]]
std::optional<std::string> text;
};
#include "screenspacetext_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceText::Documentation() {
return codegen::doc<Parameters>(
"base_screenspace_text",
ScreenSpaceRenderableText::Documentation()
);
}
ScreenSpaceText::ScreenSpaceText(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderableText(dictionary)
, _text(TextInfo, "")
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_text = p.text.value_or(_text);
addProperty(_text);
}
void ScreenSpaceText::update() {
_buffer = _text.value();
ScreenSpaceRenderableText::update();
}
} // namespace openspace

View File

@@ -0,0 +1,48 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_MODULE_BASE___SCREENSPACETEXT___H__
#define __OPENSPACE_MODULE_BASE___SCREENSPACETEXT___H__
#include <openspace/rendering/screenspacerenderabletext.h>
#include <openspace/properties/misc/stringproperty.h>
namespace openspace {
class ScreenSpaceText : public ScreenSpaceRenderableText {
public:
explicit ScreenSpaceText(const ghoul::Dictionary& dictionary);
void update() override;
static documentation::Documentation Documentation();
private:
properties::StringProperty _text;
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_BASE___SCREENSPACETEXT___H__

View File

@@ -142,7 +142,9 @@ set(OPENSPACE_SOURCE
rendering/renderable.cpp
rendering/renderengine.cpp
rendering/renderengine_lua.inl
rendering/screenspacerenderableframebuffer.cpp
rendering/screenspacerenderable.cpp
rendering/screenspacerenderabletext.cpp
rendering/texturecomponent.cpp
rendering/transferfunction.cpp
rendering/volumeraycaster.cpp
@@ -339,7 +341,9 @@ set(OPENSPACE_HEADER
${PROJECT_SOURCE_DIR}/include/openspace/rendering/raycastermanager.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/renderable.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/renderengine.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/screenspacerenderableframebuffer.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/screenspacerenderable.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/screenspacerenderabletext.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/texturecomponent.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/transferfunction.h
${PROJECT_SOURCE_DIR}/include/openspace/rendering/volumeraycaster.h

View File

@@ -22,7 +22,7 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/base/rendering/screenspaceframebuffer.h>
#include <openspace/rendering/screenspacerenderableframebuffer.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
@@ -43,17 +43,16 @@ namespace {
namespace openspace {
documentation::Documentation ScreenSpaceFramebuffer::Documentation() {
documentation::Documentation ScreenSpaceRenderableFramebuffer::Documentation() {
using namespace documentation;
return {
"ScreenSpaceFramebuffer",
"base_screenspace_framebuffer",
"",
{}
"ScreenSpaceRenderableFramebuffer",
"screenspace_framebuffer"
};
}
ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictionary)
ScreenSpaceRenderableFramebuffer::ScreenSpaceRenderableFramebuffer(
const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _size(SizeInfo, glm::vec2(16), glm::vec2(16), glm::vec2(16384))
{
@@ -63,15 +62,14 @@ ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictiona
"ScreenSpaceFramebuffer"
);
int iIdentifier = 0;
if (_identifier.empty()) {
iIdentifier = id();
int idCounter = id();
if (iIdentifier == 0) {
setIdentifier("ScreenSpaceFramebuffer");
if (idCounter == 0) {
setIdentifier("ScreenSpaceRenderableFramebuffer");
}
else {
setIdentifier("ScreenSpaceFramebuffer" + std::to_string(iIdentifier));
setIdentifier(std::format("ScreenSpaceRenderableFramebuffer{}", idCounter));
}
}
@@ -79,24 +77,24 @@ ScreenSpaceFramebuffer::ScreenSpaceFramebuffer(const ghoul::Dictionary& dictiona
addProperty(_size);
}
ScreenSpaceFramebuffer::~ScreenSpaceFramebuffer() {}
ScreenSpaceRenderableFramebuffer::~ScreenSpaceRenderableFramebuffer() {}
void ScreenSpaceFramebuffer::initializeGL() {
void ScreenSpaceRenderableFramebuffer::initializeGL() {
ScreenSpaceRenderable::initializeGL();
createFramebuffer();
}
void ScreenSpaceFramebuffer::deinitializeGL() {
void ScreenSpaceRenderableFramebuffer::deinitializeGL() {
_framebuffer->activate();
_framebuffer->detachAll();
ghoul::opengl::FramebufferObject::deactivate();
removeAllRenderFunctions();
ScreenSpaceRenderable::deinitializeGL();
ScreenSpaceRenderableFramebuffer::deinitializeGL();
}
void ScreenSpaceFramebuffer::render(const RenderData& renderData) {
void ScreenSpaceRenderableFramebuffer::render(const RenderData& renderData) {
const glm::vec2& resolution = global::windowDelegate->currentDrawBufferResolution();
const glm::vec2& size = _size.value();
const glm::vec2 ratio = resolution / size;
@@ -131,23 +129,19 @@ void ScreenSpaceFramebuffer::render(const RenderData& renderData) {
}
}
bool ScreenSpaceFramebuffer::isReady() const {
bool ScreenSpaceRenderableFramebuffer::isReady() const {
return _shader && _texture;
}
void ScreenSpaceFramebuffer::setSize(glm::vec2 size) {
_size = std::move(size);
}
void ScreenSpaceFramebuffer::addRenderFunction(RenderFunction renderFunction) {
void ScreenSpaceRenderableFramebuffer::addRenderFunction(RenderFunction renderFunction) {
_renderFunctions.push_back(std::move(renderFunction));
}
void ScreenSpaceFramebuffer::removeAllRenderFunctions() {
void ScreenSpaceRenderableFramebuffer::removeAllRenderFunctions() {
_renderFunctions.clear();
}
void ScreenSpaceFramebuffer::createFramebuffer() {
void ScreenSpaceRenderableFramebuffer::createFramebuffer() {
const glm::vec2 resolution = global::windowDelegate->currentDrawBufferResolution();
_framebuffer = std::make_unique<ghoul::opengl::FramebufferObject>();
@@ -165,12 +159,12 @@ void ScreenSpaceFramebuffer::createFramebuffer() {
ghoul::opengl::FramebufferObject::deactivate();
}
int ScreenSpaceFramebuffer::id() {
int ScreenSpaceRenderableFramebuffer::id() {
static int id = 0;
return id++;
}
void ScreenSpaceFramebuffer::bindTexture() {
void ScreenSpaceRenderableFramebuffer::bindTexture() {
_texture->bind();
}

View File

@@ -0,0 +1,180 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2025 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/rendering/screenspacerenderabletext.h>
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <ghoul/font/font.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
#include <ghoul/opengl/framebufferobject.h>
#include <optional>
namespace {
constexpr openspace::properties::Property::PropertyInfo FontNameInfo = {
"FontName",
"Font name",
"This value is the name of the font that is used. It can either refer to an "
"internal name registered previously, or it can refer to a path that is used.",
openspace::properties::Property::Visibility::User
};
constexpr openspace::properties::Property::PropertyInfo FontSizeInfo = {
"FontSize",
"Font size",
"This value determines the size of the font that is used to render the distance.",
openspace::properties::Property::Visibility::User
};
struct [[codegen::Dictionary(DashboardTextItem)]] Parameters {
// [[codegen::verbatim(FontNameInfo.description)]]
std::optional<std::string> fontName;
// [[codegen::verbatim(FontSizeInfo.description)]]
std::optional<float> fontSize;
};
#include "screenspacerenderabletext_codegen.cpp"
} // namespace
namespace openspace {
documentation::Documentation ScreenSpaceRenderableText::Documentation() {
return codegen::doc<Parameters>("screenspace_text");
}
ScreenSpaceRenderableText::ScreenSpaceRenderableText(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, _fontName(FontNameInfo, "Mono")
, _fontSize(FontSizeInfo, 15.f, 6.f, 144.f, 1.f)
, _fontRenderer(ghoul::fontrendering::FontRenderer::createDefault())
{
const Parameters p = codegen::bake<Parameters>(dictionary);
_fontName = p.fontName.value_or(_fontName);
_fontName.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontName);
_fontSize = p.fontSize.value_or(_fontSize);
_fontSize.onChange([this]() {
_font = global::fontManager->font(_fontName, _fontSize);
});
addProperty(_fontSize);
_font = global::fontManager->font(_fontName, _fontSize);
}
void ScreenSpaceRenderableText::initializeGL() {
ScreenSpaceRenderable::initializeGL();
_framebuffer = std::make_unique<ghoul::opengl::FramebufferObject>();
}
void ScreenSpaceRenderableText::deinitializeGL() {
_framebuffer->activate();
_framebuffer->detachAll();
ghoul::opengl::FramebufferObject::deactivate();
_texture = nullptr;
ScreenSpaceRenderable::deinitializeGL();
}
bool ScreenSpaceRenderableText::isReady() const {
return _shader && _font && _texture;
}
void ScreenSpaceRenderableText::update() {
updateFramebuffer();
}
void ScreenSpaceRenderableText::render(const RenderData& renderData) {
const glm::vec2& resolution = global::windowDelegate->currentDrawBufferResolution();
glm::vec2 size = _texture->dimensions();
const glm::vec2 ratio = resolution / size;
std::array<GLint, 4> viewport;
glGetIntegerv(GL_VIEWPORT, viewport.data());
glViewport(
0,
0,
static_cast<GLint>(size.x),
static_cast<GLint>(size.y)
);
const GLint defaultFBO = ghoul::opengl::FramebufferObject::getActiveObject();
_framebuffer->activate();
glClearColor(0.f, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::vec2 pos = glm::vec2(0.f, size.y / 4);
_fontRenderer->render(*_font, pos, _buffer);
ghoul::opengl::FramebufferObject::deactivate();
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
const glm::mat4 globalRotation = globalRotationMatrix();
const glm::mat4 translation = translationMatrix();
const glm::mat4 localRotation = localRotationMatrix();
const glm::mat4 scale = scaleMatrix();
const glm::mat4 modelTransform = globalRotation * translation * localRotation * scale;
draw(modelTransform, renderData);
}
void ScreenSpaceRenderableText::updateFramebuffer() {
const glm::vec2 bbox = _font->boundingBox(_buffer);
const glm::uvec3 box = glm::uvec3(bbox.x, bbox.y, 1);
const glm::uvec3 dim = _texture ? _texture->dimensions() : glm::uvec3(0);
if (box.x <= dim.x || box.y <= dim.y) {
// The size has not changed
return;
}
_objectSize = glm::ivec2(bbox.x, bbox.y);
_fontRenderer->setFramebufferSize(_objectSize);
_framebuffer->activate();
// Create a texture that has 2 times the size to create a buffer
_texture = std::make_unique<ghoul::opengl::Texture>(
glm::uvec3(bbox.x, bbox.y, 1),
GL_TEXTURE_2D
);
_texture->uploadTexture();
_texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
_texture->purgeFromRAM();
_framebuffer->attachTexture(_texture.get(), GL_COLOR_ATTACHMENT0);
ghoul::opengl::FramebufferObject::deactivate();
}
void ScreenSpaceRenderableText::bindTexture() {
_texture->bind();
}
} //namespace openspace

View File

@@ -0,0 +1,30 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacedate/date.asset"
},
{
"type": "time",
"value": "2025-09-13T02:03:04.567"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example.FontSize",
"value": 25.0
}
},
{
"type": "screenshot"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacedate/date_day-of-year.asset"
},
{
"type": "time",
"value": "2025-09-13T02:03:04.567"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_DayOfYear.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_DayOfYear.FontSize",
"value": 25.0
}
},
{
"type": "screenshot"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacedate/date_no-decoration.asset"
},
{
"type": "time",
"value": "2025-09-13T02:03:04.567"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_NoDecoration.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_NoDecoration.FontSize",
"value": 25.0
}
},
{
"type": "screenshot"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacedate/date_timezone.asset"
},
{
"type": "time",
"value": "2025-09-13T02:03:04.567"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_Timezone.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_Timezone.FontSize",
"value": 25.0
}
},
{
"type": "screenshot"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacedate/date_year-month-day.asset"
},
{
"type": "time",
"value": "2025-09-13T02:03:04.567"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_YearMonthDay.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceDate_Example_YearMonthDay.FontSize",
"value": 25.0
}
},
{
"type": "screenshot"
}
]
}

View File

@@ -0,0 +1,26 @@
{
"profile": "empty",
"commands": [
{
"type": "asset",
"value": "examples/screenspacerenderable/screenspacetext/text.asset"
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceText_Example.Scale",
"value": 0.75
}
},
{
"type": "property",
"value": {
"property": "ScreenSpace.ScreenSpaceText_Example.FontSize",
"value": 55.0
}
},
{
"type": "screenshot"
}
]
}