Skip to content

Commit

Permalink
Implement HighDPI support for 3D UI elements (#1001)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamkewley committed Feb 11, 2025
1 parent 30a432c commit bdc268b
Show file tree
Hide file tree
Showing 39 changed files with 166 additions and 74 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Upcoming Release]

- HighDPI support has now been rolled out to 3D UI elements (previously, it was
only rolled out to 2D UI elements - #950), #1001.
- A new configuration option, `graphics.render_scale`, can now be set in
`osc.toml`. This configuration option can be used to upscale/downscale
3D UI elements by a scale factor, e.g. to combine a HighDPI 2D UI with
LowDPI 3D viewports (#1001).
- `oscar_demos` are no longer bundled with the application by default, to reduce
the size of the installer (most users don't use the demos).
- Internal: Updated internal opensim-core to include the upstream change to
Expand Down
3 changes: 2 additions & 1 deletion hellooscar/hellooscar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ namespace

// ensure target texture matches screen dimensions
target_texture_.reformat({
.dimensions = App::get().main_window_dimensions(),
.dimensions = App::get().main_window_pixel_dimensions(),
.device_pixel_ratio = App::get().main_window_device_pixel_ratio(),
.anti_aliasing_level = App::get().anti_aliasing_level()
});

Expand Down
4 changes: 4 additions & 0 deletions libopensimcreator/Graphics/CachedModelRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class osc::CachedModelRenderer::Impl final {
const IModelStatePair& modelState,
const ModelRendererParams& renderParams,
Vec2 dims,
float devicePixelRatio,
AntiAliasingLevel antiAliasingLevel)
{
OSC_PERF("CachedModelRenderer/on_draw");
Expand All @@ -137,6 +138,7 @@ class osc::CachedModelRenderer::Impl final {
const SceneRendererParams rendererParameters = CalcSceneRendererParams(
renderParams,
dims,
devicePixelRatio,
antiAliasingLevel,
modelState.getFixupScaleFactor()
);
Expand Down Expand Up @@ -201,12 +203,14 @@ RenderTexture& osc::CachedModelRenderer::onDraw(
const IModelStatePair& modelState,
const ModelRendererParams& renderParams,
Vec2 dims,
float devicePixelRatio,
AntiAliasingLevel antiAliasingLevel)
{
return m_Impl->onDraw(
modelState,
renderParams,
dims,
devicePixelRatio,
antiAliasingLevel
);
}
Expand Down
1 change: 1 addition & 0 deletions libopensimcreator/Graphics/CachedModelRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace osc
const IModelStatePair&,
const ModelRendererParams&,
Vec2 dims,
float devicePixelRatio,
AntiAliasingLevel antiAliasingLevel
);
RenderTexture& updRenderTexture();
Expand Down
5 changes: 3 additions & 2 deletions libopensimcreator/Graphics/OpenSimGraphicsHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ using namespace osc;
SceneRendererParams osc::CalcSceneRendererParams(
const ModelRendererParams& renderParams,
Vec2 viewportDims,
float viewportDevicePixelRatio,
AntiAliasingLevel antiAliasingLevel,
float fixupScaleFactor)
{
SceneRendererParams rv;

if (viewportDims.x >= 1.0f && viewportDims.y >= 1.0f) {
rv.dimensions = viewportDims;
rv.virtual_pixel_dimensions = viewportDims;
}

rv.device_pixel_ratio = viewportDevicePixelRatio;
rv.antialiasing_level = antiAliasingLevel;
rv.light_direction = recommended_light_direction(renderParams.camera);
renderParams.renderingOptions.applyTo(rv);
Expand Down
1 change: 1 addition & 0 deletions libopensimcreator/Graphics/OpenSimGraphicsHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace osc
SceneRendererParams CalcSceneRendererParams(
const ModelRendererParams&,
Vec2 viewportDims,
float viewportDevicePixelRatio,
AntiAliasingLevel,
float fixupScaleFactor
);
Expand Down
3 changes: 2 additions & 1 deletion libopensimcreator/Platform/OpenSimCreatorApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,9 @@ namespace
void InitializeOpenSimCreatorSpecificSettingDefaults(AppSettings& settings)
{
for (const auto& [setting_id, default_state] : c_default_panel_states) {
settings.set_value(setting_id, default_state, AppSettingScope::System);
settings.set_value_if_not_found(setting_id, default_state, AppSettingScope::System);
}
settings.set_value_if_not_found("graphics/render_scale", Variant{1.0f}, AppSettingScope::System);
}
}

Expand Down
10 changes: 7 additions & 3 deletions libopensimcreator/UI/MeshImporter/MeshImporterSharedState.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <liboscar/Maths/Vec2.h>
#include <liboscar/Maths/Vec3.h>
#include <liboscar/Platform/App.h>
#include <liboscar/Platform/AppSettings.h>
#include <liboscar/Platform/IconCodepoints.h>
#include <liboscar/Platform/Log.h>
#include <liboscar/Platform/os.h>
Expand Down Expand Up @@ -382,16 +383,19 @@ namespace osc::mi

void drawScene(std::span<const DrawableThing> drawables)
{
const App& app = App::get();

// setup rendering params
SceneRendererParams p;
p.dimensions = dimensions_of(get3DSceneRect());
p.antialiasing_level = App::get().anti_aliasing_level();
p.virtual_pixel_dimensions = dimensions_of(get3DSceneRect());
p.device_pixel_ratio = app.settings().get_value<float>("graphics/render_scale", 1.0f) * app.main_window_device_pixel_ratio();
p.antialiasing_level = app.anti_aliasing_level();
p.draw_rims = true;
p.draw_floor = false;
p.near_clipping_plane = m_3DSceneCamera.znear;
p.far_clipping_plane = m_3DSceneCamera.zfar;
p.view_matrix = m_3DSceneCamera.view_matrix();
p.projection_matrix = m_3DSceneCamera.projection_matrix(aspect_ratio_of(p.dimensions));
p.projection_matrix = m_3DSceneCamera.projection_matrix(aspect_ratio_of(p.virtual_pixel_dimensions));
p.view_pos = m_3DSceneCamera.position();
p.light_direction = recommended_light_direction(m_3DSceneCamera);
p.light_color = Color::white();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <liboscar/Maths/Vec3.h>
#include <liboscar/Maths/Vec4.h>
#include <liboscar/Platform/App.h>
#include <liboscar/Platform/AppSettings.h>
#include <liboscar/Platform/IconCodepoints.h>
#include <liboscar/UI/oscimgui.h>
#include <liboscar/Utils/CStringView.h>
Expand Down Expand Up @@ -210,7 +211,8 @@ namespace osc
SceneRendererParams params = calc_standard_dark_scene_render_params(
m_Camera,
App::get().anti_aliasing_level(),
dims
dims,
App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio()
);
m_State->getCustomRenderingOptions().applyTo(params);
const std::vector<SceneDecoration> decorations = generateDecorations(maybeMeshCollision, maybeLandmarkCollision);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,8 @@ namespace osc
SceneRendererParams params = calc_standard_dark_scene_render_params(
m_Camera,
App::get().anti_aliasing_level(),
dims
dims,
App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio()
);
m_State->getCustomRenderingOptions().applyTo(params);
return m_CachedRenderer.render(decorations, params);
Expand Down
2 changes: 2 additions & 0 deletions libopensimcreator/UI/RendererPerfTestingTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <liboscar/Maths/RectFunctions.h>
#include <liboscar/Maths/Vec2.h>
#include <liboscar/Platform/App.h>
#include <liboscar/Platform/AppSettings.h>
#include <liboscar/UI/oscimgui.h>
#include <liboscar/UI/Tabs/TabPrivate.h>
#include <liboscar/Utils/CStringView.h>
Expand Down Expand Up @@ -85,6 +86,7 @@ class osc::RendererPerfTestingTab::Impl final : public TabPrivate {
const SceneRendererParams params = CalcSceneRendererParams(
m_ModelRendererParams,
dimensions_of(viewportRect),
App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio(),
App::get().anti_aliasing_level(),
1.0f
);
Expand Down
2 changes: 2 additions & 0 deletions libopensimcreator/UI/Shared/ChooseComponentsEditorLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <liboscar/Maths/RectFunctions.h>
#include <liboscar/Maths/Vec2.h>
#include <liboscar/Platform/App.h>
#include <liboscar/Platform/AppSettings.h>
#include <liboscar/Platform/IconCodepoints.h>
#include <liboscar/UI/oscimgui.h>
#include <liboscar/Utils/CStringView.h>
Expand Down Expand Up @@ -190,6 +191,7 @@ class osc::ChooseComponentsEditorLayer::Impl final {
const SceneRendererParams rendererParameters = CalcSceneRendererParams(
m_State.renderParams,
dimensions_of(panelState.viewportRect),
App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio(),
App::get().anti_aliasing_level(),
m_State.model->getFixupScaleFactor()
);
Expand Down
2 changes: 2 additions & 0 deletions libopensimcreator/UI/Shared/ModelViewerPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <liboscar/Maths/RectFunctions.h>
#include <liboscar/Maths/Vec3.h>
#include <liboscar/Platform/App.h>
#include <liboscar/Platform/AppSettings.h>
#include <liboscar/Platform/Log.h>
#include <liboscar/UI/IconCache.h>
#include <liboscar/UI/oscimgui.h>
Expand Down Expand Up @@ -424,6 +425,7 @@ class osc::ModelViewerPanel::Impl final : public PanelPrivate {
*m_Parameters.getModelSharedPtr(),
m_Parameters.getRenderParams(),
dimensions_of(m_State.viewportRect),
App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio(),
App::get().anti_aliasing_level()
);
ui::draw_image(
Expand Down
18 changes: 10 additions & 8 deletions libopensimcreator/UI/SplashTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class osc::SplashTab::Impl final : public TabPrivate {
{
Rect tabUIRect = ui::get_main_viewport_workspace_uiscreenspace_rect();
// pretend the attributation bar isn't there (avoid it)
tabUIRect.p2.y -= static_cast<float>(max(m_TudLogo.dimensions().y, m_CziLogo.dimensions().y)) - 2.0f*ui::get_style_panel_padding().y;
tabUIRect.p2.y -= max(m_TudLogo.device_independent_dimensions().y, m_CziLogo.device_independent_dimensions().y) - 2.0f*ui::get_style_panel_padding().y;

const Vec2 menuAndTopLogoDims = elementwise_min(dimensions_of(tabUIRect), Vec2{m_SplashMenuMaxDims.x, m_SplashMenuMaxDims.y + m_MainAppLogoDims.y + m_TopLogoPadding.y});
const Vec2 menuAndTopLogoTopLeft = tabUIRect.p1 + 0.5f*(dimensions_of(tabUIRect) - menuAndTopLogoDims);
Expand Down Expand Up @@ -195,7 +195,8 @@ class osc::SplashTab::Impl final : public TabPrivate {
ui::pop_style_var();

SceneRendererParams params{m_LastSceneRendererParams};
params.dimensions = dimensions_of(viewportUIRect);
params.virtual_pixel_dimensions = dimensions_of(viewportUIRect);
params.device_pixel_ratio = App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio(),
params.antialiasing_level = App::get().anti_aliasing_level();
params.projection_matrix = m_Camera.projection_matrix(aspect_ratio_of(viewportUIRect));

Expand Down Expand Up @@ -223,9 +224,10 @@ class osc::SplashTab::Impl final : public TabPrivate {
{
// center the menu window
const Rect mmr = calcMainMenuRect();
const Vec2 dims = dimensions_of(mmr);
ui::set_next_panel_pos(mmr.p1);
ui::set_next_panel_size({dimensions_of(mmr).x, -1.0f});
ui::set_next_panel_size_constraints(dimensions_of(mmr), dimensions_of(mmr));
ui::set_next_panel_size({dims.x, -1.0f});
ui::set_next_panel_size_constraints(dims, dims);

if (ui::begin_panel("Splash screen", nullptr, ui::WindowFlag::NoTitleBar)) {
drawMenuContent();
Expand Down Expand Up @@ -358,15 +360,15 @@ class osc::SplashTab::Impl final : public TabPrivate {
{
const Rect viewportUIRect = ui::get_main_viewport_workspace_uiscreenspace_rect();
Vec2 loc = viewportUIRect.p2;
loc.x = loc.x - 2.0f*ui::get_style_panel_padding().x - static_cast<float>(m_CziLogo.dimensions().x) - 2.0f*ui::get_style_item_spacing().x - static_cast<float>(m_TudLogo.dimensions().x);
loc.y = loc.y - 2.0f*ui::get_style_panel_padding().y - static_cast<float>(max(m_CziLogo.dimensions().y, m_TudLogo.dimensions().y));
loc.x = loc.x - 2.0f*ui::get_style_panel_padding().x - m_CziLogo.device_independent_dimensions().x - 2.0f*ui::get_style_item_spacing().x - m_TudLogo.device_independent_dimensions().x;
loc.y = loc.y - 2.0f*ui::get_style_panel_padding().y - max(m_CziLogo.device_independent_dimensions().y, m_TudLogo.device_independent_dimensions().y);

ui::set_next_panel_pos(loc);
ui::begin_panel("##czlogo", nullptr, ui::get_minimal_panel_flags());
ui::draw_image(m_CziLogo);
ui::end_panel();

loc.x += static_cast<float>(m_CziLogo.dimensions().x) + 2.0f*ui::get_style_item_spacing().x;
loc.x += m_CziLogo.device_independent_dimensions().x + 2.0f*ui::get_style_item_spacing().x;
ui::set_next_panel_pos(loc);
ui::begin_panel("##tudlogo", nullptr, ui::get_minimal_panel_flags());
ui::draw_image(m_TudLogo);
Expand Down Expand Up @@ -402,7 +404,7 @@ class osc::SplashTab::Impl final : public TabPrivate {

// dimensions of stuff
Vec2 m_SplashMenuMaxDims = {640.0f, 512.0f};
Vec2 m_MainAppLogoDims = m_MainAppLogo.dimensions();
Vec2 m_MainAppLogoDims = m_MainAppLogo.device_independent_dimensions();
Vec2 m_TopLogoPadding = {25.0f, 35.0f};

// UI state
Expand Down
7 changes: 4 additions & 3 deletions libopensimcreator/UI/TPS2DTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ class osc::TPS2DTab::Impl final : public TabPrivate {
{
const Vec2 windowDims = ui::get_content_region_available();
const float minDim = min(windowDims.x, windowDims.y);
const Vec2i texDims = Vec2i{minDim, minDim};
const Vec2 texDims = {minDim, minDim};

renderMesh(m_InputGrid, texDims, m_InputRender);

Expand Down Expand Up @@ -386,10 +386,11 @@ class osc::TPS2DTab::Impl final : public TabPrivate {
private:

// render the given mesh as-is to the given output render texture
void renderMesh(const Mesh& mesh, Vec2i dims, std::optional<RenderTexture>& out)
void renderMesh(const Mesh& mesh, Vec2 dims, std::optional<RenderTexture>& out)
{
const RenderTextureParams textureParameters = {
.dimensions = dims,
.dimensions = App::get().main_window_device_pixel_ratio() * dims,
.device_pixel_ratio = App::get().main_window_device_pixel_ratio(),
.anti_aliasing_level = App::get().anti_aliasing_level()
};
out.emplace(textureParameters);
Expand Down
2 changes: 1 addition & 1 deletion liboscar-demos/ImGuizmoDemoTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class osc::ImGuizmoDemoTab::Impl final : public TabPrivate {
{
const Mat4 view_matrix = scene_camera_.view_matrix();
const Rect viewport_ui_rect = ui::get_main_viewport_workspace_uiscreenspace_rect();
const Mat4 projection_matrix = scene_camera_.projection_matrix(aspect_ratio_of(dimensions_of(viewport_ui_rect)));
const Mat4 projection_matrix = scene_camera_.projection_matrix(aspect_ratio_of(viewport_ui_rect));

ui::gizmo_demo_draw_grid(identity<Mat4>(), view_matrix, projection_matrix, 100.0f, viewport_ui_rect);
ui::gizmo_demo_draw_cube(model_matrix_, view_matrix, projection_matrix, viewport_ui_rect);
Expand Down
5 changes: 3 additions & 2 deletions liboscar-demos/MeshGenTestTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,11 @@ class osc::MeshGenTestTab::Impl final : public TabPrivate {
ui::start_new_line();

const Vec2 content_region = ui::get_content_region_available();
render_params_.dimensions = elementwise_max(content_region, {0.0f, 0.0f});
render_params_.virtual_pixel_dimensions = elementwise_max(content_region, {0.0f, 0.0f});
render_params_.device_pixel_ratio = App::settings().get_value<float>("graphics/render_scale", 1.0f) * App::get().main_window_device_pixel_ratio(),
render_params_.antialiasing_level = App::get().anti_aliasing_level();
render_params_.light_direction = recommended_light_direction(camera_);
render_params_.projection_matrix = camera_.projection_matrix(aspect_ratio_of(render_params_.dimensions));
render_params_.projection_matrix = camera_.projection_matrix(aspect_ratio_of(render_params_.virtual_pixel_dimensions));
render_params_.view_matrix = camera_.view_matrix();
render_params_.view_pos = camera_.position();
render_params_.near_clipping_plane = camera_.znear;
Expand Down
2 changes: 1 addition & 1 deletion liboscar-demos/bookofshaders/BookOfShadersTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class osc::BookOfShadersTab::Impl final : public TabPrivate {
// update properties for this frame
const Vec2 workspace_dimensions = ui::get_main_viewport_workspace_screen_dimensions();
props_.set_time(App::get().frame_start_time());
props_.set_resolution(workspace_dimensions);
props_.set_resolution(workspace_dimensions * App::get().main_window_device_pixel_ratio());
props_.set_mouse_position(ui::get_mouse_pos());

graphics::draw(
Expand Down
10 changes: 6 additions & 4 deletions liboscar-demos/learnopengl/AdvancedLighting/LOGLBloomTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,23 @@ class osc::LOGLBloomTab::Impl final : public TabPrivate {
void draw_3d_scene()
{
const Rect viewport_screen_space_rect = ui::get_main_viewport_workspace_screenspace_rect();
const Vec2 viewport_dimensions = dimensions_of(viewport_screen_space_rect);
const float device_pixel_ratio = App::get().main_window_device_pixel_ratio();
const Vec2 viewport_pixel_dimensions = device_pixel_ratio * dimensions_of(viewport_screen_space_rect);

reformat_all_textures(viewport_dimensions);
reformat_all_textures(viewport_pixel_dimensions, device_pixel_ratio);
render_scene_mrt();
render_blurred_brightness();
render_combined_scene(viewport_screen_space_rect);
draw_overlays(viewport_screen_space_rect);
}

void reformat_all_textures(const Vec2& viewport_dimensions)
void reformat_all_textures(const Vec2& viewport_pixel_dimensions, float device_pixel_ratio)
{
const AntiAliasingLevel aa_level = App::get().anti_aliasing_level();

RenderTextureParams params = {
.dimensions = viewport_dimensions,
.dimensions = viewport_pixel_dimensions,
.device_pixel_ratio = device_pixel_ratio,
.anti_aliasing_level = aa_level,
.color_format = ColorRenderBufferFormat::DefaultHDR,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ namespace
},
};

void reformat(Vec2 dimensions, AntiAliasingLevel aa_level)
void reformat(Vec2 pixel_dimensions, float device_pixel_ratio, AntiAliasingLevel aa_level)
{
for (RenderTexture* texture_ptr : {&albedo, &normal, &position}) {
texture_ptr->reformat({
.dimensions = dimensions,
.dimensions = pixel_dimensions,
.device_pixel_ratio = device_pixel_ratio,
.anti_aliasing_level = aa_level,
.color_format = texture_ptr->color_format(),
});
Expand Down Expand Up @@ -190,12 +191,14 @@ class osc::LOGLDeferredShadingTab::Impl final : public TabPrivate {
{
const Rect viewport_screen_space_rect = ui::get_main_viewport_workspace_screenspace_rect();
const Vec2 viewport_dimensions = dimensions_of(viewport_screen_space_rect);
const float device_pixel_scale = App::get().main_window_device_pixel_ratio();
const Vec2 viewport_pixel_dimensions = device_pixel_scale * viewport_dimensions;
const AntiAliasingLevel anti_aliasing_level = App::get().anti_aliasing_level();

// ensure textures/buffers have correct dimensions
{
gbuffer_.reformat(viewport_dimensions, anti_aliasing_level);
output_texture_.set_dimensions(viewport_dimensions);
gbuffer_.reformat(viewport_pixel_dimensions, device_pixel_scale, anti_aliasing_level);
output_texture_.set_dimensions(viewport_pixel_dimensions);
output_texture_.set_anti_aliasing_level(anti_aliasing_level);
}

Expand Down
7 changes: 6 additions & 1 deletion liboscar-demos/learnopengl/AdvancedLighting/LOGLHDRTab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,13 @@ class osc::LOGLHDRTab::Impl final : public TabPrivate {
{
// reformat intermediate HDR texture to match tab dimensions etc.
{
const Vec2 viewport_dimensions = ui::get_main_viewport_workspace_screen_dimensions();
const float device_pixel_ratio = App::get().main_window_device_pixel_ratio();
const Vec2 viewport_pixel_dimensions = device_pixel_ratio * viewport_dimensions;

RenderTextureParams params = {
.dimensions = ui::get_main_viewport_workspace_screen_dimensions(),
.dimensions = viewport_pixel_dimensions,
.device_pixel_ratio = device_pixel_ratio,
.anti_aliasing_level = App::get().anti_aliasing_level(),
};
if (use_16bit_format_) {
Expand Down
Loading

0 comments on commit bdc268b

Please sign in to comment.