Skip to content

Commit 60e3e34

Browse files
committed
Adopt Taj's example
1 parent 11147b9 commit 60e3e34

File tree

2 files changed

+125
-24
lines changed

2 files changed

+125
-24
lines changed

sparse_strips/vello_hybrid/examples/scenes/src/clip.rs

Lines changed: 82 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,50 @@ use vello_hybrid::Scene;
1919

2020
/// Clip scene state
2121
#[derive(Debug)]
22-
pub struct ClipScene {}
22+
pub struct ClipScene {
23+
use_clip_path: bool,
24+
num_circles: usize,
25+
}
2326

2427
impl ExampleScene for ClipScene {
2528
fn render(&mut self, ctx: &mut Scene, root_transform: Affine) {
26-
render(ctx, root_transform);
29+
render(ctx, root_transform, self.use_clip_path, self.num_circles);
30+
}
31+
32+
fn handle_key(&mut self, key: &str) -> bool {
33+
match key {
34+
"c" | "C" => {
35+
self.toggle_clip();
36+
true
37+
}
38+
"m" | "M" => {
39+
self.add_circle();
40+
true
41+
}
42+
_ => false,
43+
}
2744
}
2845
}
2946

3047
impl ClipScene {
3148
/// Create a new `ClipScene`
3249
pub fn new() -> Self {
33-
Self {}
50+
Self {
51+
use_clip_path: false,
52+
num_circles: 1,
53+
}
54+
}
55+
56+
/// Toggle using clip path
57+
pub fn toggle_clip(&mut self) {
58+
self.use_clip_path = !self.use_clip_path;
59+
println!("Use clip path: {}", self.use_clip_path);
60+
}
61+
62+
/// Add another circle to the scene
63+
pub fn add_circle(&mut self) {
64+
self.num_circles += 1;
65+
println!("Number of circles: {}", self.num_circles);
3466
}
3567
}
3668

@@ -48,7 +80,7 @@ fn draw_clipping_outline(ctx: &mut Scene, path: &BezPath) {
4880
}
4981

