Ray-caster: only draw when the scene is changed
This is how I typically schedule draw calls in JavaScript applications. The baseline CPU activity for the display prototype is now in line with other pages (though perhaps a bit higher), and the profiler shows little time being spent in draw calls, even when I'm continually moving a slider. The interface feels pretty responsive overall, although the sliders seem to be lagging a bit.
This commit is contained in:
parent
f62f44b5a7
commit
a40a110788
@ -108,6 +108,21 @@ fn main() {
|
||||
// display
|
||||
let display = create_node_ref();
|
||||
|
||||
// change listener
|
||||
let scene_changed = create_signal(true);
|
||||
create_effect(move || {
|
||||
ctrl_x.track();
|
||||
ctrl_y.track();
|
||||
radius_x.track();
|
||||
radius_y.track();
|
||||
opacity.track();
|
||||
highlight.track();
|
||||
layer_threshold.track();
|
||||
debug_mode.track();
|
||||
|
||||
scene_changed.set(true);
|
||||
});
|
||||
|
||||
on_mount(move || {
|
||||
// list construction elements
|
||||
const SPHERE_MAX: usize = 12;
|
||||
@ -216,66 +231,67 @@ fn main() {
|
||||
bind_vertex_attrib(&ctx, position_index, 3, &positions);
|
||||
|
||||
// set up a repainting routine
|
||||
let (_, start_updating_display, _) = create_raf(move || {
|
||||
/* INSTRUMENTS */
|
||||
// measure frame time
|
||||
frames_since_last_sample += 1;
|
||||
if frames_since_last_sample >= SAMPLE_PERIOD {
|
||||
let frame_moment = performance.now();
|
||||
frame_time.set((frame_moment - last_frame_moment) / (SAMPLE_PERIOD as f64));
|
||||
last_frame_moment = frame_moment;
|
||||
let (_, start_animation_loop, _) = create_raf(move || {
|
||||
if scene_changed.get() {
|
||||
/* INSTRUMENTS */
|
||||
// measure frame time
|
||||
frames_since_last_sample += 1;
|
||||
if frames_since_last_sample >= SAMPLE_PERIOD {
|
||||
let frame_moment = performance.now();
|
||||
frame_time.set((frame_moment - last_frame_moment) / (SAMPLE_PERIOD as f64));
|
||||
last_frame_moment = frame_moment;
|
||||
frames_since_last_sample = 0;
|
||||
}
|
||||
|
||||
// update the construction
|
||||
sphere_vec.clear();
|
||||
sphere_vec.push(engine::sphere(0.5, 0.5, -5.0 + ctrl_x.get(), radius_x.get()));
|
||||
sphere_vec.push(engine::sphere(-0.5, -0.5, -5.0 + ctrl_y.get(), radius_y.get()));
|
||||
sphere_vec.push(engine::sphere(-0.5, 0.5, -5.0, 0.75));
|
||||
|
||||
// set the resolution
|
||||
let width = canvas.width() as f32;
|
||||
let height = canvas.height() as f32;
|
||||
ctx.uniform2f(resolution_loc.as_ref(), width, height);
|
||||
ctx.uniform1f(shortdim_loc.as_ref(), width.min(height));
|
||||
|
||||
// pass the construction
|
||||
ctx.uniform1i(sphere_cnt_loc.as_ref(), sphere_vec.len() as i32);
|
||||
for n in 0..sphere_vec.len() {
|
||||
let v = &sphere_vec[n];
|
||||
ctx.uniform3f(
|
||||
sphere_sp_locs[n].as_ref(),
|
||||
v[0] as f32, v[1] as f32, v[2] as f32
|
||||
);
|
||||
ctx.uniform2f(
|
||||
sphere_lt_locs[n].as_ref(),
|
||||
v[3] as f32, v[4] as f32
|
||||
);
|
||||
ctx.uniform3fv_with_f32_array(
|
||||
color_locs[n].as_ref(),
|
||||
&color_vec[n]
|
||||
);
|
||||
}
|
||||
|
||||
// pass the control parameters
|
||||
ctx.uniform2f(ctrl_loc.as_ref(), ctrl_x.get() as f32, ctrl_y.get() as f32); /* DEBUG */
|
||||
ctx.uniform2f(radius_loc.as_ref(), radius_x.get() as f32, radius_y.get() as f32); /* DEBUG */
|
||||
ctx.uniform1f(opacity_loc.as_ref(), opacity.get() as f32);
|
||||
ctx.uniform1f(highlight_loc.as_ref(), highlight.get() as f32);
|
||||
ctx.uniform1i(layer_threshold_loc.as_ref(), layer_threshold.get() as i32);
|
||||
ctx.uniform1i(debug_mode_loc.as_ref(), debug_mode.get() as i32);
|
||||
|
||||
// draw the scene
|
||||
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
||||
|
||||
// clear scene change flag
|
||||
scene_changed.set(false);
|
||||
} else {
|
||||
frames_since_last_sample = 0;
|
||||
frame_time.set(-1.0);
|
||||
}
|
||||
|
||||
// update the construction
|
||||
sphere_vec.clear();
|
||||
sphere_vec.push(engine::sphere(0.5, 0.5, -5.0 + ctrl_x.get(), radius_x.get()));
|
||||
sphere_vec.push(engine::sphere(-0.5, -0.5, -5.0 + ctrl_y.get(), radius_y.get()));
|
||||
sphere_vec.push(engine::sphere(-0.5, 0.5, -5.0, 0.75));
|
||||
|
||||
// set the resolution
|
||||
let width = canvas.width() as f32;
|
||||
let height = canvas.height() as f32;
|
||||
ctx.uniform2f(resolution_loc.as_ref(), width, height);
|
||||
ctx.uniform1f(shortdim_loc.as_ref(), width.min(height));
|
||||
|
||||
// pass the construction
|
||||
ctx.uniform1i(sphere_cnt_loc.as_ref(), sphere_vec.len() as i32);
|
||||
for n in 0..sphere_vec.len() {
|
||||
let v = &sphere_vec[n];
|
||||
ctx.uniform3f(
|
||||
sphere_sp_locs[n].as_ref(),
|
||||
v[0] as f32, v[1] as f32, v[2] as f32
|
||||
);
|
||||
ctx.uniform2f(
|
||||
sphere_lt_locs[n].as_ref(),
|
||||
v[3] as f32, v[4] as f32
|
||||
);
|
||||
ctx.uniform3fv_with_f32_array(
|
||||
color_locs[n].as_ref(),
|
||||
&color_vec[n]
|
||||
);
|
||||
}
|
||||
|
||||
// pass the control parameters
|
||||
ctx.uniform2f(ctrl_loc.as_ref(), ctrl_x.get() as f32, ctrl_y.get() as f32); /* DEBUG */
|
||||
ctx.uniform2f(radius_loc.as_ref(), radius_x.get() as f32, radius_y.get() as f32); /* DEBUG */
|
||||
ctx.uniform1f(opacity_loc.as_ref(), opacity.get() as f32);
|
||||
ctx.uniform1f(highlight_loc.as_ref(), highlight.get() as f32);
|
||||
ctx.uniform1i(layer_threshold_loc.as_ref(), layer_threshold.get() as i32);
|
||||
ctx.uniform1i(debug_mode_loc.as_ref(), debug_mode.get() as i32);
|
||||
|
||||
// draw the scene
|
||||
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
||||
});
|
||||
|
||||
/*
|
||||
this wastes CPU time by running an animation loop, which updates the
|
||||
display even when nothing has changed. there should be a way to make
|
||||
Sycamore do single-frame updates in response to changes, but i
|
||||
haven't found it yet
|
||||
*/
|
||||
start_updating_display();
|
||||
start_animation_loop();
|
||||
});
|
||||
|
||||
view! {
|
||||
|
Loading…
Reference in New Issue
Block a user