【问题标题】:Set frame redraw rate in glium?在 glium 中设置帧重绘率?
【发布时间】:2020-05-01 16:35:27
【问题描述】:

我正在尝试使用 rust 中的 glium 制作游戏循环。我的目标是让屏幕每秒重绘 60 次。使用我拥有的当前事件循环代码,只有在窗口大小发生变化时才会重绘框架。我在 glutin docs 中读到,我需要在某个地方调用 request_redraw,但我不确定如何/在哪里。到目前为止,这是我的代码:

event_loop.run(move |event, _target, control_flow| match event {
    Event::LoopDestroyed => return,
    Event::WindowEvent {
        window_id: _window_id,
        event: winevent,
    } => match winevent {
        WindowEvent::Resized(physical_size) => display.gl_window().resize(physical_size),
        WindowEvent::CloseRequested => {
            *control_flow = ControlFlow::Exit;
        }
        _ => {}
    },
    Event::RedrawRequested(_window_id) => {
        let mut target = display.draw();
        target.clear_color_srgb(rng.gen(), rng.gen(), rng.gen(), 1.0);
        target.finish().unwrap();
    }
    _ => {}
});

【问题讨论】:

  • 我可能跑题了 - 但这看起来像 winit 事件循环,对吗?
  • @chub500 我认为 glium 确实使用了 winit,是的。
  • 我对 glium 不太熟悉 - display 是什么类型?
  • 没关系哈哈找到了。你的 display 是一个 glium Surface 对象,对吧?
  • 您必须在这段代码上方创建了一个winit 窗口实例对吗?

标签: rust game-loop glium


【解决方案1】:

我之前没有使用过glium(我已经有一段时间直接使用Vulkano 制作了一些图形应用程序)。但是,仔细阅读 API,您似乎可以通过一系列 api 从winit 获取您的 Window 句柄。我在下面的代码中概述了它们。像下面这样的东西应该适合你。关键是从winit 访问Window 句柄。滚动浏览Window API,您应该会看到:request_redraw。然后,您可以像这样在事件处理程序周围插入游戏循环逻辑:

use std::time::Instant;
use glium::Display;
use winit::event_loop::{EventLoop, ControlFlow};
use winit::event::{Event, WindowEvent};
use winit::window::Window;

const TARGET_FPS: u64 = 60;

/* ... some function for main loop ... */

let display: Display = ... /* glium Display instance */

event_loop.run(move |event, _target, control_flow| {
    let start_time = Instant::now();
    match event {
        Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => {
            *control_flow = ControlFlow::Exit;
        },
        ...
    /*
     * Process events here
     */
    }
    match *control_flow {
        ControlFlow::Exit => (),
        _ => {
            /*
             * Grab window handle from the display (untested - based on API)
             */
            display.gl_window().window().request_redraw();
            /*
             * Below logic to attempt hitting TARGET_FPS.
             * Basically, sleep for the rest of our milliseconds
             */
            let elapsed_time = Instant::now().duration_since(start_time).as_millis() as u64;

            let wait_millis = match 1000 / TARGET_FPS >= elapsed_time {
                true => 1000 / TARGET_FPS - elapsed_time,
                false => 0
            };
            let new_inst = start_time + std::time::Duration::from_millis(wait_millis);
            *control_flow = ControlFlow::WaitUntil(new_inst);
        }
    }
});

【讨论】:

  • 有没有办法避免为每个事件请求重绘?例如,我不想每次移动鼠标时都重新绘制框架。
  • 是的 - 我通常有一个 Context 变量,它告诉我我的状态是否有任何变化。如果Context 表示更改,我只请求重绘。
猜你喜欢
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多