lowenware / dotrix

A 3D engine with ECS and Vulkan renderer for Rust developers
https://dotrix.rs
MIT License
292 stars 11 forks source link

camera control issue #121

Closed ZKpot closed 2 years ago

ZKpot commented 2 years ago

In the demo example it looks like the camera target position update is delayed by one frame, although the order of the player control and camera control systems looks OK. It is easy to see when player starts/stops moving (increase PLAYER_SPEED constant for better effect) .

voxelias commented 2 years ago

Will check

ZKpot commented 2 years ago

Also, some "flickering" can be observed when moving the camera while the player is moving (similar to the point above, increase PLAYER_SPEED constant for better effect).

Xaniaro commented 2 years ago

Hi, sorry for late response. I found the problem. Problem is here:

// dotrix_core/src/application.rs
Event::RedrawRequested(_) => {
    scheduler.run_bind(&mut services, current_state_ptr);
    scheduler.run_standard(&mut services, current_state_ptr);
    scheduler.run_render(&mut services, current_state_ptr);
    scheduler.run_release(&mut services, current_state_ptr);
}

Bind is before standard. So the behaviours is like this:

  1. [Bind] Setup ProjView with current camera target (position)
  2. [Standard] Change player position
  3. [Standard] Change camera target (position) - you will see this change in next frame (step 1)
  4. [Render] Render models with their actual positions.

How to solve that? Swap Bind and standart:

// dotrix_core/src/application.rs
Event::RedrawRequested(_) => {
    scheduler.run_standard(&mut services, current_state_ptr);
    scheduler.run_bind(&mut services, current_state_ptr);
    scheduler.run_render(&mut services, current_state_ptr);
    scheduler.run_release(&mut services, current_state_ptr);
}

Note Overlay will stop working! We need to find a way to fix that. I think we should split bind into 2 separated shedules.

diff

QuantumEntangledAndy commented 2 years ago

This makes sense, bind is for binding data into the gpu buffers so it should probably be directly before the render and after all changes to the data.

What is causing the overlay to fail though?

QuantumEntangledAndy commented 2 years ago

Looking through the code bind seems to be having two jobs.

Perhaps we should look into seperating it into bind for initializing the frames and load for loading data into gpu buffers?

Xaniaro commented 2 years ago

What is causing the overlay to fail though?

In demo example, .with(System::from(ui)) fails. This runs in standard and egui is initialized in bind.

Error: thread 'main' panicked at 'No fonts available until first call to CtxRef::begin_frame()', C:\Users\Xan\.cargo\registry\src\github.com-1ecc6299db9ec823\egui-0.14.2\src\context.rs:417:14

/// Not valid until first call to [`CtxRef::begin_frame()`].
/// That's because since we don't know the proper `pixels_per_point` until then.
pub fn fonts(&self) -> &Fonts {
    &*self
        .fonts
        .as_ref()
        .expect("No fonts available until first call to CtxRef::begin_frame()")
}
QuantumEntangledAndy commented 2 years ago

So we need a stage for initialing things like this right at the begining, and a stage loading uniforms just before render

voxelias commented 2 years ago

RunLevel::Bind and bind systems are related to FRAME binding, not buffers. I will check it and submit a fix.