WebGPU Rust和Javascript通信

jexiocij  于 2023-05-17  发布在  Java
关注(0)|答案(1)|浏览(174)

我通过以下方式合并WebGPU+Rust
(index.html)

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GreenMatterAI graphics preview</title>
    <style>
        canvas {
            background-color: black;
        }
    </style>
</head>

<body id="wasm-example">
<script type="module">
      import init from "./pkg/gmai_cad.js";
      init().then(() => {
          console.log("WASM Loaded");
      });
  </script>
</body>

</html>

(lib.rs)

#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
pub async fn run() {
    cfg_if::cfg_if! {
        if #[cfg(target_arch = "wasm32")] {
            std::panic::set_hook(Box::new(console_error_panic_hook::hook));
            console_log::init_with_level(log::Level::Warn).expect("Couldn't initialize logger");
        } else {
            env_logger::init();
        }
    }

    let event_loop = EventLoop::new();
    let window = WindowBuilder::new().build(&event_loop).unwrap();
    #[cfg(target_arch = "wasm32")]
    {
        use winit::dpi::PhysicalSize;
        window.set_inner_size(PhysicalSize::new(450, 400));

        use winit::platform::web::WindowExtWebSys;
        web_sys::window()
            .and_then(|win| win.document())
            .and_then(|doc| {
                let dst = doc.get_element_by_id("wasm-example")?;
                let canvas = web_sys::Element::from(window.canvas());
                dst.append_child(&canvas).ok()?;
                Some(())
            })
            .expect("Couldn't append canvas to document body.");
    }
    let mut state = State::new(window).await;
    event_loop.run(move |event, _, control_flow| match event {
        Event::RedrawRequested(window_id) if window_id == state.window().id() => {
            state.update();
            state.render()
        }
        Event::MainEventsCleared => {
            state.window().request_redraw();
        }
        Event::WindowEvent {
            ref event,
            window_id,
        } => { state.event(event) },
        _ => {}
    });
}

这段代码的结构方式使我无法将任何数据从Javascript传递到渲染循环。我想有一些HTML输入,用户可以修改和影响交互式渲染。我唯一想到的是有一个全局可变变量,并公开一些JavaScript可以用来修改这些变量的Rust函数。当然,这是一个明显的Rust反模式。关于这一点的规范方法是什么?

xzv2uavs

xzv2uavs1#

不要使用标记为#[wasm_bindgen(start)]的函数,而是使用普通的#[wasm_bindgen]导出函数,该函数可以接受参数,并从JavaScript调用它。

#[cfg(target_arch = "wasm32")
#[wasm_bindgen]
pub async fn run_in_browser(configuration: JsValue /* or whatever */) {
    ...
}
<script type="module">
    import init, { run_in_browser } from "./pkg/gmai_cad.js";
    init().then(() => {
        console.log("WASM Loaded");
        run_in_browser({ /* put configuration/callbacks here */ });
    });
</script>

相关问题