diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index f96a46586f..7e102768cd 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3413,7 +3413,7 @@ impl Hud { span!(_guard, "render", "Hud::render"); // Don't show anything if the UI is toggled off. if self.show.ui { - self.ui.render(renderer, Some(globals)); + //self.ui.render(renderer, Some(globals)); } } diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index a7825976a7..c8ba084af5 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -224,15 +224,25 @@ impl PlayState for CharSelectionState { fn name(&self) -> &'static str { "Character Selection" } fn render(&mut self, renderer: &mut Renderer, _: &Settings) { + let mut drawer = match renderer + .start_recording_frame(self.scene.global_bind_group()) + .unwrap() + { + Some(d) => d, + // Couldn't get swap chain texture this fime + None => return, + }; + let client = self.client.borrow(); let (humanoid_body, loadout) = Self::get_humanoid_body_inventory(&self.char_selection_ui, &client); // Render the scene. - self.scene - .render(renderer, client.get_tick(), humanoid_body, loadout); + //self.scene + // .render(renderer, client.get_tick(), humanoid_body, loadout); // Draw the UI to the screen. - self.char_selection_ui.render(renderer); + self.char_selection_ui + .render(&mut drawer.third_pass().draw_ui()); } } diff --git a/voxygen/src/menu/char_selection/ui/mod.rs b/voxygen/src/menu/char_selection/ui/mod.rs index f00a776157..be0c99b0ac 100644 --- a/voxygen/src/menu/char_selection/ui/mod.rs +++ b/voxygen/src/menu/char_selection/ui/mod.rs @@ -1,6 +1,6 @@ use crate::{ i18n::{Localization, LocalizationHandle}, - render::Renderer, + render::UiDrawer, ui::{ self, fonts::IcedFonts as Fonts, @@ -1583,9 +1583,7 @@ impl CharSelectionUi { events } - // TODO: do we need globals? - pub fn render(&self, renderer: &mut Renderer) { /* self.ui.render(renderer);*/ - } + pub fn render<'a>(&'a self, drawer: &mut UiDrawer<'_, 'a>) { self.ui.render(drawer); } } #[derive(Default)] diff --git a/voxygen/src/menu/main/mod.rs b/voxygen/src/menu/main/mod.rs index 4ed8964a20..c9f49b76e3 100644 --- a/voxygen/src/menu/main/mod.rs +++ b/voxygen/src/menu/main/mod.rs @@ -346,7 +346,6 @@ impl PlayState for MainMenuState { fn name(&self) -> &'static str { "Title" } fn render(&mut self, renderer: &mut Renderer, _: &Settings) { - // TODO: maybe the drawer should be passed in from above? let mut drawer = match renderer .start_recording_frame(self.scene.global_bind_group()) .unwrap() diff --git a/voxygen/src/menu/main/scene.rs b/voxygen/src/menu/main/scene.rs index b592e13db5..32e8699358 100644 --- a/voxygen/src/menu/main/scene.rs +++ b/voxygen/src/menu/main/scene.rs @@ -3,8 +3,6 @@ use crate::render::{ }; pub struct Scene { - // global_data: GlobalModel, - // lod_data: LodData, bind_group: GlobalsBindGroup, } diff --git a/voxygen/src/render/bound.rs b/voxygen/src/render/bound.rs new file mode 100644 index 0000000000..e601c0adb1 --- /dev/null +++ b/voxygen/src/render/bound.rs @@ -0,0 +1,14 @@ +pub struct Bound { + pub(super) bind_group: wgpu::BindGroup, + pub(super) with: T, +} + +impl std::ops::Deref for Bound { + type Target = T; + + fn deref(&self) -> &Self::Target { &self.with } +} + +impl std::ops::DerefMut for Bound { + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.with } +} diff --git a/voxygen/src/render/mod.rs b/voxygen/src/render/mod.rs index 000da2d167..9a4230f514 100644 --- a/voxygen/src/render/mod.rs +++ b/voxygen/src/render/mod.rs @@ -1,3 +1,4 @@ +pub mod bound; mod buffer; #[allow(clippy::single_component_path_imports)] // TODO: Pending review in #587 pub mod consts; @@ -11,6 +12,7 @@ pub mod texture; // Reexports pub use self::{ + bound::Bound, consts::Consts, error::RenderError, instances::Instances, @@ -37,7 +39,7 @@ pub use self::{ ui::{ create_quad as create_ui_quad, create_quad_vert_gradient as create_ui_quad_vert_gradient, create_tri as create_ui_tri, - Locals as UiLocals, LocalsBindGroup as UiLocalsBindGroup, Mode as UiMode, + BoundLocals as UiBoundLocals, Locals as UiLocals, Mode as UiMode, TextureBindGroup as UiTextureBindGroup, Vertex as UiVertex, }, GlobalModel, Globals, GlobalsBindGroup, GlobalsLayouts, Light, Shadow, diff --git a/voxygen/src/render/pipelines/ui.rs b/voxygen/src/render/pipelines/ui.rs index 6c87ab9adf..99cf389aad 100644 --- a/voxygen/src/render/pipelines/ui.rs +++ b/voxygen/src/render/pipelines/ui.rs @@ -1,4 +1,4 @@ -use super::super::{AaMode, Consts, GlobalsLayouts, Quad, Texture, Tri}; +use super::super::{AaMode, Bound, Consts, GlobalsLayouts, Quad, Texture, Tri}; use bytemuck::{Pod, Zeroable}; use vek::*; @@ -80,9 +80,7 @@ impl Mode { } } -pub struct LocalsBindGroup { - pub(in super::super) bind_group: wgpu::BindGroup, -} +pub type BoundLocals = Bound>; pub struct TextureBindGroup { pub(in super::super) bind_group: wgpu::BindGroup, @@ -136,7 +134,7 @@ impl UiLayout { } } - pub fn bind_locals(&self, device: &wgpu::Device, locals: &Consts) -> LocalsBindGroup { + pub fn bind_locals(&self, device: &wgpu::Device, locals: Consts) -> BoundLocals { let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { label: None, layout: &self.locals, @@ -146,7 +144,10 @@ impl UiLayout { }], }); - LocalsBindGroup { bind_group } + BoundLocals { + bind_group, + with: locals, + } } pub fn bind_texture(&self, device: &wgpu::Device, texture: &Texture) -> TextureBindGroup { diff --git a/voxygen/src/render/renderer.rs b/voxygen/src/render/renderer.rs index 64d723f49f..672b9f4f38 100644 --- a/voxygen/src/render/renderer.rs +++ b/voxygen/src/render/renderer.rs @@ -1,4 +1,4 @@ -mod bind_group; +mod binding; mod drawer; pub use drawer::{Drawer, UiDrawer}; diff --git a/voxygen/src/render/renderer/bind_group.rs b/voxygen/src/render/renderer/binding.rs similarity index 84% rename from voxygen/src/render/renderer/bind_group.rs rename to voxygen/src/render/renderer/binding.rs index fd6af70f04..5ecfda32cf 100644 --- a/voxygen/src/render/renderer/bind_group.rs +++ b/voxygen/src/render/renderer/binding.rs @@ -8,6 +8,7 @@ use super::{ }; impl Renderer { + // TODO: rework this to use the Bound type? pub fn bind_globals( &self, global_model: &GlobalModel, @@ -28,7 +29,8 @@ impl Renderer { ) } - pub fn ui_bind_locals(&self, locals: &Consts) -> ui::LocalsBindGroup { + pub fn create_ui_bound_locals(&mut self, vals: &[ui::Locals]) -> ui::BoundLocals { + let locals = self.create_consts(vals); self.layouts.ui.bind_locals(&self.device, locals) } diff --git a/voxygen/src/render/renderer/drawer.rs b/voxygen/src/render/renderer/drawer.rs index 38a2b04605..036283d673 100644 --- a/voxygen/src/render/renderer/drawer.rs +++ b/voxygen/src/render/renderer/drawer.rs @@ -104,12 +104,7 @@ impl<'a> Drawer<'a> { attachment: &self.tex.view, resolve_target: None, ops: wgpu::Operations { - load: wgpu::LoadOp::Clear(wgpu::Color { - r: 1.0, - g: 0.25, - b: 0.5, - a: 0.5, - }), + load: wgpu::LoadOp::Clear(wgpu::Color::TRANSPARENT), store: true, }, }], @@ -310,7 +305,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { /// set with every draw call pub fn prepare<'data: 'pass>( &mut self, - locals: &'data ui::LocalsBindGroup, + locals: &'data ui::BoundLocals, //texture: &'b ui::TextureBindGroup, buf: &'data DynamicModel, scissor: Aabr, @@ -331,7 +326,7 @@ impl<'pass_ref, 'pass: 'pass_ref> UiDrawer<'pass_ref, 'pass> { } impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { - pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::LocalsBindGroup) { + pub fn set_locals<'data: 'pass>(&mut self, locals: &'data ui::BoundLocals) { self.render_pass.set_bind_group(1, &locals.bind_group, &[]); } @@ -345,12 +340,12 @@ impl<'pass_ref, 'pass: 'pass_ref> PreparedUiDrawer<'pass_ref, 'pass> { pub fn set_scissor<'data: 'pass>(&mut self, scissor: Aabr) { let Aabr { min, max } = scissor; - //self.render_pass.set_scissor_rect( - // min.x as u32, - // min.y as u32, - // (max.x - min.x) as u32, - // (max.y - min.y) as u32, - //); + self.render_pass.set_scissor_rect( + min.x as u32, + min.y as u32, + (max.x - min.x) as u32, + (max.y - min.y) as u32, + ); } pub fn draw<'data: 'pass>(&mut self, texture: &'data ui::TextureBindGroup, verts: Range) { diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index 0bd0217eec..7c221ca974 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -2,9 +2,9 @@ use crate::{ mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_terrain}, render::{ create_clouds_mesh, create_pp_mesh, create_skybox_mesh, BoneMeshes, CloudsLocals, - CloudsVertex, Consts, FigureModel, GlobalModel, Globals, Light, LodData, Mesh, Model, - PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, SkyboxVertex, - TerrainVertex, + CloudsVertex, Consts, FigureModel, GlobalModel, Globals, GlobalsBindGroup, Light, LodData, + Mesh, Model, PostProcessLocals, PostProcessVertex, Renderer, Shadow, ShadowLocals, + SkyboxVertex, TerrainVertex, }, scene::{ camera::{self, Camera, CameraMode}, @@ -69,6 +69,7 @@ struct Clouds { pub struct Scene { data: GlobalModel, + globals_bind_group: GlobalsBindGroup, camera: Camera, skybox: Skybox, @@ -117,14 +118,19 @@ impl Scene { let mut col_lights = FigureColLights::new(renderer); - Self { - data: GlobalModel { - globals: renderer.create_consts(&[Globals::default()]), - lights: renderer.create_consts(&[Light::default(); 32]), - shadows: renderer.create_consts(&[Shadow::default(); 32]), - shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), - }, + let data = GlobalModel { + globals: renderer.create_consts(&[Globals::default()]), + lights: renderer.create_consts(&[Light::default(); 32]), + shadows: renderer.create_consts(&[Shadow::default(); 32]), + shadow_mats: renderer.create_consts(&[ShadowLocals::default(); 6]), + }; + let lod = LodData::dummy(renderer); + let globals_bind_group = renderer.bind_globals(&data, &lod); + + Self { + data, + globals_bind_group, skybox: Skybox { model: renderer.create_model(&create_skybox_mesh()).unwrap(), }, @@ -136,7 +142,7 @@ impl Scene { model: renderer.create_model(&create_pp_mesh()).unwrap(), locals: renderer.create_consts(&[PostProcessLocals::default()]), }, - lod: LodData::dummy(renderer), + lod, map_bounds, figure_model_cache: FigureModelCache::new(), @@ -359,6 +365,8 @@ impl Scene { } } + pub fn global_bind_group(&self) -> &GlobalsBindGroup { &self.globals_bind_group } + pub fn render( &mut self, renderer: &mut Renderer, diff --git a/voxygen/src/ui/cache.rs b/voxygen/src/ui/cache.rs index ac10193dfa..dcf5041b8e 100644 --- a/voxygen/src/ui/cache.rs +++ b/voxygen/src/ui/cache.rs @@ -1,6 +1,6 @@ use super::graphic::{Graphic, GraphicCache, Id as GraphicId}; use crate::{ - render::{Mesh, Renderer, Texture, UiVertex}, + render::{Mesh, Renderer, Texture, UiTextureBindGroup, UiVertex}, Error, }; use conrod_core::{text::GlyphCache, widget::Id}; @@ -19,7 +19,7 @@ pub struct Cache { // Map from text ids to their positioned glyphs. text_cache: TextCache, glyph_cache: GlyphCache<'static>, - glyph_cache_tex: Texture, + glyph_cache_tex: (Texture, UiTextureBindGroup), graphic_cache: GraphicCache, } @@ -33,6 +33,12 @@ impl Cache { let glyph_cache_dims = Vec2::new(w, h).map(|e| (e * GLYPH_CACHE_SIZE).min(max_texture_size).max(512)); + let glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(glyph_cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; + Ok(Self { text_cache: Default::default(), glyph_cache: GlyphCache::builder() @@ -40,12 +46,12 @@ impl Cache { .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(), - glyph_cache_tex: renderer.create_dynamic_texture(glyph_cache_dims), + glyph_cache_tex, graphic_cache: GraphicCache::new(renderer), }) } - pub fn glyph_cache_tex(&self) -> &Texture { &self.glyph_cache_tex } + pub fn glyph_cache_tex(&self) -> &(Texture, UiTextureBindGroup) { &self.glyph_cache_tex } pub fn cache_mut_and_tex( &mut self, @@ -53,7 +59,7 @@ impl Cache { &mut GraphicCache, &mut TextCache, &mut GlyphCache<'static>, - &Texture, + &(Texture, UiTextureBindGroup), ) { ( &mut self.graphic_cache, @@ -89,7 +95,11 @@ impl Cache { .scale_tolerance(SCALE_TOLERANCE) .position_tolerance(POSITION_TOLERANCE) .build(); - self.glyph_cache_tex = renderer.create_dynamic_texture(cache_dims); + self.glyph_cache_tex = { + let tex = renderer.create_dynamic_texture(cache_dims); + let bind = renderer.ui_bind_texture(&tex); + (tex, bind) + }; Ok(()) } } diff --git a/voxygen/src/ui/ice/renderer/mod.rs b/voxygen/src/ui/ice/renderer/mod.rs index c41c8ad67f..a2778d3d88 100644 --- a/voxygen/src/ui/ice/renderer/mod.rs +++ b/voxygen/src/ui/ice/renderer/mod.rs @@ -16,7 +16,7 @@ use super::{ use crate::{ render::{ create_ui_quad, create_ui_quad_vert_gradient, Consts, DynamicModel, Mesh, Renderer, - UiDrawer, UiLocals, UiLocalsBindGroup, UiMode, UiVertex, + UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, Error, }; @@ -85,10 +85,9 @@ pub struct IcedRenderer { // Model for drawing the ui model: DynamicModel, // Consts to specify positions of ingame elements (e.g. Nametags) - ingame_locals: Vec<(Consts, UiLocalsBindGroup)>, + ingame_locals: Vec, // Consts for default ui drawing position (ie the interface) - interface_locals: (Consts, UiLocalsBindGroup), - //default_globals: Consts, + interface_locals: UiBoundLocals, // Used to delay cache resizing until after current frame is drawn //need_cache_resize: bool, @@ -125,18 +124,13 @@ impl IcedRenderer { let (half_res, align, p_scale) = Self::calculate_resolution_dependents(physical_resolution, scaled_resolution); - let interface_locals = { - let locals = renderer.create_consts(&[UiLocals::default()]); - let bind = renderer.ui_bind_locals(&locals); - (locals, bind) - }; + let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]); Ok(Self { cache: Cache::new(renderer, default_font)?, draw_commands: Vec::new(), model: renderer.create_dynamic_model(100), interface_locals, - //default_globals: renderer.create_consts(&[Globals::default()]), ingame_locals: Vec::new(), mesh: Mesh::new(), glyphs: Vec::new(), @@ -770,15 +764,9 @@ impl IcedRenderer { } } - pub fn render<'pass_ref, 'pass: 'pass_ref, 'data: 'pass>( - &'data self, - drawer: &mut UiDrawer<'pass_ref, 'pass>, /* maybe_globals: Option<&Consts> */ - ) { + pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) { span!(_guard, "render", "IcedRenderer::render"); - let mut drawer = drawer.prepare(&self.interface_locals.1, &self.model, self.window_scissor); - //let mut scissor = self.window_scissor; - //let globals = maybe_globals.unwrap_or(&self.default_globals); - //let mut locals = &self.interface_locals.1; + let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor); for draw_command in self.draw_commands.iter() { match draw_command { DrawCommand::Scissor(new_scissor) => { @@ -786,11 +774,11 @@ impl IcedRenderer { }, DrawCommand::WorldPos(index) => { drawer.set_locals( - index.map_or(&self.interface_locals.1, |i| &self.ingame_locals[i].1), + index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]), ); }, DrawCommand::Draw { kind, verts } => { - // TODO: don't make these assert!(!verts.is_empty()); + // TODO: don't make these: assert!(!verts.is_empty()); let tex = match kind { DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), DrawKind::Plain => self.cache.glyph_cache_tex(), diff --git a/voxygen/src/ui/mod.rs b/voxygen/src/ui/mod.rs index c97e6f5661..87bf14b0d6 100644 --- a/voxygen/src/ui/mod.rs +++ b/voxygen/src/ui/mod.rs @@ -26,7 +26,7 @@ pub use widgets::{ use crate::{ render::{ create_ui_quad, create_ui_tri, Consts, DynamicModel, Globals, Mesh, RenderError, Renderer, - UiLocals, UiMode, UiVertex, + UiBoundLocals, UiDrawer, UiLocals, UiMode, UiVertex, }, window::Window, Error, @@ -111,10 +111,9 @@ pub struct Ui { // Model for drawing the ui model: DynamicModel, // Consts for default ui drawing position (ie the interface) - interface_locals: Consts, - default_globals: Consts, + interface_locals: UiBoundLocals, // Consts to specify positions of ingame elements (e.g. Nametags) - ingame_locals: Vec>, + ingame_locals: Vec, // Window size for updating scaling window_resized: Option>, // Scale factor changed @@ -127,12 +126,15 @@ pub struct Ui { tooltip_manager: TooltipManager, // Item tooltips manager item_tooltip_manager: ItemTooltipManager, + // Scissor for the whole window + window_scissor: Aabr, } impl Ui { pub fn new(window: &mut Window) -> Result { let scale = Scale::new(window, ScaleMode::Absolute(1.0), 1.0); let win_dims = scale.scaled_resolution().into_array(); + let physical_resolution = scale.physical_resolution(); let renderer = window.renderer_mut(); @@ -156,6 +158,8 @@ impl Ui { scale.scale_factor_logical(), ); + let interface_locals = renderer.create_ui_bound_locals(&[UiLocals::default()]); + Ok(Self { ui, image_map: Map::new(), @@ -163,8 +167,7 @@ impl Ui { draw_commands: Vec::new(), mesh: Mesh::new(), model: renderer.create_dynamic_model(100), - interface_locals: renderer.create_consts(&[UiLocals::default()]), - default_globals: renderer.create_consts(&[Globals::default()]), + interface_locals, ingame_locals: Vec::new(), window_resized: None, scale_factor_changed: None, @@ -172,6 +175,7 @@ impl Ui { scale, tooltip_manager, item_tooltip_manager, + window_scissor: default_scissor(physical_resolution), }) } @@ -329,6 +333,7 @@ impl Ui { self.scale.window_resized(new_dims); let (w, h) = self.scale.scaled_resolution().into_tuple(); self.ui.handle_event(Input::Resize(w, h)); + self.window_scissor = default_scissor(self.scale.physical_resolution()); // Avoid panic in graphic cache when minimizing. // Avoid resetting cache if window size didn't change @@ -568,7 +573,7 @@ impl Ui { .map(|x| [255, 255, 255, *x]) .collect::>(); - renderer.update_texture(cache_tex, offset, size, &new_data); + renderer.update_texture(&cache_tex.0, offset, size, &new_data); }) { // FIXME: If we actually hit this error, it's still possible we could salvage // things in various ways (for instance, the current queue might have extra @@ -604,7 +609,7 @@ impl Ui { let mut current_state = State::Plain; let mut start = 0; - let window_scissor = default_scissor(renderer); + let window_scissor = self.window_scissor; let mut current_scissor = window_scissor; let mut ingame_local_index = 0; @@ -954,7 +959,7 @@ impl Ui { ) } else { self.ingame_locals - .push(renderer.create_consts(&[world_pos.into()])); + .push(renderer.create_ui_bound_locals(&[world_pos.into()])); } self.draw_commands .push(DrawCommand::WorldPos(Some(ingame_local_index))); @@ -1006,42 +1011,38 @@ impl Ui { renderer.update_model(&self.model, &self.mesh, 0); } - pub fn render(&self, renderer: &mut Renderer, maybe_globals: Option<&Consts>) { + pub fn render<'pass, 'data: 'pass>(&'data self, drawer: &mut UiDrawer<'_, 'pass>) { span!(_guard, "render", "Ui::render"); - let mut scissor = default_scissor(renderer); - let globals = maybe_globals.unwrap_or(&self.default_globals); - let mut locals = &self.interface_locals; + let mut drawer = drawer.prepare(&self.interface_locals, &self.model, self.window_scissor); for draw_command in self.draw_commands.iter() { match draw_command { DrawCommand::Scissor(new_scissor) => { - scissor = *new_scissor; + drawer.set_scissor(*new_scissor); }, DrawCommand::WorldPos(index) => { - locals = index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]); + drawer.set_locals( + index.map_or(&self.interface_locals, |i| &self.ingame_locals[i]), + ); }, DrawCommand::Draw { kind, verts } => { - //let tex = match kind { - // DrawKind::Image(tex_id) => - // self.cache.graphic_cache().get_tex(*tex_id), - // DrawKind::Plain => self.cache.glyph_cache_tex(), - //}; - //let model = self.model.submodel(verts.clone()); - // TODO - //renderer.render_ui_element(model, tex, scissor, globals, - // locals); + let tex = match kind { + DrawKind::Image(tex_id) => self.cache.graphic_cache().get_tex(*tex_id), + DrawKind::Plain => self.cache.glyph_cache_tex(), + }; + drawer.draw(&tex.1, verts.clone()); // Note: trivial clone }, } } } } -fn default_scissor(renderer: &Renderer) -> Aabr { - let (screen_w, screen_h) = renderer.resolution().into_tuple(); +fn default_scissor(physical_resolution: Vec2) -> Aabr { + let (screen_w, screen_h) = physical_resolution.into_tuple(); Aabr { min: Vec2 { x: 0, y: 0 }, max: Vec2 { - x: screen_w as u16, - y: screen_h as u16, + x: screen_w, + y: screen_h, }, } }