Рассмотрим две программы и разницу между ними:
$ diff flashes/src/main.rs doesnt_flash/src/main.rs
22,23c22
<
< let mut i = 0;
---
> let mut cursor_poses: Vec<(f64, f64)> = Vec::new();
28c27
< mx = x; my = y;
---
> cursor_poses.push((x,y));
32,33c31,33
< if i == 0 {
< graphics::clear([1.0; 4], g);
---
> graphics::clear([1.0; 4], g);
> for &(x, y) in cursor_poses.iter() {
> draw_cursor_pos([x, y], &c, g);
35,36d34
< draw_cursor_pos([mx, my], &c, g);
< i+=1;
Видео демонстрация двух программ.
Программа представляет собой чрезвычайно базовую программу рисования с единственной шириной кисти, цветом штриховки, размером холста, без сохранения и т.д.; oh и прекратить рисование, вытащите мышь из окна, так как каждый раз, когда вы переходите через окно, это считается рисованием; -)
flashes.rs
не рисует каждый пиксель каждый раз, когда достигается e.render_args()
, за исключением первого раза. doesnt_flash.rs
делает каждый пиксель каждый раз, когда достигается e.render_args()
. Это единственное различие между двумя программами.
Хотя для создания контента в этой программе не требуется много времени, поэтому допустимо повторно генерировать его сотни раз, когда мышь перемещается по окну, это кажется неэффективным. Теоретически, поскольку на экран добавляется все больше точек, каждая итерация gl.draw
занимает больше времени и дольше. На практике разница между вызовами graphics::ellipse
один раз и десять тысяч раз не значительна для современного оборудования.
Другие программы, которые я хочу написать, не будут иметь такой роскоши, так как для получения результата на экране потребуется больше времени.
При изучении API я не нашел очевидного способа просто "ничего не делать". Я предполагаю, что мне придется писать мои изменения экрана в некоторый буферный объект, а затем GlGraphics
вернуть этот буферный объект, если вызывается e.render_args()
, но мне не нужно обновлять экран.
Проблема в том, что я не могу найти этот буферный объект.: - (
Как я могу "ничего не делать", не заставляя мигать экран? Если моя теория верна, как я могу рисовать в буфере GlGraphics
вместо экрана, а затем загружать свой буфер обратно на экран, когда у меня нет ничего нового для рисования?
Cargo.toml
[package]
name = "stackoverflow-piston-example"
version = "0.0.0"
authors = ["Fred"]
description = "Note: This program can be used for both of the programs below. Simply use `cargo new` and save either of the below files as `src/main.rs`"
keywords = []
[dependencies]
piston = "0.35.0"
piston2d-opengl_graphics = "0.50.0"
piston2d-graphics = "0.24.0"
piston2d-touch_visualizer = "0.8.0"
pistoncore-sdl2_window = "0.47.0"
doesnt_flash.rs
extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
extern crate touch_visualizer;
extern crate sdl2_window;
use opengl_graphics::{ GlGraphics, OpenGL };
use graphics::{ Context, Graphics };
use piston::input::*;
use piston::event_loop::*;
use sdl2_window::Sdl2Window as AppWindow;
static CURSOR_POS_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
fn main() {
let opengl = OpenGL::V3_2;
let mut window: AppWindow = piston::window::WindowSettings::new("Example for StackOverflow", [600, 600])
.exit_on_esc(true).opengl(opengl).build().unwrap();
let ref mut gl = GlGraphics::new(opengl);
let (mut mx, mut my) = (0., 0.);
let mut cursor_poses: Vec<(f64, f64)> = Vec::new();
let mut events = Events::new(EventSettings::new().lazy(true));
while let Some(e) = events.next(&mut window) {
e.mouse_cursor(|x, y| {
cursor_poses.push((x,y));
});
if let Some(args) = e.render_args() {
gl.draw(args.viewport(), |c, g| {
graphics::clear([1.0; 4], g);
for &(x, y) in cursor_poses.iter() {
draw_cursor_pos([x, y], &c, g);
}
}
);
}
}
}
fn draw_cursor_pos<G: Graphics>(
cursor: [f64; 2],
c: &Context,
g: &mut G,
) {
graphics::ellipse(
CURSOR_POS_COLOR,
graphics::ellipse::circle(cursor[0], cursor[1], 4.0),
c.transform,
g
);
}
flashes.rs
extern crate piston;
extern crate opengl_graphics;
extern crate graphics;
extern crate touch_visualizer;
extern crate sdl2_window;
use opengl_graphics::{ GlGraphics, OpenGL };
use graphics::{ Context, Graphics };
use piston::input::*;
use piston::event_loop::*;
use sdl2_window::Sdl2Window as AppWindow;
static CURSOR_POS_COLOR: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
fn main() {
let opengl = OpenGL::V3_2;
let mut window: AppWindow = piston::window::WindowSettings::new("Example for StackOverflow", [600, 600])
.exit_on_esc(true).opengl(opengl).build().unwrap();
let ref mut gl = GlGraphics::new(opengl);
let (mut mx, mut my) = (0., 0.);
let mut i = 0;
let mut events = Events::new(EventSettings::new().lazy(true));
while let Some(e) = events.next(&mut window) {
e.mouse_cursor(|x, y| {
mx = x; my = y;
});
if let Some(args) = e.render_args() {
gl.draw(args.viewport(), |c, g| {
if i == 0 {
graphics::clear([1.0; 4], g);
}
draw_cursor_pos([mx, my], &c, g);
i+=1;
}
);
}
}
}
fn draw_cursor_pos<G: Graphics>(
cursor: [f64; 2],
c: &Context,
g: &mut G,
) {
graphics::ellipse(
CURSOR_POS_COLOR,
graphics::ellipse::circle(cursor[0], cursor[1], 4.0),
c.transform,
g
);
}