diff --git a/app-proto/src/display.rs b/app-proto/src/display.rs index 903193c..67e36e9 100644 --- a/app-proto/src/display.rs +++ b/app-proto/src/display.rs @@ -27,7 +27,7 @@ fn compile_shader( shader } -fn create_program_with_shaders( +fn set_up_program( context: &WebGl2RenderingContext, vertex_shader_source: &str, fragment_shader_source: &str @@ -131,7 +131,8 @@ fn event_dir(event: &MouseEvent) -> Vector3 { let height = rect.height(); let shortdim = width.min(height); - // this constant should be kept synchronized with `inversive.frag` + // this constant should be kept synchronized with `spheres.frag` and + // `point.vert` const FOCAL_SLOPE: f64 = 0.3; Vector3::new( @@ -225,13 +226,22 @@ pub fn Display() -> View { .dyn_into::() .unwrap(); - // create and use the rendering program - let program = create_program_with_shaders( + // disable depth testing + ctx.disable(WebGl2RenderingContext::DEPTH_TEST); + + // set up the sphere rendering program + let sphere_program = set_up_program( &ctx, include_str!("identity.vert"), - include_str!("inversive.frag") + include_str!("spheres.frag") + ); + + // set up the point rendering program + let point_program = set_up_program( + &ctx, + include_str!("point.vert"), + include_str!("point.frag") ); - ctx.use_program(Some(&program)); /* DEBUG */ // print the maximum number of vectors that can be passed as @@ -250,31 +260,31 @@ pub fn Display() -> View { &JsValue::from("uniform vectors available") ); - // find indices of vertex attributes and uniforms + // find indices of sphere vertex attributes and uniforms const SPHERE_MAX: usize = 200; - let position_index = ctx.get_attrib_location(&program, "position") as u32; - let sphere_cnt_loc = ctx.get_uniform_location(&program, "sphere_cnt"); + 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::( - &ctx, &program, "sphere_list", Some("sp") + &ctx, &sphere_program, "sphere_list", Some("sp") ); let sphere_lt_locs = get_uniform_array_locations::( - &ctx, &program, "sphere_list", Some("lt") + &ctx, &sphere_program, "sphere_list", Some("lt") ); - let color_locs = get_uniform_array_locations::( - &ctx, &program, "color_list", None + let sphere_color_locs = get_uniform_array_locations::( + &ctx, &sphere_program, "color_list", None ); - let highlight_locs = get_uniform_array_locations::( - &ctx, &program, "highlight_list", None + let sphere_highlight_locs = get_uniform_array_locations::( + &ctx, &sphere_program, "highlight_list", None ); - let resolution_loc = ctx.get_uniform_location(&program, "resolution"); - let shortdim_loc = ctx.get_uniform_location(&program, "shortdim"); - let opacity_loc = ctx.get_uniform_location(&program, "opacity"); - let layer_threshold_loc = ctx.get_uniform_location(&program, "layer_threshold"); - let debug_mode_loc = ctx.get_uniform_location(&program, "debug_mode"); + let resolution_loc = ctx.get_uniform_location(&sphere_program, "resolution"); + let shortdim_loc = ctx.get_uniform_location(&sphere_program, "shortdim"); + let opacity_loc = ctx.get_uniform_location(&sphere_program, "opacity"); + 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 vertex positions + // set the viewport vertex positions const VERTEX_CNT: usize = 6; - let positions: [f32; 3*VERTEX_CNT] = [ + let viewport_positions: [f32; 3*VERTEX_CNT] = [ // northwest triangle -1.0, -1.0, 0.0, -1.0, 1.0, 0.0, @@ -284,7 +294,9 @@ pub fn Display() -> View { 1.0, 1.0, 0.0, 1.0, -1.0, 0.0 ]; - bind_vertex_attrib(&ctx, position_index, 3, &positions); + + // find indices of point vertex attributes and uniforms + let point_position_index = ctx.get_attrib_location(&point_program, "position") as u32; // set up a repainting routine let (_, start_animation_loop, _) = create_raf(move || { @@ -387,6 +399,8 @@ pub fn Display() -> View { frames_since_last_sample = 0; } + // --- get the assembly --- + // find the map from assembly space to world space let location = { let u = -location_z; @@ -400,12 +414,12 @@ pub fn Display() -> View { }; let asm_to_world = &location * &orientation; - // get the assembly + // get the spheres let ( - elt_cnt, - reps_world, - colors, - highlights + sphere_cnt, + sphere_reps_world, + sphere_colors, + sphere_highlights ) = state.assembly.elements.with(|elts| { ( // number of elements @@ -436,16 +450,45 @@ pub fn Display() -> View { ) }); + /* SCAFFOLDING */ + // get the points + let point_positions = { + use crate::engine::point; + + /* DEBUG */ + // hard-code the origin and the centers of the spheres in + // the general test assembly + let point_reps = [ + point(0.0, 0.0, 0.0), + point(0.5, 0.5, 0.0), + point(-0.5, -0.5, 0.0), + point(-0.5, 0.5, 0.0), + point(0.5, -0.5, 0.0), + point(0.0, 0.15, 1.0), + point(0.0, -0.15, -1.0) + ]; + + const SPACE_DIM: usize = 3; + let asm_to_world_sp = asm_to_world.rows(0, SPACE_DIM); + let point_reps_world_sp = point_reps.map(|rep| &asm_to_world_sp * rep); + DMatrix::from_columns(&point_reps_world_sp).cast::() + }; + + // --- draw the spheres --- + + // use the sphere rendering program + ctx.use_program(Some(&sphere_program)); + // 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 assembly - ctx.uniform1i(sphere_cnt_loc.as_ref(), elt_cnt); - for n in 0..reps_world.len() { - let v = &reps_world[n]; + // pass the assembly data + ctx.uniform1i(sphere_cnt_loc.as_ref(), sphere_cnt); + for n in 0..sphere_reps_world.len() { + let v = &sphere_reps_world[n]; ctx.uniform3f( sphere_sp_locs[n].as_ref(), v[0] as f32, v[1] as f32, v[2] as f32 @@ -455,12 +498,12 @@ pub fn Display() -> View { v[3] as f32, v[4] as f32 ); ctx.uniform3fv_with_f32_array( - color_locs[n].as_ref(), - &colors[n] + sphere_color_locs[n].as_ref(), + &sphere_colors[n] ); ctx.uniform1f( - highlight_locs[n].as_ref(), - highlights[n] + sphere_highlight_locs[n].as_ref(), + sphere_highlights[n] ); } @@ -469,9 +512,25 @@ 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); + // draw the scene ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, VERTEX_CNT as i32); + // --- draw the points --- + + // 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()); + + // draw the scene + ctx.draw_arrays(WebGl2RenderingContext::POINTS, 0, point_positions.ncols() as i32); + + // --- update the display state --- + // update the viewpoint assembly_to_world.set(asm_to_world); diff --git a/app-proto/src/engine.rs b/app-proto/src/engine.rs index 869a7de..b0fa23d 100644 --- a/app-proto/src/engine.rs +++ b/app-proto/src/engine.rs @@ -4,7 +4,6 @@ use web_sys::{console, wasm_bindgen::JsValue}; /* DEBUG */ // --- elements --- -#[cfg(feature = "dev")] pub fn point(x: f64, y: f64, z: f64) -> DVector { DVector::from_column_slice(&[x, y, z, 0.5, 0.5*(x*x + y*y + z*z)]) } diff --git a/app-proto/src/point.frag b/app-proto/src/point.frag new file mode 100644 index 0000000..984d1c9 --- /dev/null +++ b/app-proto/src/point.frag @@ -0,0 +1,9 @@ +#version 300 es + +precision highp float; + +out vec4 outColor; + +void main() { + outColor = vec4(vec3(1.), 1.); +} \ No newline at end of file diff --git a/app-proto/src/point.vert b/app-proto/src/point.vert new file mode 100644 index 0000000..6b8c739 --- /dev/null +++ b/app-proto/src/point.vert @@ -0,0 +1,12 @@ +#version 300 es + +in vec4 position; + +// camera +const float focal_slope = 0.3; + +void main() { + float depth = -focal_slope * position.z; + gl_Position = vec4(position.xy / depth, 0., 1.); + gl_PointSize = 5.; +} \ No newline at end of file diff --git a/app-proto/src/inversive.frag b/app-proto/src/spheres.frag similarity index 100% rename from app-proto/src/inversive.frag rename to app-proto/src/spheres.frag