forked from StudioInfinity/dyna3
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,
|
KeyboardEvent,
|
||||||
MouseEvent,
|
MouseEvent,
|
||||||
WebGl2RenderingContext,
|
WebGl2RenderingContext,
|
||||||
|
WebGlBuffer,
|
||||||
WebGlProgram,
|
WebGlProgram,
|
||||||
WebGlShader,
|
WebGlShader,
|
||||||
WebGlUniformLocation,
|
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
|
// find the vertex attribute called `attr_name` in the given program. enable it
|
||||||
fn bind_vertex_attrib(
|
// and return its index
|
||||||
|
fn find_and_enable_attribute(
|
||||||
context: &WebGl2RenderingContext,
|
context: &WebGl2RenderingContext,
|
||||||
index: u32,
|
program: &WebGlProgram,
|
||||||
size: i32,
|
attr_name: &str
|
||||||
data: &[f32]
|
) -> 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
|
context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, buffer.as_ref());
|
||||||
let buffer = context.create_buffer().unwrap();
|
context.vertex_attrib_pointer_with_i32(
|
||||||
context.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer));
|
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`
|
// load the given data into the buffer. this block is unsafe because
|
||||||
// creates a raw view into our module's `WebAssembly.Memory` buffer.
|
// `Float32Array::view` creates a raw view into our module's
|
||||||
// allocating more memory will change the buffer, invalidating the view.
|
// `WebAssembly.Memory` buffer. allocating more memory will change the
|
||||||
// that means we have to make sure we don't allocate any memory until the
|
// buffer, invalidating the view, so we have to make sure we don't allocate
|
||||||
// view is dropped
|
// any memory until the view is dropped. we're okay here because the view is
|
||||||
|
// used as soon as it's created
|
||||||
unsafe {
|
unsafe {
|
||||||
context.buffer_data_with_array_buffer_view(
|
context.buffer_data_with_array_buffer_view(
|
||||||
WebGl2RenderingContext::ARRAY_BUFFER,
|
WebGl2RenderingContext::ARRAY_BUFFER,
|
||||||
|
@ -105,22 +135,7 @@ fn bind_vertex_attrib(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// allow the target attribute to be used
|
buffer
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the direction in camera space that a mouse event is pointing along
|
// 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")
|
&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;
|
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_cnt_loc = ctx.get_uniform_location(&sphere_program, "sphere_cnt");
|
||||||
let sphere_sp_locs = get_uniform_array_locations::<SPHERE_MAX>(
|
let sphere_sp_locs = get_uniform_array_locations::<SPHERE_MAX>(
|
||||||
&ctx, &sphere_program, "sphere_list", Some("sp")
|
&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 layer_threshold_loc = ctx.get_uniform_location(&sphere_program, "layer_threshold");
|
||||||
let debug_mode_loc = ctx.get_uniform_location(&sphere_program, "debug_mode");
|
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;
|
const VERTEX_CNT: usize = 6;
|
||||||
let viewport_positions: [f32; 3*VERTEX_CNT] = [
|
let viewport_positions: [f32; 3*VERTEX_CNT] = [
|
||||||
// northwest triangle
|
// northwest triangle
|
||||||
|
@ -294,9 +311,10 @@ pub fn Display() -> View {
|
||||||
1.0, 1.0, 0.0,
|
1.0, 1.0, 0.0,
|
||||||
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
|
// find and enable the point program's sole vertex attribute
|
||||||
let point_position_index = ctx.get_attrib_location(&point_program, "position") as u32;
|
let point_position_attr = find_and_enable_attribute(&ctx, &point_program, "position");
|
||||||
|
|
||||||
// set up a repainting routine
|
// set up a repainting routine
|
||||||
let (_, start_animation_loop, _) = create_raf(move || {
|
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(layer_threshold_loc.as_ref(), LAYER_THRESHOLD);
|
||||||
ctx.uniform1i(debug_mode_loc.as_ref(), DEBUG_MODE);
|
ctx.uniform1i(debug_mode_loc.as_ref(), DEBUG_MODE);
|
||||||
|
|
||||||
// pass the viewport vertex positions
|
// bind the viewport vertex position buffer to the position
|
||||||
bind_vertex_attrib(&ctx, viewport_position_index, 3, &viewport_positions);
|
// attribute in the vertex shader
|
||||||
|
bind_to_attribute(&ctx, viewport_position_attr, 3, &viewport_position_buffer);
|
||||||
|
|
||||||
// draw the scene
|
// draw the scene
|
||||||
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32);
|
||||||
|
@ -523,8 +542,10 @@ pub fn Display() -> View {
|
||||||
// use the point rendering program
|
// use the point rendering program
|
||||||
ctx.use_program(Some(&point_program));
|
ctx.use_program(Some(&point_program));
|
||||||
|
|
||||||
// pass the point vertex positions
|
// load the point positions into a new buffer and bind it to the
|
||||||
bind_vertex_attrib(&ctx, point_position_index, 3, point_positions.as_slice());
|
// 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
|
// draw the scene
|
||||||
ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32);
|
ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue