diff --git a/beppe_online/Cargo.toml b/beppe_online/Cargo.toml
index 033df70..f09ae56 100644
--- a/beppe_online/Cargo.toml
+++ b/beppe_online/Cargo.toml
@@ -13,17 +13,15 @@ crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
js-sys = "0.3"
+yew = { git = "https://github.com/yewstack/yew/", features = ["csr"] }
[dependencies.web-sys]
version = "0.3"
features = [
- 'Document',
- 'Window',
'HtmlCanvasElement',
- 'WebGlRenderingContext',
- 'WebGl2RenderingContext',
- 'WebGlProgram',
- 'WebGlShader',
'WebGlBuffer',
- 'WebGlUniformLocation'
+ 'WebGlProgram',
+ 'WebGlRenderingContext',
+ 'WebGlShader',
+ 'WebGlUniformLocation',
]
diff --git a/beppe_online/index.html b/beppe_online/index.html
new file mode 100644
index 0000000..202cc6f
--- /dev/null
+++ b/beppe_online/index.html
@@ -0,0 +1,11 @@
+
+
+
+
+
+ Yew App
+
+
+
+
+
diff --git a/beppe_online/src/basic.frag b/beppe_online/src/basic.frag
new file mode 100644
index 0000000..49bb667
--- /dev/null
+++ b/beppe_online/src/basic.frag
@@ -0,0 +1,10 @@
+precision mediump float;
+
+uniform float u_time;
+
+void main() {
+ float r = sin(u_time * .0003);
+ float g = sin(u_time*.0005);
+ float b = sin(u_time*.0007);
+ gl_fragColor = vec4(r,g,b,1.);
+}
diff --git a/beppe_online/src/basic.vert b/beppe_online/src/basic.vert
new file mode 100644
index 0000000..b5d74da
--- /dev/null
+++ b/beppe_online/src/basic.vert
@@ -0,0 +1,7 @@
+precision mediump float;
+
+attribute vec2 a_position;
+
+void main() {
+ gl_Position = vec4(a_position, 0.0, 1.0);
+}
diff --git a/beppe_online/src/lib.rs b/beppe_online/src/lib.rs
index d7ca686..7e341e1 100644
--- a/beppe_online/src/lib.rs
+++ b/beppe_online/src/lib.rs
@@ -1,91 +1,119 @@
+use std::cell::RefCell;
+use std::rc::Rc;
+
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
-use web_sys::{WebGlRenderingContext, WebGlShader, WebGlProgram};
-extern crate js_sys;
+use web_sys::{window, HtmlCanvasElement, WebGlRenderingContext as GL, WebGlRenderingContext};
-pub fn init_webgl_context(canvas_id: &str) -> Result {
- let document = web_sys::window().unwrap().document().unwrap();
- let canvas = document.get_element_by_id(canvas_id).unwrap();
- let canvas: web_sys::HtmlCanvasElement = canvas.dyn_into::()?;
- let gl: WebGlRenderingContext = canvas.get_context("webgl")?
- .unwrap()
- .dyn_into::()
- .unwrap();
+use yew::{html, Component, Context, Html, NodeRef};
- gl.viewport(
- 0,
- 0,
- canvas.width().try_into().unwrap(),
- canvas.height().try_into().unwrap(),
- );
- Ok(gl);
+pub struct App {
+ node_ref: NodeRef,
}
+impl Component for App {
+ type Message = ();
+ type Properties = ();
-// https://blog.logrocket.com/implement-webassembly-webgl-viewer-using-rust/#setup-environment
-pub fn create_shader(
- gl: &WebGlRenderingContext,
- shader_type: u32,
- source: &str,
-) -> Result {
- let shader = gl.create_shader(shader_type)
- .ok_or_else(|| JsValue::from_str("Unable to create shader object"))?;
+ fn create(_ctx: &Context) -> Self {
+ Self {
+ node_ref: NodeRef::default(),
+ }
+ }
- g..shader_source(&shader, source);
- gl.compile_shader(&shader);
+ fn view(&self, _ctx: &Context) -> Html {
+ html! {
+
+ }
+ }
- if gl.get_shader_parameter(&shader. WebGlRenderingContext::COMPILE_STATUS)
- .as_bool().unwrap_or(false) {
- Ok(shader)
- } else {
- Err(JsValue::from_str(&gl.get_shader_info_log(&shader).unwrap_or_else(|| "Unknown error creating shader".into()),
- ))
+ fn rendered(&mut self, _ctx: &Context, first_renderer: bool) {
+ if !first_renderer {
+ return;
+ }
+
+ let canvas = self.node_ref.cast::().unwrap();
+ let gl: GL = canvas
+ .get_context("webgl")
+ .unwrap()
+ .unwrap()
+ .dyn_into()
+ .unwrap();
+ Self::render_gl(gl);
}
}
-
-pub fn setup_shaders(gl: &WebGlRenderingContext) -> Result {
- let vertex_shader_source = "
- attribute vec3 coordinates;
- void main(void) {
- gl_Position = vec4(coordinates, 1.0);
- }
- ";
- let fragment_shader_source = "
- precision mediump float;
- uniform vec4 fragColor;
- void main(void) {
- gl_FragColor = fragColor;
- }
- ";
- let vertex_shader = create_shader(
- &gl,
- WebGlRenderingContext::VERTEX_SHADER,
- vertex_shader_source,
- ).unwrap();
- let fragment_shader = create_shader(
- &gl,
- WebGlRenderingContext::FRAGMENT_SHADER,
- fragment_shader_source,
- ).unwrap();
-
- let shader_program = gl.create_program().unwrap();
- gl.attach_shader(&shader_program, &vertex_shader);
- gl.attach_shader(&shader_program, &fragment_shader);
- gl.link_program(&shader_program);
-
- if gl.get_program_parameter(&shader_program, WebGlRenderingContext::LINK_STATUS)
- .as_bool()
- .unwrap_or(false) {
- g.use_program(Some(&shader_program));
- Ok(shader_program);
- } else {
- return Err(JsValue::from_str(
- &gl.get_program_info_log(&shader_program)
- .unwrap_or_else(|| "Unknown error linking program".into()),
- ));
+impl App {
+ fn request_animation_frame(f: &Closure) {
+ window()
+ .unwrap()
+ .request_animation_frame(f.as_ref().unchecked_ref())
+ .expect("should register `requestAnimationFrame` OK");
}
+
+ fn render_gl(gl: WebGlRenderingContext) {
+
+ let mut timestamp = 0.0;
+
+ let vert_code = include_str!("./basic.vert");
+ let frag_code = include_str!("./basic.frag");
+
+ let vertices: Vec = vec![
+ -1.0, -1.0,
+ 1.0, -1.0,
+ -1.0, 1.0,
+ -1.0, 1.0,
+ 1.0, -1.0,
+ 1.0, 1.0,
+ ];
+ let vertex_buffer = gl.create_buffer().unwrap();
+ let verts = js_sys::Float32Array::from(vertices.as_slice());
+
+ gl.bind_buffer(GL::ARRAY_BUFFER, Some(&vertex_buffer));
+ gl.buffer_data_with_array_buffer_view(GL::ARRAY_BUFFER, &verts, GL::STATIC_DRAW);
+
+ let vert_shader = gl.create_shader(GL::VERTEX_SHADER).unwrap();
+ gl.shader_source(&vert_shader, vert_code);
+ gl.compile_shader(&vert_shader);
+
+ let frag_shader = gl.create_shader(GL::FRAGMENT_SHADER).unwrap();
+ gl.shader_source(&frag_shader, frag_code);
+ gl.compile_shader(&frag_shader);
+
+ let shader_program = gl.create_program().unwrap();
+ gl.attach_shader(&shader_program, &vert_shader);
+ gl.attach_shader(&shader_program, &frag_shader);
+ gl.link_program(&shader_program);
+
+ gl.use_program(Some(&shader_program));
+
+ let position = gl.get_attrib_location(&shader_program, "a_position") as u32;
+ gl.vertex_attrib_pointer_with_i32(position, 2, GL::FLOAT, false, 0, 0);
+ gl.enable_vertex_attrib_array(position);
+
+ let time = gl.get_uniform_location(&shader_program, "u_time");
+ gl.uniform1f(time.as_ref(), timestamp as f32);
+
+ gl.draw_arrays(GL::TRIANGLES, 0, 6);
+
+ let cb = Rc::new(RefCell::new(None));
+
+ *cb.borrow_mut() = Some(Closure::wrap(Box::new({
+ let cb = cb.clone();
+ move || {
+ timestamp += 20.0;
+ gl.uniform1f(time.as_ref(), timestamp as f32);
+ gl.draw_arrays(GL::TRIANGLES, 0, 6);
+ App::request_animation_frame(cb.borrow().as_ref().unwrap());
+ }
+ }) as Box));
+
+ App::request_animation_frame(cb.borrow().as_ref().unwrap());
+ }
+
}
-
+fn main() {
+ yew::Renderer::::new().render();
+}