Rust中相机控制器卡顿缓慢问题的优化方案咨询
相机移动卡顿、不稳定的优化方案
问题背景
使用Rust语言结合OpenGL封装库Glium开发3D渲染程序,已完成基础3D模型与相机搭建,正在适配相机控制器。目前通过device_query检测键盘输入修改相机x、y坐标实现移动,但存在移动不稳定、卡顿的问题。
当前事件循环代码
event_loop.run(move |event, _, control_flow| { let next_frame_time = std::time::Instant::now() + std::time::Duration::from_nanos(16_666_667); ####### This is where I change the coordinates ######## x = keyboardinput::keyboard_input_x(x); y = keyboardinput::keyboard_input_y(y); *control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time); match event { glutin::event::Event::WindowEvent { event, .. } => match event { glutin::event::WindowEvent::CloseRequested => { *control_flow = glutin::event_loop::ControlFlow::Exit; return; } _ => return, }, glutin::event::Event::NewEvents(cause) => match cause { glutin::event::StartCause::ResumeTimeReached { .. } => (), glutin::event::StartCause::Init => (), _ => return, }, _ => return, }
当前键盘输入模块代码
use device_query::{DeviceQuery, DeviceState, Keycode}; pub fn keyboard_input_x(mut x: f32) -> f32 { let device_state = DeviceState::new(); let keys: Vec<Keycode> = device_state.get_keys(); for key in keys.iter() { println!("Pressed key: {:?}", key); if key == &Keycode::W { x -= 0.03; return x; } if key == &Keycode::S { x += 0.03; return x; } } return x; } pub fn keyboard_input_y(mut y: f32) -> f32 { let device_state = DeviceState::new(); let keys: Vec<Keycode> = device_state.get_keys(); for key in keys.iter() { println!("Pressed key: {:?}", key); if key == &Keycode::Space { y += 0.03; return y; } if key == &Keycode::LControl { y -= 0.03; return y; } } return y; }
优化方案
1. 替换轮询式输入为Glutin原生事件驱动
device_query采用轮询方式检测输入,容易导致状态不一致、响应延迟,改用Glutin原生键盘事件跟踪按键状态:
- 定义按键状态结构体,用于记录按键按下/释放状态:
#[derive(Default)] struct KeyState { w_pressed: bool, s_pressed: bool, space_pressed: bool, lctrl_pressed: bool, } // 在事件循环外部初始化按键状态 let mut key_state = KeyState::default();
- 修改事件循环,处理键盘按下/释放事件,更新按键状态:
event_loop.run(move |event, _, control_flow| { let next_frame_time = std::time::Instant::now() + std::time::Duration::from_nanos(16_666_667); *control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time); match event { glutin::event::Event::WindowEvent { event, .. } => match event { glutin::event::WindowEvent::CloseRequested => { *control_flow = glutin::event_loop::ControlFlow::Exit; return; } glutin::event::WindowEvent::KeyboardInput { input, .. } => { let pressed = input.state == glutin::event::ElementState::Pressed; match input.virtual_keycode { Some(glutin::event::VirtualKeyCode::W) => key_state.w_pressed = pressed, Some(glutin::event::VirtualKeyCode::S) => key_state.s_pressed = pressed, Some(glutin::event::VirtualKeyCode::Space) => key_state.space_pressed = pressed, Some(glutin::event::VirtualKeyCode::LControl) => key_state.lctrl_pressed = pressed, _ => {} } } _ => {} }, glutin::event::Event::NewEvents(cause) => match cause { glutin::event::StartCause::ResumeTimeReached { .. } | glutin::event::StartCause::Init => { // 仅在帧更新阶段处理相机移动 update_camera_position(&mut x, &mut y, &key_state); // 执行渲染逻辑 } _ => return, }, _ => return, } });
- 实现相机位置更新函数:
fn update_camera_position(x: &mut f32, y: &mut f32, key_state: &KeyState) { // 可根据需求调整移动速度 let move_speed = 0.1; if key_state.w_pressed { *x -= move_speed; } if key_state.s_pressed { *x += move_speed; } if key_state.space_pressed { *y += move_speed; } if key_state.lctrl_pressed { *y -= move_speed; } }
2. 基于帧间隔时间(Delta Time)稳定移动速度
固定每帧移动距离会因帧率波动导致速度不稳定,通过计算帧间隔时间,将移动速度与时间绑定,保证移动速度恒定:
- 在事件循环外记录上一帧时间:
let mut last_frame_time = std::time::Instant::now();
- 在帧更新阶段计算Delta Time并传入移动函数:
glutin::event::Event::NewEvents(cause) => match cause { glutin::event::StartCause::ResumeTimeReached { .. } | glutin::event::StartCause::Init => { let now = std::time::Instant::now(); let delta_time = now.duration_since(last_frame_time).as_secs_f32(); last_frame_time = now; update_camera_position(&mut x, &mut y, &key_state, delta_time); // 执行渲染逻辑 } _ => return, },
- 修改移动函数,使用Delta Time计算实际移动距离:
fn update_camera_position(x: &mut f32, y: &mut f32, key_state: &KeyState, delta_time: f32) { // 基础移动速度(单位:单位/秒) let base_speed = 2.0; let move_speed = base_speed * delta_time; if key_state.w_pressed { *x -= move_speed; } if key_state.s_pressed { *x += move_speed; } if key_state.space_pressed { *y += move_speed; } if key_state.lctrl_pressed { *y -= move_speed; } }
3. 移除性能消耗操作
原代码中每次调用输入函数都创建DeviceState实例并打印按键信息,会额外消耗系统资源,优化后这些操作全部移除,减少性能开销。
内容的提问来源于stack exchange,提问作者Teer 2008
相关产品推荐
相关产品推荐

