#webgl #web-gpu #3d #graphics #abstraction-layer #muge

无 std mugl

为 Rust 和 WebAssembly 设计的最小化低级别 WebGL 2.0 / WebGPU 3D 图形抽象层

3 个版本

0.1.2 2022 年 4 月 25 日
0.1.1 2022 年 4 月 16 日
0.1.0 2022 年 4 月 16 日

#464 in 图形 API


用于 mugltf

MIT 许可证

585KB
4.5K SLoC

█▓▒−░⡷⠂μ GL⠐⢾░▒▓█

Rust 的 Micro WebGL2 / WebGPU 图形库


License: MIT Crates.io Docs.rs

概述

mugl 是一个最小化、现代化的 WebGL 2.0 / WebGPU 3D 图形抽象层。它提供了一个简化的 WebGPU 风格的 API,可在网页上使用 WebGL 2.0 运行,在其他平台上使用本机 WebGPU。

安装

[dependencies]
mugl = "0.1"

功能

  • backend-webgl - 为 WASM 启用 WebGL 2.0 后端。需要 mugl/wasm npm 软件包进行粘合代码。 (参见 用法)
  • backend-wgpu - 基于 wgpu 启用 WebGPU 后端
  • std - 启用 std 支持
  • wasm-bindgen 启用 wasm-bindgen 集成
  • serde - 启用 serde 序列化/反序列化实现

文档

请参阅 Docs.rs: https://docs.rs/mugl

用法

示例

此存储库中可以找到几个示例。使用 npm 在网页上运行以下示例:npm install && npm start

屏幕截图 源代码 运行脚本
basic 基本 cargo运行 --功能backend-wgpu --示例基本
instancing 实例化 cargo运行 --功能backend-wgpu --示例实例化
stencil 模板 cargo运行 --功能backend-wgpu --示例模板

你好世界

以下是在基本示例中使用 WebGL 后端绘制三角形的最小 WASM 应用程序(参见完整的示例代码 这里

use mugl::{prelude::*, webgl::*};

// (Optional) Define a unique app ID to use in JS glue code. Required only when multiple WASM modules use mugl.
#[no_mangle]
pub extern "C" fn app_id() -> ContextId { ContextId::set(123); ContextId::get() }

#[no_mangle]
pub extern "C" fn render() {
    app_id(); // Make sure we call ContextId::set() before any API call.

    // 1. Create device from canvas of id "canvas"
    let canvas = Canvas::from_id("canvas");
    let device = WebGL::request_device(&canvas, WebGLContextAttribute::default(), WebGL2Features::empty())
        .expect("WebGL 2.0 is unsupported");

    // 2. Create buffer
    let vertices: &[f32] = &[
        // position      color 
        0.0, 0.5, 0.0,   1.0, 0.0, 0.0, 1.0,
        0.5, -0.5, 0.0,  0.0, 1.0, 0.0, 1.0,
        -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 1.0
    ];
    let vertices: &[u8] = bytemuck::cast_slice(vertices);
    let buffer = device.create_buffer(BufferDescriptor { usage: BufferUsage::VERTEX, size: 3 });
    device.write_buffer(&buffer, 0, vertices);

    // 3. Create shaders
    let vertex = &device.create_shader(ShaderDescriptor {
        usage: ShaderStage::VERTEX,
        code: "#version 300 es
        layout (location=0) in vec3 position;
        layout (location=1) in vec4 color;
        out vec4 vColor;
        void main () {
          gl_Position = vec4(position, 1);
          vColor = color;
        }
        ".into(),
    });
    let fragment = &device.create_shader(ShaderDescriptor {
        usage: ShaderStage::FRAGMENT,
        code: "#version 300 es
        precision mediump float;
        in vec4 vColor;
        out vec4 outColor;
        void main () {
          outColor = vColor;
        }
        ".into(),
    });

    // 4. Create pipeline
    let pipeline = device.create_render_pipeline(RenderPipelineDescriptor {
        vertex,
        fragment,
        buffers: &[VertexBufferLayout {
            stride: core::mem::size_of::<[f32; 7]>() as BufferSize,
            step_mode: VertexStepMode::Vertex,
            attributes: &[
                VertexAttribute { shader_location: 0, format: VertexFormat::F32x3, offset: 0 },
                VertexAttribute { shader_location: 1, format: VertexFormat::F32x4, offset: core::mem::size_of::<[f32; 3]>() as BufferSize },
            ],
        }],
        bind_groups: &[],
        targets: Default::default(),
        primitive: Default::default(),
        depth_stencil: Default::default(),
        multisample: Default::default(),
    });

    // 5. Create default pass
    let pass = device.create_render_pass(RenderPassDescriptor::Default {
        clear_color: Some(Color(0.1, 0.2, 0.3, 1.0)),
        clear_depth: None,
        clear_stencil: None,
    });

    // 6. Render
    {
        let encoder = device.render(&pass);
        encoder.pipeline(&pipeline);
        encoder.vertex(0, &buffer, 0);
        encoder.draw(0..3, 0..1);
        encoder.submit();
    }
    device.present();
}

要运行上述 WASM 模块,您需要依赖 mugl NPM 软件包和以下 JS 粘合代码

npm install --save mugl
import { set_context_memory } from "mugl/wasm";
import { memory, app_id, render } from "hello_world.wasm";

set_context_memory(app_id(), memory); // Required only if `wasm-bindgen` feature is not enabled

// 1. Create canvas with id "canvas"
const canvas = document.createElement("canvas");
canvas.id = "canvas";
canvas.width = canvas.height = 512;
document.body.appendChild(canvas);

// 2. Call render in WASM
render();

依赖项

~0.4–13MB
~151K SLoC