Only recreate buffers when their contents change
This commit is contained in:
parent
23f395331a
commit
5a1d8bc201
1 changed files with 59 additions and 38 deletions
|
@ -8,6 +8,7 @@ use web_sys::{
|
|||
KeyboardEvent,
|
||||
MouseEvent,
|
||||
WebGl2RenderingContext,
|
||||
WebGlBuffer,
|
||||
WebGlProgram,
|
||||
WebGlShader,
|
||||
WebGlUniformLocation,
|
||||
|
@ -81,22 +82,51 @@ fn get_uniform_array_locations<const N: usize>(
|
|||
})
|
||||
}
|
||||
|
||||
// load the given data into the vertex input of the given name
|
||||
fn bind_vertex_attrib(
|
||||
// find the vertex attribute called `attr_name` in the given program. enable it
|
||||
// and return its index
|
||||
fn find_and_enable_attribute(
|
||||
context: &WebGl2RenderingContext,
|
||||
index: u32,
|
||||
size: i32,
|
||||
data: &[f32]
|
||||
program: &WebGlProgram,
|
||||
attr_name: &str
|
||||
) -> u32 {
|
||||
let attr_index = context.get_attrib_location(program, attr_name) as u32;
|
||||
context.enable_vertex_attrib_array(attr_index);
|
||||
attr_index
|
||||
}
|
||||
|
||||
// bind the given vertex buffer object to the given vertex attribute
|
||||
fn bind_to_attribute(
|
||||
context: &WebGl2RenderingContext,
|
||||
attr_index: u32,
|
||||
attr_size: i32,
|
||||
buffer: &Option<WebGlBuffer>
|
||||
) {
|
||||
// create a data buffer and bind it to ARRAY_BUFFER
|
||||
let buffer = context.create_buffer().unwrap();
|
||||
context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer));
|
||||
context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, buffer.as_ref());
|
||||
context.vertex_attrib_pointer_with_i32(
|
||||
attr_index,
|
||||
attr_size,
|
||||
WebGl2RenderingContext::FLOAT,
|
||||
false, // don't normalize
|
||||
0, // zero stride
|
||||
0, // zero offset
|
||||
);
|
||||
}
|
||||
|
||||
// load the given data into a new vertex buffer object
|
||||
fn load_new_buffer(
|
||||
context: &WebGl2RenderingContext,
|
||||
data: &[f32]
|
||||
) -> Option<WebGlBuffer> {
|
||||
// create a buffer and bind it to ARRAY_BUFFER
|
||||
let buffer = context.create_buffer();
|
||||
context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, buffer.as_ref());
|
||||
|
||||
// load the given data into the buffer. the function `Float32Array::view`
|
||||
// creates a raw view into our module's `WebAssembly.Memory` buffer.
|
||||
// allocating more memory will change the buffer, invalidating the view.
|
||||
// that means we have to make sure we don't allocate any memory until the
|
||||
// view is dropped
|
||||
// load the given data into the buffer. this block is unsafe because
|
||||
// `Float32Array::view` creates a raw view into our module's
|
||||
// `WebAssembly.Memory` buffer. allocating more memory will change the
|
||||
// buffer, invalidating the view, so we have to make sure we don't allocate
|
||||
// any memory until the view is dropped. we're okay here because the view is
|
||||
// used as soon as it's created
|
||||
unsafe {
|
||||
context.buffer_data_with_array_buffer_view(
|
||||
WebGl2RenderingContext::ARRAY_BUFFER,
|
||||
|
@ -105,22 +135,7 @@ fn bind_vertex_attrib(
|
|||
);
|
||||
}
|
||||
|
||||
// allow the target attribute to be used
|
||||
context.enable_vertex_attrib_array(index);
|
||||
|
||||
// take whatever's bound to ARRAY_BUFFER---here, the data buffer created
|
||||
// above---and bind it to the target attribute
|
||||
//
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer
|
||||
//
|
||||
context.vertex_attrib_pointer_with_i32(
|
||||
index,
|
||||
size,
|
||||
WebGl2RenderingContext::FLOAT,
|
||||
false, // don't normalize
|
||||
0, // zero stride
|
||||
0, // zero offset
|
||||
);
|
||||
buffer
|
||||
}
|
||||
|
||||
// the direction in camera space that a mouse event is pointing along
|
||||
|
@ -260,9 +275,11 @@ pub fn Display() -> View {
|
|||
&JsValue::from("uniform vectors available")
|
||||
);
|
||||
|
||||
// find indices of sphere vertex attributes and uniforms
|
||||
// find and enable the sphere program's sole vertex attribute
|
||||
let viewport_position_attr = find_and_enable_attribute(&ctx, &sphere_program, "position");
|
||||
|
||||
// find the sphere program's uniforms
|
||||
const SPHERE_MAX: usize = 200;
|
||||
let viewport_position_index = ctx.get_attrib_location(&sphere_program, "position") as u32;
|
||||
let sphere_cnt_loc = ctx.get_uniform_location(&sphere_program, "sphere_cnt");
|
||||
let sphere_sp_locs = get_uniform_array_locations::<SPHERE_MAX>(
|
||||
&ctx, &sphere_program, "sphere_list", Some("sp")
|
||||
|
@ -282,7 +299,7 @@ pub fn Display() -> View {
|
|||
let layer_threshold_loc = ctx.get_uniform_location(&sphere_program, "layer_threshold");
|
||||
let debug_mode_loc = ctx.get_uniform_location(&sphere_program, "debug_mode");
|
||||
|
||||
// set the viewport vertex positions
|
||||
// load the viewport vertex positions into a new vertex buffer object
|
||||
const VERTEX_CNT: usize = 6;
|
||||
let viewport_positions: [f32; 3*VERTEX_CNT] = [
|
||||
// northwest triangle
|
||||
|
@ -294,9 +311,10 @@ pub fn Display() -> View {
|
|||
1.0, 1.0, 0.0,
|
||||
1.0, -1.0, 0.0
|
||||
];
|
||||
let viewport_position_buffer = load_new_buffer(&ctx, &viewport_positions);
|
||||
|
||||
// find indices of point vertex attributes and uniforms
|
||||
let point_position_index = ctx.get_attrib_location(&point_program, "position") as u32;
|
||||
// find and enable the point program's sole vertex attribute
|
||||
let point_position_attr = find_and_enable_attribute(&ctx, &point_program, "position");
|
||||
|
||||
// set up a repainting routine
|
||||
let (_, start_animation_loop, _) = create_raf(move || {
|
||||
|
@ -512,8 +530,9 @@ pub fn Display() -> View {
|
|||
ctx.uniform1i(layer_threshold_loc.as_ref(), LAYER_THRESHOLD);
|
||||
ctx.uniform1i(debug_mode_loc.as_ref(), DEBUG_MODE);
|
||||
|
||||
// pass the viewport vertex positions
|
||||
bind_vertex_attrib(&ctx, viewport_position_index, 3, &viewport_positions);
|
||||
// bind the viewport vertex position buffer to the position
|
||||
// attribute in the vertex shader
|
||||
bind_to_attribute(&ctx, viewport_position_attr, 3, &viewport_position_buffer);
|
||||
|
||||
// draw the scene
|
||||
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
||||
|
@ -523,8 +542,10 @@ pub fn Display() -> View {
|
|||
// use the point rendering program
|
||||
ctx.use_program(Some(&point_program));
|
||||
|
||||
// pass the point vertex positions
|
||||
bind_vertex_attrib(&ctx, point_position_index, 3, point_positions.as_slice());
|
||||
// load the point positions into a new buffer and bind it to the
|
||||
// position attribute in the vertex shader
|
||||
let point_position_buffer = load_new_buffer(&ctx, point_positions.as_slice());
|
||||
bind_to_attribute(&ctx, point_position_attr, 3, &point_position_buffer);
|
||||
|
||||
// draw the scene
|
||||
ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue