Get a WebGL canvas working in Sycamore
This commit is contained in:
parent
c48d685ad6
commit
fd3cbae1b4
3
app-proto/inversive-display/.gitignore
vendored
Normal file
3
app-proto/inversive-display/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target
|
||||||
|
dist
|
||||||
|
Cargo.lock
|
37
app-proto/inversive-display/Cargo.toml
Normal file
37
app-proto/inversive-display/Cargo.toml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
[package]
|
||||||
|
name = "inversive-display"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Aaron"]
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["console_error_panic_hook"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
js-sys = "0.3.70"
|
||||||
|
sycamore = "0.9.0-beta.2"
|
||||||
|
|
||||||
|
# The `console_error_panic_hook` crate provides better debugging of panics by
|
||||||
|
# logging them with `console.error`. This is great for development, but requires
|
||||||
|
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
|
||||||
|
# code size when deploying.
|
||||||
|
console_error_panic_hook = { version = "0.1.7", optional = true }
|
||||||
|
|
||||||
|
[dependencies.web-sys]
|
||||||
|
version = "0.3.69"
|
||||||
|
features = [
|
||||||
|
'HtmlCanvasElement',
|
||||||
|
'WebGl2RenderingContext',
|
||||||
|
'WebGlBuffer',
|
||||||
|
'WebGlProgram',
|
||||||
|
'WebGlShader',
|
||||||
|
'WebGlVertexArrayObject',
|
||||||
|
'Window'
|
||||||
|
]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
wasm-bindgen-test = "0.3.34"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = "s" # optimize for small code size
|
||||||
|
debug = true # include debug symbols
|
9
app-proto/inversive-display/index.html
Normal file
9
app-proto/inversive-display/index.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Inversive display</title>
|
||||||
|
<link data-trunk rel="css" href="main.css"/>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
</html>
|
23
app-proto/inversive-display/main.css
Normal file
23
app-proto/inversive-display/main.css
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
body {
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-top: 20px;
|
||||||
|
color: #fcfcfc;
|
||||||
|
background-color: #202020;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
float: left;
|
||||||
|
background-color: #020202;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
152
app-proto/inversive-display/src/main.rs
Normal file
152
app-proto/inversive-display/src/main.rs
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
// based on the WebGL example in the `wasm-bindgen` guide
|
||||||
|
//
|
||||||
|
// https://rustwasm.github.io/wasm-bindgen/examples/webgl.html
|
||||||
|
//
|
||||||
|
|
||||||
|
extern crate js_sys;
|
||||||
|
use std::f64::consts::PI as PI;
|
||||||
|
use sycamore::{prelude::*, rt::{JsCast, JsValue}};
|
||||||
|
use web_sys::{console, WebGl2RenderingContext, WebGlProgram, WebGlShader};
|
||||||
|
|
||||||
|
fn compile_shader(
|
||||||
|
context: &WebGl2RenderingContext,
|
||||||
|
shader_type: u32,
|
||||||
|
source: &str,
|
||||||
|
) -> WebGlShader {
|
||||||
|
let shader = context.create_shader(shader_type).unwrap();
|
||||||
|
context.shader_source(&shader, source);
|
||||||
|
context.compile_shader(&shader);
|
||||||
|
shader
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// set up a config option that forwards panic messages to `console.error`
|
||||||
|
#[cfg(feature = "console_error_panic_hook")]
|
||||||
|
console_error_panic_hook::set_once();
|
||||||
|
|
||||||
|
sycamore::render(|| {
|
||||||
|
let tip = create_signal(0.0);
|
||||||
|
let display = create_node_ref();
|
||||||
|
|
||||||
|
on_mount(move || {
|
||||||
|
// get the display canvas
|
||||||
|
let canvas = display
|
||||||
|
.get::<DomNode>()
|
||||||
|
.unchecked_into::<web_sys::HtmlCanvasElement>();
|
||||||
|
let ctx = canvas
|
||||||
|
.get_context("webgl2")
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.dyn_into::<WebGl2RenderingContext>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// load the vertex and fragment shaders
|
||||||
|
let vertex_shader = compile_shader(
|
||||||
|
&ctx,
|
||||||
|
WebGl2RenderingContext::VERTEX_SHADER,
|
||||||
|
r##"#version 300 es
|
||||||
|
|
||||||
|
in vec4 position;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = position;
|
||||||
|
}
|
||||||
|
"##,
|
||||||
|
);
|
||||||
|
let fragment_shader = compile_shader(
|
||||||
|
&ctx,
|
||||||
|
WebGl2RenderingContext::FRAGMENT_SHADER,
|
||||||
|
r##"#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
out vec4 outColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
outColor = vec4(gl_FragCoord.xy / 600., 1., 1.);
|
||||||
|
}
|
||||||
|
"##,
|
||||||
|
);
|
||||||
|
let program = ctx.create_program().unwrap();
|
||||||
|
ctx.attach_shader(&program, &vertex_shader);
|
||||||
|
ctx.attach_shader(&program, &fragment_shader);
|
||||||
|
ctx.link_program(&program);
|
||||||
|
let link_status = ctx
|
||||||
|
.get_program_parameter(&program, WebGl2RenderingContext::LINK_STATUS)
|
||||||
|
.as_bool()
|
||||||
|
.unwrap();
|
||||||
|
let link_msg = if link_status {
|
||||||
|
"Linked successfully"
|
||||||
|
} else {
|
||||||
|
"Linking failed"
|
||||||
|
};
|
||||||
|
console::log_1(&JsValue::from(link_msg));
|
||||||
|
ctx.use_program(Some(&program));
|
||||||
|
|
||||||
|
// set up a repainting routine
|
||||||
|
create_effect(move || {
|
||||||
|
// list the vertices
|
||||||
|
let vertices: [f32; 9] = [
|
||||||
|
-0.9, 0.9, 0.0,
|
||||||
|
-0.9, -0.9, 0.0,
|
||||||
|
0.9*(tip.get() as f32), 0.0, 0.0
|
||||||
|
];
|
||||||
|
|
||||||
|
// create a vertex buffer and bind it to ARRAY_BUFFER
|
||||||
|
let position_attribute_location = ctx.get_attrib_location(&program, "position");
|
||||||
|
let buffer = ctx.create_buffer().unwrap();
|
||||||
|
ctx.bind_buffer(WebGl2RenderingContext::ARRAY_BUFFER, Some(&buffer));
|
||||||
|
|
||||||
|
// load the vertex list into the vertex 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
|
||||||
|
unsafe {
|
||||||
|
ctx.buffer_data_with_array_buffer_view(
|
||||||
|
WebGl2RenderingContext::ARRAY_BUFFER,
|
||||||
|
&js_sys::Float32Array::view(&vertices),
|
||||||
|
WebGl2RenderingContext::STATIC_DRAW,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a vertex array and bind it to the graphics context
|
||||||
|
let vtx_array_obj = ctx.create_vertex_array().unwrap();
|
||||||
|
ctx.bind_vertex_array(Some(&vtx_array_obj));
|
||||||
|
|
||||||
|
// use whatever is bound to ARRAY_BUFFER---here, the vertex
|
||||||
|
// buffer created above---as the vertex attribute array
|
||||||
|
//
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/vertexAttribPointer
|
||||||
|
//
|
||||||
|
ctx.vertex_attrib_pointer_with_i32(
|
||||||
|
position_attribute_location as u32,
|
||||||
|
3, // dimension
|
||||||
|
WebGl2RenderingContext::FLOAT, // type
|
||||||
|
false, // normalized?
|
||||||
|
0, // stride
|
||||||
|
0, // offset
|
||||||
|
);
|
||||||
|
ctx.enable_vertex_attrib_array(position_attribute_location as u32);
|
||||||
|
|
||||||
|
// clear the screen and draw the scene
|
||||||
|
let vert_count = (vertices.len() / 3) as i32;
|
||||||
|
ctx.clear_color(0.0, 0.0, 0.0, 1.0);
|
||||||
|
ctx.clear(WebGl2RenderingContext::COLOR_BUFFER_BIT);
|
||||||
|
ctx.draw_arrays(WebGl2RenderingContext::TRIANGLES, 0, vert_count);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
view! {
|
||||||
|
div(id="app") {
|
||||||
|
canvas(ref=display, width="600", height="600")
|
||||||
|
input(
|
||||||
|
type="range",
|
||||||
|
max=1.0,
|
||||||
|
step=0.01,
|
||||||
|
bind:valueAsNumber=tip
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user