You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am working on split screen game with 1-4 players. I'm seeing weird squeezed rendering in 2 player mode (where the screen is split vertically in the middle into higher than wider blocks) but not in 4 player mode (where the screen is split into wider than higher blocks in the exact same size of the window). Here's a screenshot of what the weird rendering looks like:
Similarly, here's the same screen with 4 players
As soon as I re-size the 2-player window, the artefact disappears and everything looks correct.
I tried to re-implement the gist of what I'm doing in a minimal project, but I can't replicate the issue there. I will share this minimal-working-version nonetheless to give an overview of what my code does.
I tried a variety of things, including manually setting the camera sizes, resetting cameras, changing the order of systems etc, to no avail. One difference between my minimal project and the actual project is that the actual project:
Initially installs another camera in a menu screen (and then removes it)
Loads meshes from the assets
Caches some meshes.
My gut feeling is that somehow the initial camera (that is the size of the window) caches some attributes and then the new split screen cameras (that are of a different size) have some wrong attributes cached until I resize the window and the cache is reset. But I can't replicate this behaviour and don't know enough about bevy to understand where to look.
Would love some help. Maybe I need to reset something somewhere that I don't know about? Thanks in advance!
The Minimal (but working) code:
use bevy::core_pipeline::clear_color::ClearColorConfig;use bevy::ecs::schedule::ShouldRun;use bevy::render::camera::Viewport;use bevy::window::{close_on_esc,WindowId,WindowResized};use bevy::{log::LogSettings, prelude::*};constSIZE:f32 = 0.25;constPLAYER_Y:f32 = 4.5;#[derive(Component)]structPlayerCamera(usize);#[derive(PartialEq,Eq,Clone,Copy,Debug,Hash)]enumGameState{Loading,Running,}implGameState{fnis_running(state:Res<State<GameState>>) -> ShouldRun{(state.current() == &GameState::Running).into()}}fnmain(){App::new().insert_resource(LogSettings{filter:"info,wgpu_core=warn,wgpu_hal=warn,pacbomber=debug".into(),level: bevy::log::Level::DEBUG,}).insert_resource(ClearColor(Color::rgb(20. / 255.,20. / 255.,20. / 255.))).insert_resource(WindowDescriptor{title:"Test".to_string(),width:900.,height:660.,resizable:true,
..default()}).add_plugins(DefaultPlugins)// .add_plugin(LogDiagnosticsPlugin::default())// .add_plugin(FrameTimeDiagnosticsPlugin::default()).add_system_set(SystemSet::on_enter(GameState::Loading).with_system(build_level_system)).add_system_set(SystemSet::on_enter(GameState::Running).with_system(set_camera_viewports)).add_system_set(SystemSet::new().with_run_criteria(GameState::is_running).with_system(keyboard_system).with_system(move_camera_system).with_system(close_on_esc).with_system(detect_resize_events),).add_state(GameState::Loading).run();}#[derive(Component)]structPlayer;fnbuild_level_system(mutcommands:Commands,mutmeshes:ResMut<Assets<Mesh>>,mutmaterials:ResMut<Assets<StandardMaterial>>,mutstate:ResMut<State<GameState>>,){info!("build level");// 4 playersfor player in0..=1{let clear_color = if player == 0{ClearColorConfig::Default}else{ClearColorConfig::None};
commands
.spawn(Camera3dBundle{transform:Transform::from_xyz(0.0,PLAYER_Y,3.0).looking_at(Vec3::ZERO,Vec3::Y),camera:Camera{// Renders the right camera after the left camera, which has a default priority of 0priority:(player asisize),
..default()},camera_3d:Camera3d{
clear_color,
..Default::default()},
..default()}).insert(PlayerCamera(player));}let player = meshes.add(Mesh::from(shape::Cube{size:SIZE}));let player_material = materials.add(StandardMaterial{base_color:Color::YELLOW,metallic:0.5,reflectance:0.15,
..Default::default()});
commands
.spawn(PbrBundle{mesh: player,material: player_material,transform:Transform::from_xyz(10.*SIZE,0.5,10.*SIZE),
..Default::default()}).insert(Player);let floor = meshes.add(Mesh::from(shape::Plane{size:SIZE - 0.01}));let floor_material = materials.add(StandardMaterial{base_color:Color::RED,metallic:0.5,reflectance:0.15,perceptual_roughness:0.5,
..Default::default()});let offset = SIZE* -10.;let(mut x,mut z) = (offset, offset);for zc in0..=128{
z += SIZE;for xc in0..=128{
x += SIZE;
commands.spawn(PbrBundle{mesh: floor.clone(),material: floor_material.clone(),transform:Transform::from_xyz(x, -0.1, z),
..Default::default()});// every corner a lightmatch(zc, xc){(1,1) => spawn_light(&mut commands, x, z),(1,127) => spawn_light(&mut commands, x, z),(127,127) => spawn_light(&mut commands, x, z),(127,1) => spawn_light(&mut commands, x, z),(64,64) => spawn_light(&mut commands, x, z),(64,1) => spawn_light(&mut commands, x, z),(1,64) => spawn_light(&mut commands, x, z),
_ => (),}}
x = offset;}
state.overwrite_replace(GameState::Running).unwrap();}fnspawn_light(commands:&mutCommands,x:f32,z:f32){
commands.spawn(PointLightBundle{point_light:PointLight{intensity:350.0,shadows_enabled:true,
..default()},transform:Transform::from_xyz(x,1.0, z),
..default()});}fnkeyboard_system(keyboard_input:Res<Input<KeyCode>>,mutplayer:Query<&mutTransform,With<Player>>,){let speed = 0.15;for(code,(d_x, d_z))in[(KeyCode::Left,(-1,0)),(KeyCode::Right,(1,0)),(KeyCode::Up,(0, -1)),(KeyCode::Down,(0,1)),]{if keyboard_input.pressed(code) || keyboard_input.just_pressed(code){let(x, z) = ((d_x asf32)* speed,(d_z asf32)* speed);formut transform in player.iter_mut(){
transform.translation.x += x;
transform.translation.z += z;}}}}fnmove_camera_system(player_query:Query<&Transform,(With<Player>,Without<PlayerCamera>)>,mutcamera_query:Query<(&Camera,&mutTransform),With<PlayerCamera>>,){for transform in player_query.iter(){let player_pos = transform.translation;for(_,mut transform)in camera_query.iter_mut(){*transform =
Transform::from_xyz(player_pos.x,PLAYER_Y - player_pos.y, player_pos.z + 3.0).looking_at(player_pos,Vec3::Y);}}}fndetect_resize_events(windows:Res<Windows>,mutresize_events:EventReader<WindowResized>,camera_query:Query<(&mutCamera,&PlayerCamera)>,){for resize_event in resize_events.iter(){if resize_event.id == WindowId::primary(){info!("resize event");set_camera_viewports(windows, camera_query);break;}}}fnset_camera_viewports(windows:Res<Windows>,mutcamera_query:Query<(&mutCamera,&PlayerCamera)>,){info!("set viewport");let window = windows.primary();let(w, h) = (window.physical_width(), window.physical_height());fnpad(x:u32,y:u32,w:u32,h:u32) -> (u32,u32,u32,u32){let padding = 4;(x + padding, y + padding, w - padding *2, h - padding *2)}let stupid_map:&[&[(u32,u32,u32,u32)]] = &[// Easy mode: One player&[pad(0,0, w, h)],// Two Players&[pad(0,0, w / 2, h),pad(w / 2,0, w / 2, h)],// Three players&[pad(0,0, w / 2, h / 2),pad(w / 2,0, w / 2, h / 2),pad(0, h / 2, w / 2, h / 2),],// Four players&[pad(0,0, w / 2, h / 2),pad(w / 2,0, w / 2, h / 2),pad(0, h / 2, w / 2, h / 2),pad(w / 2, h / 2, w / 2, h / 2),],];let total = camera_query.iter().count();for(mut camera, player_camera)in camera_query.iter_mut(){let(x, y, w, h) = stupid_map[total - 1][player_camera.0];
camera.viewport = Some(Viewport{physical_position:UVec2::new(x, y),physical_size:UVec2::new(w, h),
..default()});}}
The text was updated successfully, but these errors were encountered:
So it seems the bug is that creating a camera without a viewport and then setting the viewport at a later time (e.g. a couple of frames after) is not applied correctly.
Bevy version
Bevy Main (7989cb2)
[Optional] Relevant system information
M1 MacBook Pro (macOS 12.6):
What you did
I am working on split screen game with 1-4 players. I'm seeing weird squeezed rendering in 2 player mode (where the screen is split vertically in the middle into higher than wider blocks) but not in 4 player mode (where the screen is split into wider than higher blocks in the exact same size of the window). Here's a screenshot of what the weird rendering looks like:
Similarly, here's the same screen with 4 players
As soon as I re-size the 2-player window, the artefact disappears and everything looks correct.
I tried to re-implement the gist of what I'm doing in a minimal project, but I can't replicate the issue there. I will share this minimal-working-version nonetheless to give an overview of what my code does.
I tried a variety of things, including manually setting the camera sizes, resetting cameras, changing the order of systems etc, to no avail. One difference between my minimal project and the actual project is that the actual project:
My gut feeling is that somehow the initial camera (that is the size of the window) caches some attributes and then the new split screen cameras (that are of a different size) have some wrong attributes cached until I resize the window and the cache is reset. But I can't replicate this behaviour and don't know enough about bevy to understand where to look.
Would love some help. Maybe I need to reset something somewhere that I don't know about? Thanks in advance!
The Minimal (but working) code:
The text was updated successfully, but these errors were encountered: