-
Notifications
You must be signed in to change notification settings - Fork 271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Camera jitters when you look and move at same time #294
Comments
I'm not able to replicate it on my machine. Are you on M1? |
Same problem. I am able to replicate it on Linux + Wayland and even with Windows build under Wine. |
Hmm, I wonder if it's an integrated graphics thing. I'm running on a discrete Nvidia GPU. |
I tried my discrete Nvidia GPU and still able to replicate this issue. |
I have not been able to reproduce the problem but I wonder if the problem is actually on the input side. In the update_camera method there are many lines of code that depend on dt, a value that changes proportionally to the time of the last redraw (i.e. it is frame dependent).
Edit: I don't think it's a useful question to solve the problem anymore, I found material on the internet about it and I'll write it in another message |
I found this problem described in some forum about gamedev unity, example: I don't know if this would fix it in our case, what I expect is that unity has a pipelined renderer across multiple threads (so game and input logic is parallel to that of draw, or at least any serious engine has a similar system). There is also this page which is interesting: |
I agree with @CatCode79, it would make sense that this is some weirdness with the input. @dartvader316, try putting the update method after the render match statement and turn v-sync back on. See if that fixes it. The Event::RedrawRequested(window_id) if window_id == state.window().id() => {
let now = instant::Instant::now();
let dt = now - last_render_time;
last_render_time = now;
match state.render() {
Ok(_) => {}
// Reconfigure the surface if it's lost or outdated
Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => state.resize(state.size),
// The system is out of memory, we should probably quit
Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
// We're ignoring timeouts
Err(wgpu::SurfaceError::Timeout) => log::warn!("Surface timeout"),
}
state.update(dt); // Updated!
} |
I'm able to reproduce this issue on Windows, even using what @sotrh suggested, the jittering persists. |
@BlackGoku36 and @jaydevelopsstuff , do either of you get the same jittering when just moving via the keyboard? |
No, the jittering only occurred for me when moving the mouse around. |
Same here on Linux, X11, disabling vsync fixed it, but not ideal :/ |
Ok, I think I found out why & a couple solutions. The problem The solution(s) Basically we average the MouseMotion, simply, instead of assigning, we add all the motion deltas together, also keeping track of how many we added, then at some point (I do it before the mouse_delta calcualtions) you calculate the actual average mouse motion of that "frame" and then reset it all back to zero & repeat. My code looks something like // Wherever you track your mouse_pos I use an InputState struct that gets passed to my update method
self.mouse_delta += Vector2(..);
self.mouse_samples += 1;
/*
...
...
*/
// In our update method
let mut real_delta = Vector2::zeroes(); // I'm using Nalgebra idk if its the same in cgmath
if input.mouse_samples != 0 { // Have to make sure they actually moved the mouse or we get / by 0
real_delta = input.mouse_delta / (input.mouse_samples as f32);
}
// do calculations with real_delta now
input.mouse_delta = Vector2::zeroes();
input.mouse_samples = 0 Below is a video of a before and after Before.mp4After.mp4I don't know how well that comes across on video but on my 144hz monitor its a world of difference. Anyway hopes this helps. Still not sure why only some people seemed to experience this though. |
Glad you found a work around. Currently threading is not supported on web directly, so unless I want to mess around with web workers and offscreen canvas, the motion averaging/disabling vsync might be the best idea. |
Instead of averaging multiple For example: // inside State struct
fn update_camera_rotation(&mut self) {
self.camera_controller.update_camera_rotation(&mut self.camera);
}
// inside State.update()
fn update(&mut self) {
self.camera_controller.update_camera_position(&mut self.camera, self.delta_time_f32);
// everything else
// ...
}
// mouse motion event
Event::DeviceEvent {
event: DeviceEvent::MouseMotion { delta },
..
} => {
state.camera_controller.process_mouse(delta.0, delta.1);
state.update_camera_rotation();
}
// camera.rs
pub fn update_camera_rotation(&mut self, camera: &mut Camera) {
camera.yaw += Rad(self.rotate_horizontal) * self.sensitivity;
camera.pitch += Rad(-self.rotate_vertical) * self.sensitivity;
self.rotate_horizontal = 0.0;
self.rotate_vertical = 0.0;
if camera.pitch < -Rad(SAFE_FRAC_PI_2) {
camera.pitch = -Rad(SAFE_FRAC_PI_2);
} else if camera.pitch > Rad(SAFE_FRAC_PI_2) {
camera.pitch = Rad(SAFE_FRAC_PI_2);
}
}
pub fn update_camera_position(&mut self, camera: &mut Camera, dt: f32) {
// everything else left over from update_camera()
// ...
} learn-wgpu-mouse-fix.mp4 |
To see this jitter, you should circle around an object, while looking at it.
Untitled.mp4
Maybe it is not much visible in the above video. But it will be clearly visible if you, try it on a single triangle.
Platform: x86_64 macOS
The text was updated successfully, but these errors were encountered: