Bevy version and features
bevy = { version = "0.19" }
Relevant system information
- cargo 1.96.0 (30a34c682 2026-05-25)
- Latest CachyOS, KDE
AdapterInfo { name: "AMD Radeon RX 9070 XT (RADV GFX1201)", vendor: 4098, device: 30032, device_type: DiscreteGpu, device_pci_bus_id: "0000:03:00.0", driver: "radv", driver_info: "Mesa 26.1.2-arch3.1", backend: Vulkan, subgroup_min_size: 32, subgroup_max_size: 64, transient_saves_memory: false }
What you did
I'm working on a pixel-style game and I'm trying to utilizing resolution scaling for that.
I want to keep my logical resolution as 640x360 at all times, while overriding the scale factor, which should scale the physical resolution.
Below is a MRE of what I'm doing: setting the physical resolution to 1280x720 and the scale_factor_override to Some(2.0):
use bevy::input::common_conditions::input_just_pressed;
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, startup)
.add_systems(
Update,
(
update_resolution_text,
change_resolution.run_if(input_just_pressed(KeyCode::Space)),
reset_resolution.run_if(input_just_pressed(KeyCode::Escape)),
),
)
.run();
}
fn startup(mut commands: Commands) {
commands.spawn(Camera2d);
commands.spawn(Text::default());
commands.spawn((
Text2d::new("I'm at [0, -180]"),
Transform::from_translation(vec3(0.0, -180.0, 0.0)),
));
}
fn reset_resolution(mut q_window: Query<&mut Window>) {
let mut bevy_window = q_window.single_mut().unwrap();
bevy_window.resolution.set_scale_factor_override(None);
bevy_window.resolution.set_physical_resolution(1280, 720);
}
fn change_resolution(mut q_window: Query<&mut Window>) {
let mut bevy_window = q_window.single_mut().unwrap();
bevy_window.resolution.set_scale_factor_override(Some(2.0));
bevy_window.resolution.set_physical_resolution(1280, 720);
// After setting the above I expect a window with HD size, but 640x360 internal resolution
}
/// Only for informative purposes, to display the current window state.
fn update_resolution_text(mut q_text: Query<&mut Text>, q_window: Query<&Window>) {
let res = q_window.single().unwrap().resolution.clone();
q_text.single_mut().unwrap().0 = format!(
"Logical size: {}\nPhysical size: {}\nBase scale: {}\nScale override: {:?}",
res.size(),
res.physical_size(),
res.base_scale_factor(),
res.scale_factor_override()
);
}
What went wrong
My expectation would be that I get a window of HD (physical) size and 640x360 logical size.
As a visual check, I've put a Text entity at [0, -180], which should place it just at the bottom of the window.
What happens is that I get a window with physical size: 2560x1440 (double 1280x720) and logical size: 1280x720.
Only after calling the system and changing the resolution an additional time do I get the desired effect.
(If I were to request 1920x1080 with override=3.0 I would get the FHD logical size and triple that in physical size).
This to me is a bug (or at least an unexpected behaviour).
The requested WindowResolution should be resolved to the same window state regardless of the state it's requested in.
I believe the culprit is in
|
pub(crate) fn changed_windows( |
.
I'm happy to work on this and provide a PR, but I'd like to first confirm that this is reproducible for others and we have an agreement of the desired behaviour.
Additional information
I'm also pretty sure that there is another bug in this WindowResolution handling.
If I were to, instead of bevy_window.resolution.set_scale_factor_override(Some(2.0)), set the base scale factor with bevy_window.resolution.set_scale_factor(2.0) then (with the default initial window resolution of 1280x720) it would have no effect on the window state.
Only after resizing the window manually (or setting it to a different value than the current one) I will get the scaling factor effect.
So it looks like: if the physical resolution was not changed, the base_scale_factor will have no effect.
Bevy version and features
Relevant system information
What you did
I'm working on a pixel-style game and I'm trying to utilizing resolution scaling for that.
I want to keep my logical resolution as 640x360 at all times, while overriding the scale factor, which should scale the physical resolution.
Below is a MRE of what I'm doing: setting the physical resolution to 1280x720 and the
scale_factor_overridetoSome(2.0):What went wrong
My expectation would be that I get a window of HD (physical) size and 640x360 logical size.
As a visual check, I've put a Text entity at [0, -180], which should place it just at the bottom of the window.
What happens is that I get a window with physical size: 2560x1440 (double 1280x720) and logical size: 1280x720.
Only after calling the system and changing the resolution an additional time do I get the desired effect.
(If I were to request 1920x1080 with override=3.0 I would get the FHD logical size and triple that in physical size).
This to me is a bug (or at least an unexpected behaviour).
The requested
WindowResolutionshould be resolved to the same window state regardless of the state it's requested in.I believe the culprit is in
bevy/crates/bevy_winit/src/system.rs
Line 305 in 097fc03
I'm happy to work on this and provide a PR, but I'd like to first confirm that this is reproducible for others and we have an agreement of the desired behaviour.
Additional information
I'm also pretty sure that there is another bug in this
WindowResolutionhandling.If I were to, instead of
bevy_window.resolution.set_scale_factor_override(Some(2.0)), set the base scale factor withbevy_window.resolution.set_scale_factor(2.0)then (with the default initial window resolution of 1280x720) it would have no effect on the window state.Only after resizing the window manually (or setting it to a different value than the current one) I will get the scaling factor effect.
So it looks like: if the physical resolution was not changed, the
base_scale_factorwill have no effect.