5082
/// Draws a deeply nested clip of circles.
51-
pub fn render(ctx: &mut Scene, root_transform: Affine) {
83+
pub fn render(ctx: &mut Scene, root_transform: Affine, use_clip_path: bool, num_circles: usize) {
5284
const INITIAL_RADIUS: f64 = 48.0;
5385
const RADIUS_DECREMENT: f64 = 2.5;
5486
const INNER_COUNT: usize = 10;
@@ -68,26 +100,57 @@ pub fn render(ctx: &mut Scene, root_transform: Affine) {
68100
DARK_GREEN,
69101
];
70102

71-
const COVER_RECT: Rect = Rect::new(0.0, 0.0, 100.0, 100.0);
72-
const CENTER: Point = Point::new(50.0, 50.0);
73-
let mut radius = INITIAL_RADIUS;
103+
const SPACING: f64 = 120.0;
104+
const BASE_X: f64 = 50.0;
105+
const BASE_Y: f64 = 50.0;
74106

75107
ctx.set_transform(root_transform);
76-
for _ in 0..outer_count {
77-
for color in COLORS.iter() {
78-
let clip_circle = Circle::new(CENTER, radius).to_path(0.1);
79-
draw_clipping_outline(ctx, &clip_circle);
80-
ctx.push_clip_layer(&clip_circle);
81108

82-
ctx.set_paint(*color);
83-
ctx.fill_rect(&COVER_RECT);
109+
// Draw multiple circles in a checkerboard pattern
110+
for circle_idx in 0..num_circles {
111+
// Calculate checkerboard position
112+
// Create a grid pattern where circles are placed in a checkerboard layout
113+
let row = circle_idx / 4;
114+
let col = circle_idx % 4;
115+
116+
// Create checkerboard offset pattern
117+
let offset_x = if (row + col) % 2 == 0 {
118+
0.0
119+
} else {
120+
SPACING / 2.0
121+
};
122+
let x = BASE_X + col as f64 * SPACING + offset_x;
123+
let y = BASE_Y + row as f64 * SPACING;
124+
125+
let center = Point::new(x, y);
126+
let cover_rect = Rect::new(x - 50.0, y - 50.0, x + 50.0, y + 50.0);
127+
let mut radius = INITIAL_RADIUS;
128+
129+
for _ in 0..outer_count {
130+
for color in COLORS.iter() {
131+
let clip_circle = Circle::new(center, radius).to_path(0.1);
132+
draw_clipping_outline(ctx, &clip_circle);
133+
if use_clip_path {
134+
ctx.push_clip_path(&clip_circle);
135+
} else {
136+
ctx.push_clip_layer(&clip_circle);
137+
}
84138

85-
radius -= RADIUS_DECREMENT;
139+
ctx.set_paint(*color);
140+
ctx.fill_rect(&cover_rect);
141+
142+
radius -= RADIUS_DECREMENT;
143+
}
86144
}
87-
}
88-
for _ in 0..outer_count {
89-
for _ in COLORS.iter() {
90-
ctx.pop_layer();
145+
146+
for _ in 0..outer_count {
147+
for _ in COLORS.iter() {
148+
if !use_clip_path {
149+
ctx.pop_layer();
150+
} else {
151+
ctx.pop_clip_path();
152+
}
153+
}
91154
}
92155
}
93156
}

sparse_strips/vello_hybrid/examples/winit/src/main.rs

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use render_context::{RenderContext, RenderSurface, create_vello_renderer, create
88
#[cfg(not(target_arch = "wasm32"))]
99
use std::env;
1010
use std::sync::Arc;
11+
use std::time::Instant;
1112
use vello_common::color::palette::css::WHITE;
1213
use vello_common::color::{AlphaColor, Srgb};
1314
use vello_common::kurbo::{Affine, Point};
@@ -45,6 +46,10 @@ struct App<'s> {
4546
transform: Affine,
4647
mouse_down: bool,
4748
last_cursor_position: Option<Point>,
49+
last_frame_time: Option<Instant>,
50+
frame_count: u32,
51+
fps_update_time: Instant,
52+
accumulated_frame_time: f64,
4853
}
4954

5055
fn main() {
@@ -77,6 +82,7 @@ fn main() {
7782
#[cfg(target_arch = "wasm32")]
7883
let (scenes, start_scene_index) = (get_example_scenes(), 0);
7984

85+
let now = Instant::now();
8086
let mut app = App {
8187
context: RenderContext::new(),
8288
renderers: vec![],
@@ -87,6 +93,10 @@ fn main() {
8793
transform: Affine::IDENTITY,
8894
mouse_down: false,
8995
last_cursor_position: None,
96+
last_frame_time: None,
97+
frame_count: 0,
98+
fps_update_time: now,
99+
accumulated_frame_time: 0.0,
90100
};
91101

92102
let event_loop = EventLoop::new().unwrap();
@@ -130,7 +140,7 @@ impl ApplicationHandler for App<'_> {
130140
window.clone(),
131141
size.width,
132142
size.height,
133-
wgpu::PresentMode::AutoVsync,
143+
wgpu::PresentMode::Immediate, // Unlimited FPS mode
134144
wgpu::TextureFormat::Bgra8Unorm,
135145
));
136146

@@ -203,10 +213,10 @@ impl ApplicationHandler for App<'_> {
203213
event_loop.exit();
204214
}
205215
Key::Character(ch) => {
206-
if let Some(scene) = self.scenes.get_mut(self.current_scene)
207-
&& scene.handle_key(ch.as_str())
208-
{
209-
window.request_redraw();
216+
if let Some(scene) = self.scenes.get_mut(self.current_scene) {
217+
if scene.handle_key(ch.as_str()) {
218+
window.request_redraw();
219+
}
210220
}
211221
}
212222
_ => {}
@@ -268,6 +278,31 @@ impl ApplicationHandler for App<'_> {
268278
window.request_redraw();
269279
}
270280
WindowEvent::RedrawRequested => {
281+
// Measure frame time
282+
let now = Instant::now();
283+
if let Some(last_time) = self.last_frame_time {
284+
let frame_time = now.duration_since(last_time).as_secs_f64() * 1000.0; // Convert to milliseconds
285+
self.accumulated_frame_time += frame_time;
286+
self.frame_count += 1;
287+
288+
// Update window title every second with average FPS
289+
if now.duration_since(self.fps_update_time).as_secs_f64() >= 1.0 {
290+
let avg_frame_time = self.accumulated_frame_time / self.frame_count as f64;
291+
let avg_fps = 1000.0 / avg_frame_time;
292+
println!("Average FPS: {:.1}", avg_fps);
293+
window.set_title(&format!(
294+
"Vello Hybrid - Scene {} - {:.1} FPS ({:.2}ms avg)",
295+
self.current_scene, avg_fps, avg_frame_time
296+
));
297+
298+
// Reset counters
299+
self.frame_count = 0;
300+
self.accumulated_frame_time = 0.0;
301+
self.fps_update_time = now;
302+
}
303+
}
304+
self.last_frame_time = Some(now);
305+
271306
self.scene.reset();
272307

273308
self.scene.set_transform(self.transform);
@@ -311,6 +346,9 @@ impl ApplicationHandler for App<'_> {
311346
surface_texture.present();
312347

313348
device_handle.device.poll(wgpu::PollType::Poll).unwrap();
349+
350+
// Request continuous redraw for FPS measurement
351+
window.request_redraw();
314352
}
315353
_ => {}
316354
}

0 commit comments

Comments
 (0)