mirror of
https://github.com/bevyengine/bevy
synced 2024-11-13 00:17:27 +00:00
attempt to deal with rounding issue when creating the swap chain (#997)
attempt to deal with rounding issue when creating the swap chain on high DPI displays
This commit is contained in:
parent
08b6aa59f8
commit
3d386a77b4
11 changed files with 86 additions and 64 deletions
|
@ -78,7 +78,7 @@ pub fn camera_system<T: CameraProjection + Component>(
|
||||||
for (entity, mut camera, mut camera_projection) in queries.q0_mut().iter_mut() {
|
for (entity, mut camera, mut camera_projection) in queries.q0_mut().iter_mut() {
|
||||||
if let Some(window) = windows.get(camera.window) {
|
if let Some(window) = windows.get(camera.window) {
|
||||||
if changed_window_ids.contains(&window.id()) || added_cameras.contains(&entity) {
|
if changed_window_ids.contains(&window.id()) || added_cameras.contains(&entity) {
|
||||||
camera_projection.update(window.width() as usize, window.height() as usize);
|
camera_projection.update(window.logical_width(), window.logical_height());
|
||||||
camera.projection_matrix = camera_projection.get_projection_matrix();
|
camera.projection_matrix = camera_projection.get_projection_matrix();
|
||||||
camera.depth_calculation = camera_projection.depth_calculation();
|
camera.depth_calculation = camera_projection.depth_calculation();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub trait CameraProjection {
|
pub trait CameraProjection {
|
||||||
fn get_projection_matrix(&self) -> Mat4;
|
fn get_projection_matrix(&self) -> Mat4;
|
||||||
fn update(&mut self, width: usize, height: usize);
|
fn update(&mut self, width: f32, height: f32);
|
||||||
fn depth_calculation(&self) -> DepthCalculation;
|
fn depth_calculation(&self) -> DepthCalculation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ impl CameraProjection for PerspectiveProjection {
|
||||||
Mat4::perspective_rh(self.fov, self.aspect_ratio, self.near, self.far)
|
Mat4::perspective_rh(self.fov, self.aspect_ratio, self.near, self.far)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, width: usize, height: usize) {
|
fn update(&mut self, width: f32, height: f32) {
|
||||||
self.aspect_ratio = width as f32 / height as f32;
|
self.aspect_ratio = width / height;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depth_calculation(&self) -> DepthCalculation {
|
fn depth_calculation(&self) -> DepthCalculation {
|
||||||
|
@ -75,11 +75,11 @@ impl CameraProjection for OrthographicProjection {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, width: usize, height: usize) {
|
fn update(&mut self, width: f32, height: f32) {
|
||||||
match self.window_origin {
|
match self.window_origin {
|
||||||
WindowOrigin::Center => {
|
WindowOrigin::Center => {
|
||||||
let half_width = width as f32 / 2.0;
|
let half_width = width / 2.0;
|
||||||
let half_height = height as f32 / 2.0;
|
let half_height = height / 2.0;
|
||||||
self.left = -half_width;
|
self.left = -half_width;
|
||||||
self.right = half_width;
|
self.right = half_width;
|
||||||
self.top = half_height;
|
self.top = half_height;
|
||||||
|
@ -87,8 +87,8 @@ impl CameraProjection for OrthographicProjection {
|
||||||
}
|
}
|
||||||
WindowOrigin::BottomLeft => {
|
WindowOrigin::BottomLeft => {
|
||||||
self.left = 0.0;
|
self.left = 0.0;
|
||||||
self.right = width as f32;
|
self.right = width;
|
||||||
self.top = height as f32;
|
self.top = height;
|
||||||
self.bottom = 0.0;
|
self.bottom = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,8 +68,8 @@ impl Node for WindowTextureNode {
|
||||||
render_resource_context.remove_texture(old_texture);
|
render_resource_context.remove_texture(old_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.descriptor.size.width = window.scaled_width();
|
self.descriptor.size.width = window.physical_width();
|
||||||
self.descriptor.size.height = window.scaled_height();
|
self.descriptor.size.height = window.physical_height();
|
||||||
let texture_resource = render_resource_context.create_texture(self.descriptor);
|
let texture_resource = render_resource_context.create_texture(self.descriptor);
|
||||||
output.set(WINDOW_TEXTURE, RenderResourceId::Texture(texture_resource));
|
output.set(WINDOW_TEXTURE, RenderResourceId::Texture(texture_resource));
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,8 +116,8 @@ impl FlexSurface {
|
||||||
*node,
|
*node,
|
||||||
stretch::style::Style {
|
stretch::style::Style {
|
||||||
size: stretch::geometry::Size {
|
size: stretch::geometry::Size {
|
||||||
width: stretch::style::Dimension::Points(window.width() as f32),
|
width: stretch::style::Dimension::Points(window.logical_width()),
|
||||||
height: stretch::style::Dimension::Points(window.height() as f32),
|
height: stretch::style::Dimension::Points(window.logical_height()),
|
||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
|
|
|
@ -564,8 +564,8 @@ impl WgpuFrom<&Window> for wgpu::SwapChainDescriptor {
|
||||||
wgpu::SwapChainDescriptor {
|
wgpu::SwapChainDescriptor {
|
||||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
format: TextureFormat::default().wgpu_into(),
|
format: TextureFormat::default().wgpu_into(),
|
||||||
width: window.scaled_width(),
|
width: window.physical_width(),
|
||||||
height: window.scaled_height(),
|
height: window.physical_height(),
|
||||||
present_mode: if window.vsync() {
|
present_mode: if window.vsync() {
|
||||||
wgpu::PresentMode::Mailbox
|
wgpu::PresentMode::Mailbox
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,8 +5,8 @@ use bevy_math::Vec2;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct WindowResized {
|
pub struct WindowResized {
|
||||||
pub id: WindowId,
|
pub id: WindowId,
|
||||||
pub width: usize,
|
pub width: f32,
|
||||||
pub height: usize,
|
pub height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An event that indicates that a new window should be created.
|
/// An event that indicates that a new window should be created.
|
||||||
|
|
|
@ -35,8 +35,8 @@ impl Default for WindowId {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
id: WindowId,
|
id: WindowId,
|
||||||
width: u32,
|
physical_width: u32,
|
||||||
height: u32,
|
physical_height: u32,
|
||||||
title: String,
|
title: String,
|
||||||
vsync: bool,
|
vsync: bool,
|
||||||
resizable: bool,
|
resizable: bool,
|
||||||
|
@ -61,8 +61,8 @@ pub enum WindowCommand {
|
||||||
title: String,
|
title: String,
|
||||||
},
|
},
|
||||||
SetResolution {
|
SetResolution {
|
||||||
width: u32,
|
physical_width: u32,
|
||||||
height: u32,
|
physical_height: u32,
|
||||||
},
|
},
|
||||||
SetVsync {
|
SetVsync {
|
||||||
vsync: bool,
|
vsync: bool,
|
||||||
|
@ -103,8 +103,8 @@ impl Window {
|
||||||
pub fn new(id: WindowId, window_descriptor: &WindowDescriptor) -> Self {
|
pub fn new(id: WindowId, window_descriptor: &WindowDescriptor) -> Self {
|
||||||
Window {
|
Window {
|
||||||
id,
|
id,
|
||||||
height: window_descriptor.height,
|
physical_height: window_descriptor.height,
|
||||||
width: window_descriptor.width,
|
physical_width: window_descriptor.width,
|
||||||
title: window_descriptor.title.clone(),
|
title: window_descriptor.title.clone(),
|
||||||
vsync: window_descriptor.vsync,
|
vsync: window_descriptor.vsync,
|
||||||
resizable: window_descriptor.resizable,
|
resizable: window_descriptor.resizable,
|
||||||
|
@ -127,20 +127,32 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn width(&self) -> u32 {
|
pub fn width(&self) -> u32 {
|
||||||
self.width
|
self.logical_width() as u32
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scaled_width(&self) -> u32 {
|
|
||||||
(self.width as f64 * self.scale_factor) as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn scaled_height(&self) -> u32 {
|
|
||||||
(self.height as f64 * self.scale_factor) as u32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn height(&self) -> u32 {
|
pub fn height(&self) -> u32 {
|
||||||
self.height
|
self.logical_height() as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn logical_width(&self) -> f32 {
|
||||||
|
(self.physical_width as f64 / self.scale_factor) as f32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn logical_height(&self) -> f32 {
|
||||||
|
(self.physical_height as f64 / self.scale_factor) as f32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn physical_width(&self) -> u32 {
|
||||||
|
self.physical_width
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn physical_height(&self) -> u32 {
|
||||||
|
self.physical_height
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -150,17 +162,19 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_resolution(&mut self, width: u32, height: u32) {
|
pub fn set_resolution(&mut self, width: u32, height: u32) {
|
||||||
self.width = width;
|
self.physical_width = (width as f64 * self.scale_factor) as u32;
|
||||||
self.height = height;
|
self.physical_height = (height as f64 * self.scale_factor) as u32;
|
||||||
self.command_queue
|
self.command_queue.push(WindowCommand::SetResolution {
|
||||||
.push(WindowCommand::SetResolution { width, height });
|
physical_width: self.physical_width,
|
||||||
|
physical_height: self.physical_height,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn update_resolution_from_backend(&mut self, width: u32, height: u32) {
|
pub fn update_physical_size_from_backend(&mut self, width: u32, height: u32) {
|
||||||
self.width = width;
|
self.physical_width = width;
|
||||||
self.height = height;
|
self.physical_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
@ -265,7 +279,7 @@ impl Window {
|
||||||
self.mode = mode;
|
self.mode = mode;
|
||||||
self.command_queue.push(WindowCommand::SetWindowMode {
|
self.command_queue.push(WindowCommand::SetWindowMode {
|
||||||
mode,
|
mode,
|
||||||
resolution: (self.width, self.height),
|
resolution: (self.physical_width, self.physical_height),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,9 +67,15 @@ fn change_window(_: &mut World, resources: &mut Resources) {
|
||||||
let window = winit_windows.get_window(id).unwrap();
|
let window = winit_windows.get_window(id).unwrap();
|
||||||
window.set_title(&title);
|
window.set_title(&title);
|
||||||
}
|
}
|
||||||
bevy_window::WindowCommand::SetResolution { width, height } => {
|
bevy_window::WindowCommand::SetResolution {
|
||||||
|
physical_width,
|
||||||
|
physical_height,
|
||||||
|
} => {
|
||||||
let window = winit_windows.get_window(id).unwrap();
|
let window = winit_windows.get_window(id).unwrap();
|
||||||
window.set_inner_size(winit::dpi::LogicalSize::new(width, height));
|
window.set_inner_size(winit::dpi::PhysicalSize::new(
|
||||||
|
physical_width,
|
||||||
|
physical_height,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
bevy_window::WindowCommand::SetVsync { .. } => (),
|
bevy_window::WindowCommand::SetVsync { .. } => (),
|
||||||
bevy_window::WindowCommand::SetResizable { resizable } => {
|
bevy_window::WindowCommand::SetResizable { resizable } => {
|
||||||
|
@ -197,17 +203,15 @@ pub fn winit_runner(mut app: App) {
|
||||||
let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap();
|
let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap();
|
||||||
let mut windows = app.resources.get_mut::<Windows>().unwrap();
|
let mut windows = app.resources.get_mut::<Windows>().unwrap();
|
||||||
let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
|
let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
|
||||||
let winit_window = winit_windows.get_window(window_id).unwrap();
|
|
||||||
let window = windows.get_mut(window_id).unwrap();
|
let window = windows.get_mut(window_id).unwrap();
|
||||||
let size = size.to_logical(winit_window.scale_factor());
|
window.update_physical_size_from_backend(size.width, size.height);
|
||||||
window.update_resolution_from_backend(size.width, size.height);
|
|
||||||
|
|
||||||
let mut resize_events =
|
let mut resize_events =
|
||||||
app.resources.get_mut::<Events<WindowResized>>().unwrap();
|
app.resources.get_mut::<Events<WindowResized>>().unwrap();
|
||||||
resize_events.send(WindowResized {
|
resize_events.send(WindowResized {
|
||||||
id: window_id,
|
id: window_id,
|
||||||
height: window.height() as usize,
|
height: window.logical_height(),
|
||||||
width: window.width() as usize,
|
width: window.logical_width(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
WindowEvent::CloseRequested => {
|
WindowEvent::CloseRequested => {
|
||||||
|
@ -305,8 +309,8 @@ pub fn winit_runner(mut app: App) {
|
||||||
|
|
||||||
// FIXME?: On Android window start is top while on PC/Linux/OSX on bottom
|
// FIXME?: On Android window start is top while on PC/Linux/OSX on bottom
|
||||||
if cfg!(target_os = "android") {
|
if cfg!(target_os = "android") {
|
||||||
let window_height = windows.get_primary().unwrap().height();
|
let window_height = windows.get_primary().unwrap().logical_height();
|
||||||
location.y = window_height as f32 - location.y;
|
location.y = window_height - location.y;
|
||||||
}
|
}
|
||||||
touch_input_events.send(converters::convert_touch_input(touch, location));
|
touch_input_events.send(converters::convert_touch_input(touch, location));
|
||||||
}
|
}
|
||||||
|
@ -332,9 +336,11 @@ pub fn winit_runner(mut app: App) {
|
||||||
let mut windows = app.resources.get_mut::<Windows>().unwrap();
|
let mut windows = app.resources.get_mut::<Windows>().unwrap();
|
||||||
let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
|
let window_id = winit_windows.get_window_id(winit_window_id).unwrap();
|
||||||
let window = windows.get_mut(window_id).unwrap();
|
let window = windows.get_mut(window_id).unwrap();
|
||||||
let size = new_inner_size.to_logical(scale_factor);
|
window.update_physical_size_from_backend(
|
||||||
|
new_inner_size.width,
|
||||||
|
new_inner_size.height,
|
||||||
|
);
|
||||||
window.update_scale_factor_from_backend(scale_factor);
|
window.update_scale_factor_from_backend(scale_factor);
|
||||||
window.update_resolution_from_backend(size.width, size.height);
|
|
||||||
}
|
}
|
||||||
WindowEvent::Focused(focused) => {
|
WindowEvent::Focused(focused) => {
|
||||||
let mut focused_events =
|
let mut focused_events =
|
||||||
|
|
|
@ -31,8 +31,8 @@ impl WinitWindows {
|
||||||
winit::window::Fullscreen::Exclusive(match use_size {
|
winit::window::Fullscreen::Exclusive(match use_size {
|
||||||
true => get_fitting_videomode(
|
true => get_fitting_videomode(
|
||||||
&event_loop.primary_monitor().unwrap(),
|
&event_loop.primary_monitor().unwrap(),
|
||||||
window.width(),
|
window.physical_width(),
|
||||||
window.height(),
|
window.physical_height(),
|
||||||
),
|
),
|
||||||
false => get_best_videomode(&event_loop.primary_monitor().unwrap()),
|
false => get_best_videomode(&event_loop.primary_monitor().unwrap()),
|
||||||
}),
|
}),
|
||||||
|
@ -100,6 +100,8 @@ impl WinitWindows {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let inner_size = winit_window.inner_size();
|
||||||
|
window.update_physical_size_from_backend(inner_size.width, inner_size.height);
|
||||||
window.update_scale_factor_from_backend(winit_window.scale_factor());
|
window.update_scale_factor_from_backend(winit_window.scale_factor());
|
||||||
|
|
||||||
self.windows.insert(winit_window.id(), winit_window);
|
self.windows.insert(winit_window.id(), winit_window);
|
||||||
|
|
|
@ -237,11 +237,11 @@ fn collision_system(
|
||||||
|
|
||||||
let win = wins.get_primary().unwrap();
|
let win = wins.get_primary().unwrap();
|
||||||
|
|
||||||
let ceiling = (win.height() / 2) as f32;
|
let ceiling = win.logical_height() / 2.;
|
||||||
let ground = -((win.height() / 2) as f32);
|
let ground = -(win.logical_height() / 2.);
|
||||||
|
|
||||||
let wall_left = -((win.width() / 2) as f32);
|
let wall_left = -(win.logical_width() / 2.);
|
||||||
let wall_right = (win.width() / 2) as f32;
|
let wall_right = win.logical_width() / 2.;
|
||||||
|
|
||||||
for (mut v, mut t) in q.iter_mut() {
|
for (mut v, mut t) in q.iter_mut() {
|
||||||
let left = t.translation.x - SPRITE_SIZE / 2.0;
|
let left = t.translation.x - SPRITE_SIZE / 2.0;
|
||||||
|
|
|
@ -48,12 +48,12 @@ fn bounce_system(
|
||||||
mut sprites: Query<(&Transform, &mut Velocity)>,
|
mut sprites: Query<(&Transform, &mut Velocity)>,
|
||||||
) {
|
) {
|
||||||
let window = windows.get_primary().expect("No primary window.");
|
let window = windows.get_primary().expect("No primary window.");
|
||||||
let width = window.width();
|
let width = window.logical_width();
|
||||||
let height = window.height();
|
let height = window.logical_height();
|
||||||
let left = width as f32 / -2.0;
|
let left = width / -2.0;
|
||||||
let right = width as f32 / 2.0;
|
let right = width / 2.0;
|
||||||
let bottom = height as f32 / -2.0;
|
let bottom = height / -2.0;
|
||||||
let top = height as f32 / 2.0;
|
let top = height / 2.0;
|
||||||
sprites
|
sprites
|
||||||
// Batch size of 32 is chosen to limit the overhead of
|
// Batch size of 32 is chosen to limit the overhead of
|
||||||
// ParallelIterator, since negating a vector is very inexpensive.
|
// ParallelIterator, since negating a vector is very inexpensive.
|
||||||
|
|
Loading…
Reference in a new issue