Skip to content

Commit 7bcee70

Browse files
committed
override_image demo WIP
Signed-off-by: Nico Burns <[email protected]>
1 parent 7b32dc2 commit 7bcee70

File tree

7 files changed

+328
-3
lines changed

7 files changed

+328
-3
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/simple/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
//! Simple example.
55
66
use anyhow::Result;
7+
use std::f64::consts::{FRAC_PI_2, FRAC_PI_4};
78
use std::sync::Arc;
8-
use vello::kurbo::{Affine, Circle, Ellipse, Line, RoundedRect, Stroke};
9+
use vello::kurbo::{Affine, BezPath, Circle, Ellipse, Line, RoundedRect, Shape, Stroke};
910
use vello::peniko::Color;
1011
use vello::peniko::color::palette;
1112
use vello::util::{RenderContext, RenderSurface};

examples/with_winit/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ scenes = { workspace = true }
3535
anyhow = { workspace = true }
3636
clap = { workspace = true, features = ["derive"] }
3737
pollster = { workspace = true }
38+
wgpu = { workspace = true }
3839
wgpu-profiler = { workspace = true, optional = true }
3940

4041
winit = { workspace = true }
4142
log = { workspace = true }
43+
bytemuck = { workspace = true }
4244

4345
# We're still using env-logger, but we want to use tracing spans to allow using
4446
# tracing_android_trace

examples/with_winit/src/lib.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ use minimal_pipeline_cache::{get_cache_directory, load_pipeline_cache, write_pip
2222
#[cfg(not(target_arch = "wasm32"))]
2323
use std::time::Instant;
2424
use vello::low_level::DebugLayers;
25+
use vello::peniko::Blob;
2526
#[cfg(target_arch = "wasm32")]
2627
use web_time::Instant;
28+
use wgpu::TexelCopyTextureInfoBase;
29+
use wgpu_shader::DemoRenderer;
2730
use winit::application::ApplicationHandler;
2831
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent};
2932
use winit::keyboard::{Key, ModifiersState, NamedKey};
@@ -51,6 +54,7 @@ mod hot_reload;
5154
mod minimal_pipeline_cache;
5255
mod multi_touch;
5356
mod stats;
57+
mod wgpu_shader;
5458

5559
#[derive(Parser, Debug)]
5660
#[command(about, long_about = None, bin_name="cargo run -p with_winit --")]
@@ -170,6 +174,8 @@ struct VelloApp<'s> {
170174
prev_scene_ix: i32,
171175
modifiers: ModifiersState,
172176

177+
demo_renderer: Option<DemoRenderer>,
178+
173179
debug: DebugLayers,
174180

175181
#[cfg(not(target_arch = "wasm32"))]
@@ -205,6 +211,14 @@ impl ApplicationHandler<UserEvent> for VelloApp<'_> {
205211
self.renderers
206212
.resize_with(self.context.devices.len(), || None);
207213
let id = render_state.surface.dev_id;
214+
215+
// Initialise demo renderer
216+
let device_handle = &self.context.devices[id];
217+
self.demo_renderer = Some(DemoRenderer::new(
218+
&device_handle.device,
219+
&device_handle.queue,
220+
));
221+
208222
self.renderers[id].get_or_insert_with(|| {
209223
let device_handle = &self.context.devices[id];
210224
let cache = if let Some((dir, tx)) = self.cache_data.as_ref() {
@@ -484,6 +498,40 @@ impl ApplicationHandler<UserEvent> for VelloApp<'_> {
484498
let device_handle = &self.context.devices[surface.dev_id];
485499
let snapshot = self.stats.snapshot();
486500

501+
// Render demo and store as override_image
502+
// TODO: reuse dummy images and texture mapping
503+
504+
let mut demo_texture = None;
505+
let demo_w = width / 2;
506+
let demo_h = height / 2;
507+
let demo_x = width / 4;
508+
let demo_y = height / 4;
509+
if let Some(renderer) = self.renderers[surface.dev_id].as_mut() {
510+
if let Some(demo) = self.demo_renderer.as_mut() {
511+
let texture = demo.render(1.0, 0.0, 0.0, demo_w, demo_h);
512+
let dummy_image = vello::peniko::Image {
513+
data: Blob::new(Arc::new([])), // will be ignored
514+
format: vello::peniko::ImageFormat::Rgba8,
515+
width: demo_w,
516+
height: demo_h,
517+
x_extend: vello::peniko::Extend::Pad,
518+
y_extend: vello::peniko::Extend::Pad,
519+
quality: vello::peniko::ImageQuality::High,
520+
alpha: 1.0,
521+
};
522+
523+
let base = TexelCopyTextureInfoBase {
524+
texture,
525+
mip_level: 0,
526+
origin: wgpu::Origin3d::ZERO,
527+
aspect: wgpu::TextureAspect::All,
528+
};
529+
renderer.override_image(&dummy_image, Some(base));
530+
531+
demo_texture = Some(dummy_image);
532+
}
533+
}
534+
487535
// Allow looping forever
488536
self.scene_ix = self.scene_ix.rem_euclid(self.scenes.len() as i32);
489537
self.aa_config_ix = self.aa_config_ix.rem_euclid(AA_CONFIGS.len() as i32);
@@ -531,6 +579,17 @@ impl ApplicationHandler<UserEvent> for VelloApp<'_> {
531579
transform *= Affine::scale(scale_factor);
532580
}
533581
self.scene.append(&self.fragment, Some(transform));
582+
583+
if let Some(demo_texture) = demo_texture {
584+
self.scene.draw_image(
585+
&demo_texture,
586+
Affine::translate(Vec2 {
587+
x: demo_x as f64,
588+
y: demo_y as f64,
589+
}),
590+
);
591+
};
592+
534593
if self.stats_shown {
535594
snapshot.draw_layer(
536595
&mut self.scene,
@@ -821,6 +880,8 @@ fn run(
821880
frame_start_time: Instant::now(),
822881
start: Instant::now(),
823882

883+
demo_renderer: None,
884+
824885
touch_state: multi_touch::TouchState::new(),
825886
navigation_fingers: HashSet::new(),
826887
transform: Affine::IDENTITY,
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Copyright © SixtyFPS GmbH <[email protected]>
2+
// SPDX-License-Identifier: MIT
3+
4+
struct VertexOutput {
5+
@builtin(position) position: vec4<f32>,
6+
@location(0) frag_position: vec2<f32>,
7+
};
8+
9+
@vertex
10+
fn vs_main(
11+
@builtin(vertex_index) vertex_index: u32
12+
) -> VertexOutput {
13+
var output: VertexOutput;
14+
15+
var positions = array<vec2<f32>, 3>(
16+
vec2<f32>(-1.0, 3.0),
17+
vec2<f32>(-1.0, -1.0),
18+
vec2<f32>( 3.0, -1.0)
19+
);
20+
21+
let pos = positions[vertex_index];
22+
output.position = vec4<f32>(pos.x, -pos.y, 0.0, 1.0);
23+
output.frag_position = pos;
24+
return output;
25+
}
26+
27+
struct PushConstants {
28+
light_color_and_time: vec4<f32>,
29+
};
30+
31+
var<push_constant> pc: PushConstants;
32+
33+
fn sdRoundBox(p: vec3<f32>, b: vec3<f32>, r: f32) -> f32 {
34+
let q = abs(p) - b;
35+
return length(max(q, vec3<f32>(0.0))) + min(max(q.x, max(q.y, q.z)), 0.0) - r;
36+
}
37+
38+
fn rotateY(r: vec3<f32>, angle: f32) -> vec3<f32> {
39+
let c = cos(angle);
40+
let s = sin(angle);
41+
let rotation_matrix = mat3x3<f32>(
42+
vec3<f32>( c, 0.0, s),
43+
vec3<f32>(0.0, 1.0, 0.0),
44+
vec3<f32>(-s, 0.0, c)
45+
);
46+
return rotation_matrix * r;
47+
}
48+
49+
fn rotateZ(r: vec3<f32>, angle: f32) -> vec3<f32> {
50+
let c = cos(angle);
51+
let s = sin(angle);
52+
let rotation_matrix = mat3x3<f32>(
53+
vec3<f32>( c, -s, 0.0),
54+
vec3<f32>( s, c, 0.0),
55+
vec3<f32>(0.0, 0.0, 1.0)
56+
);
57+
return rotation_matrix * r;
58+
}
59+
60+
// Distance from the scene
61+
fn scene(r: vec3<f32>) -> f32 {
62+
let iTime = pc.light_color_and_time.w;
63+
let pos = rotateZ(rotateY(r + vec3<f32>(-1.0, -1.0, 4.0), iTime), iTime);
64+
let cube = vec3<f32>(0.5, 0.5, 0.5);
65+
let edge = 0.1;
66+
return sdRoundBox(pos, cube, edge);
67+
}
68+
69+
// https://iquilezles.org/articles/normalsSDF
70+
fn normal(pos: vec3<f32>) -> vec3<f32> {
71+
let e = vec2<f32>(1.0, -1.0) * 0.5773;
72+
let eps = 0.0005;
73+
return normalize(
74+
e.xyy * scene(pos + e.xyy * eps) +
75+
e.yyx * scene(pos + e.yyx * eps) +
76+
e.yxy * scene(pos + e.yxy * eps) +
77+
e.xxx * scene(pos + e.xxx * eps)
78+
);
79+
}
80+
81+
fn render(fragCoord: vec2<f32>, light_color: vec3<f32>) -> vec4<f32> {
82+
var color = vec4<f32>(0.0, 0.0, 0.0, 1.0);
83+
84+
var camera = vec3<f32>(1.0, 2.0, 1.0);
85+
var p = vec3<f32>(fragCoord.x, fragCoord.y + 1.0, -1.0);
86+
var dir = normalize(p - camera);
87+
88+
var i = 0;
89+
loop {
90+
if (i >= 90) { break; }
91+
let dist = scene(p);
92+
if (dist < 0.0001) { break; }
93+
p = p + dir * dist;
94+
i = i + 1;
95+
}
96+
97+
let surf_normal = normal(p);
98+
let light_position = vec3<f32>(2.0, 4.0, -0.5);
99+
var light = 7.0 + 2.0 * dot(surf_normal, light_position);
100+
light = light / (0.2 * pow(length(light_position - p), 3.5));
101+
102+
return vec4<f32>(light * light_color, 1.0) * 2.0;
103+
}
104+
105+
@fragment
106+
fn fs_main(@location(0) frag_position: vec2<f32>) -> @location(0) vec4<f32> {
107+
let selected_light_color = pc.light_color_and_time.xyz;
108+
let r = vec2<f32>(0.5 * frag_position.x + 1.0, 0.5 - 0.5 * frag_position.y);
109+
return render(r, selected_light_color);
110+
}

0 commit comments

Comments
 (0)