{"id":18498229,"url":"https://github.com/andykswong/mugl","last_synced_at":"2025-04-09T00:31:07.905Z","repository":{"id":40667856,"uuid":"354661190","full_name":"andykswong/mugl","owner":"andykswong","description":"WebGPU and WebGL Micro 3D Graphics Library for JavaScript and WebAssembly","archived":false,"fork":false,"pushed_at":"2023-07-19T02:02:16.000Z","size":7411,"stargazers_count":106,"open_issues_count":8,"forks_count":5,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-29T03:34:28.311Z","etag":null,"topics":["3d","3d-graphics","assemblyscript","expo","gltf","gltf2","html5","javascript","react-native","renderer","typescript","wasm","webassembly","webgl","webgl2","webgpu"],"latest_commit_sha":null,"homepage":"https://andykswong.github.io/mugl/examples","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andykswong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-04-04T22:43:19.000Z","updated_at":"2025-03-28T13:23:09.000Z","dependencies_parsed_at":"2023-01-31T20:31:42.954Z","dependency_job_id":"c2d7aeb0-0201-4285-8212-934cd985fa6a","html_url":"https://github.com/andykswong/mugl","commit_stats":{"total_commits":103,"total_committers":3,"mean_commits":"34.333333333333336","dds":0.04854368932038833,"last_synced_commit":"27b9d9ef1342c8e8b07c3d8c43def915035b0989"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andykswong%2Fmugl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andykswong%2Fmugl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andykswong%2Fmugl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andykswong%2Fmugl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andykswong","download_url":"https://codeload.github.com/andykswong/mugl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247931922,"owners_count":21020359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["3d","3d-graphics","assemblyscript","expo","gltf","gltf2","html5","javascript","react-native","renderer","typescript","wasm","webassembly","webgl","webgl2","webgpu"],"created_at":"2024-11-06T13:38:12.563Z","updated_at":"2025-04-09T00:31:02.895Z","avatar_url":"https://github.com/andykswong.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e█▓▒­░⡷⠂μＧＬ⠐⢾░▒▓█\u003c/h1\u003e\n\u003ch2 align=\"center\"\u003emugl - WebGPU and WebGL Micro 3D Graphics Library for JavaScript and WebAssembly\u003c/h2\u003e\n\u003cbr/\u003e\n\n[![mugl](https://img.shields.io/badge/project-mugl-blueviolet.svg?style=flat-square\u0026logo=github)](https://github.com/andykswong/mugl)\n[![npm](https://img.shields.io/npm/v/mugl?style=flat-square\u0026logo=npm)](https://www.npmjs.com/package/mugl)\n[![docs](https://img.shields.io/badge/docs-typedoc-blue?style=flat-square\u0026logo=typescript\u0026logoColor=white)](http://andykswong.github.io/mugl)\n[![license: MIT](https://img.shields.io/badge/License-MIT-red.svg?style=flat-square)](./LICENSE)\n[![build](https://img.shields.io/github/actions/workflow/status/andykswong/mugl/build.yaml?style=flat-square)](https://github.com/andykswong/mugl/actions/workflows/build.yaml)\n\n\u003cbr/\u003e\n\n\n## Overview\n`mugl` is a minimal, modern 3D graphics abstraction layer that provides a simplified [WebGPU](https://gpuweb.github.io/gpuweb/)-style low-level graphics API for JavaScript. It supports both WebGPU and WebGL 2.0, runs on any modern web browser (WebGL/WebGPU), React Native mobile app (WebGL), and on WebAssembly (WASM) with [AssemblyScript](https://www.assemblyscript.org/) binding (WebGL/WebGPU).\n\n## Why `mugl`?\n`mugl` is for you if you want to:\n- render graphics from AssemblyScript / WASM using WebGPU or WebGL\n- use WebGL2 through a minimal modern graphics API that removes the verbosity and state management aspect of WebGL\n- use WebGPU today with fallback to WebGL2\n\n## Documentation\n- Latest JavaScript / AssemblyScript API: [Typedoc](http://andykswong.github.io/mugl/latest/docs)\n- Raw WebAssembly API spec: [API.wit](./API.wit), [AssemblyScript imports](./assembly/mugl.ts)\n\n## Showcase\n\n### [Live Examples](https://andykswong.github.io/mugl/latest/examples)\nCheck out the live examples [here](https://andykswong.github.io/mugl/latest/examples).\n\nThe source code of all examples can be found [here](./packages/examples/src/apps/). All examples run on **both WebGL and WebGPU, for both JavaScript and WebAssembly, using the same code base**! Click the toggles in the examples menu to seamlessly switch between JS/WASM and WebGL/WebGPU.\n\n|   |   |   |\n|---|---|---|\n|[![basic](./screenshots/basic.png)](https://andykswong.github.io/mugl/latest/examples/#basic)|[![instancing](./screenshots/instancing.png)](https://andykswong.github.io/mugl/latest/examples/#instancing)|[![postprocess](./screenshots/postprocess.png)](https://andykswong.github.io/mugl/latest/examples/#postprocess)|\n|[![mrt](./screenshots/mrt.png)](https://andykswong.github.io/mugl/latest/examples/#mrt)|[![stencil](./screenshots/stencil.png)](https://andykswong.github.io/mugl/latest/examples/#stencil)|[![pbr](./screenshots/pbr.png)](https://andykswong.github.io/mugl/latest/examples/#pbr)|\n\n### [glTF 2.0 Model Viewer](https://andykswong.github.io/mugl/latest/gltf-viewer)\n[\u003cimg src=\"./screenshots/DamagedHelmet.png\" width=\"192\" align=\"left\" style=\"margin: 0 2rem\" /\u003e](https://andykswong.github.io/mugl/latest/gltf-viewer/?model=DamagedHelmet)\n\nA small but full-featured glTF model viewer built on `mugl` is available as an example usage of this library [here](https://andykswong.github.io/mugl/latest/gltf-viewer). \\\nThe source code can be found [here](./packages/gltf-viewer).\n\nAny model from [glTF-Sample-Models](https://github.com/KhronosGroup/glTF-Sample-Models) can be loaded using the `model` and `variant` URL parameter, \\\ne.g.: [?model=Buggy\u0026variant=glTF-Binary](https://andykswong.github.io/mugl/latest/gltf-viewer/?model=Buggy\u0026variant=glTF-Binary\u0026camera=0\u0026scene=0) to load the [Buggy](https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Buggy) model. \\\nYou can also use the `url` URL parameter to load a model from any source ([example](https://andykswong.github.io/mugl/latest/gltf-viewer/?url=https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Avocado/glTF/Avocado.gltf)).\n\n\u003cbr style=\"clear: both\" /\u003e\n\n## Usage\n\n### 0. Install\n```shell\nnpm install --save mugl\n```\n\n### 1. Basic Rendering\nBelow is the minimal `mugl` program to draw a triangle (See this example live [here](https://andykswong.github.io/mugl/latest/examples/#basic)):\n```javascript\nimport { ShaderStage, VertexFormat, vertexBufferLayouts, WebGL } from 'mugl';\n\n// 0. Prepare triangle vertex positions and colors data\nconst triangle = new Float32Array([\n  // position  color\n  +0.0, +0.5,  1.0, 0.0, 0.0, 1.0, // vertex 0\n  +0.5, -0.5,  0.0, 1.0, 0.0, 1.0, // vertex 1\n  -0.5, -0.5,  0.0, 0.0, 1.0, 1.0, // vertex 2\n]);\n\n// 1. Create WebGL rendering device from an existing canvas\nconst device = WebGL.requestWebGL2Device(canvas);\nif (!device) throw new Error('WebGL 2.0 is unsupported');\n\n// Import `WebGPU` instead of `WebGL` to use WebGPU backend instead:\n// const device = await WebGPU.requestWebGPUDevice(canvas);\n\n// 2. Create GPU buffer and upload the triangle data\nconst buffer = WebGL.createBuffer(device, { usage, size: triangle.byteLength });\nWebGL.writeBuffer(device, buffer, triangle);\n\n// 3. Compile the vertex and fragment shaders. (for WebGPU, WGSL shader code should be used)\nconst vertex = WebGL.createShader(device, {\n  usage: ShaderStage.Vertex,\n  code: `#version 300 es\n    layout (location=0) in vec2 position;\n    layout (location=1) in vec4 color;\n    out vec4 vColor;\n    void main () {\n      gl_Position = vec4(position, 0., 1.);\n      vColor = color;\n    }`\n});\nconst fragment = WebGL.createShader(device, {\n  usage: ShaderStage.Fragment,\n  code: `#version 300 es\n    precision mediump float;\n    in vec4 vColor;\n    out vec4 outColor;\n    void main () {\n      outColor = vColor;\n    }`\n});\n\n// 4. Create the pipeline object\nconst pipeline = WebGL.createRenderPipeline(device, {\n  vertex, fragment,\n  // vertexBufferLayouts(...) auto-calculates the stride and offsets of vertex attributes for you\n  // Attribute indices / ordering must match the attribute locations specified in vertex shader\n  buffers: vertexBufferLayouts([\n    { attributes: [/* position */ VertexFormat.F32x2, /* color */ VertexFormat.F32x4] }\n  ]),\n});\n\n// 5. Submit draw call in a render pass\nWebGL.beginRenderPass(device);\n  WebGL.setRenderPipeline(device, pipeline);\n  WebGL.setVertex(device, 0, buffer);\n  WebGL.draw(device, 3); // 3 vertices to draw\nWebGL.submitRenderPass(device);\n\n// 6. Free up GPU resources\nvertex.destroy();\nfragment.destroy();\npipeline.destroy();\nbuffer.destroy();\ndevice.destroy();\n```\n\n### 2. Running on React Native Mobile Apps via expo-gl\n`mugl` is compatible with [expo-gl](https://docs.expo.dev/versions/latest/sdk/gl-view/) for 3D rendering on Expo / React Native mobile apps. Below is the setup required to use `mugl` with `expo-gl` (source code of the full example can be found [here](./packages/examples-native/)):\n\n```javascript\nimport React from 'react';\nimport { Asset } from 'expo-asset';\nimport { GLView } from 'expo-gl';\nimport { WebGL } from 'mugl';\n\nexport default function App() {\n  return (\u003cGLView style={{ width: 300, height: 300 }} onContextCreate={onContextCreate} /\u003e);\n}\n\nasync function onContextCreate(gl) {\n  // 1. Create device by passing a canvas-like object that wraps the gl context\n  const canvas = { getContext() { return gl; }, width: 300, height: 300 };\n  const device = WebGL.requestWebGL2Device(canvas);\n\n  // 2. Use expo-asset to load an image to GPU texture\n  const image = (await Asset.loadAsync(require('./image.png')))[0];\n  const size = [512, 512, 1];\n  const texture = WebGL.createTexture(device, { size });\n  WebGL.copyExternalImageToTexture(device, { src: image }, { texture }, size);\n\n  // 3. Setup other resources\n  const pipeline = WebGL.createRenderPipeline(device, { ... });\n  const buffer = WebGL.createBuffer(device, { ... });\n  WebGL.writeBuffer(device, buffer, ...);\n  const bindgroup = WebGL.createBindGroup(device, { layout, entries: [{ texture }] });\n\n  // 4. Render as usual\n  WebGL.beginRenderPass(device);\n    WebGL.setRenderPipeline(device, pipeline);\n    WebGL.setVertex(device, 0, buffer);\n    WebGL.setBindGroup(device, 0, bindgroup);\n    WebGL.draw(device, ...);\n  WebGL.submitRenderPass(device);\n\n  // 5. Call the expo-gl 'swap buffers' API at the end of each frame\n  // See: https://docs.expo.dev/versions/latest/sdk/gl-view/#webgl-api\n  gl.endFrameEXP();\n}\n```\n\nAs `expo-gl` does not fully support all WebGL2 APIs, you may find some advanced features of `mugl` not working as expected. Notably missing is `pixelStorei` API support for defining texture image source offsets.\n\n### 3. Running on WebAssembly\nImport `mugl/wasm` to your WASM module:\n\n```javascript\n// 1. Import mugl/wasm\nimport * as muglWasm from 'mugl/wasm';\n\n// 2. Import your WASM module as ESM (require Webpack with experiments.asyncWebAssembly = true):\nimport * as exports from './your_module.wasm';\n\n// 2b. Alternatively, using the WASM API, add mugl/wasm to your module imports\nconst imports = { 'mugl/wasm': muglWasm, ... };\nconst exports = (await WebAssembly.instantiateStreaming(\n  fetch('your_module.wasm'), imports\n)).instance.exports;\n\n// 3. Expose WASM module memory to mugl. This must be done before your WASM module calls any mugl method.\nconst CONTEXT_ID = 123; // Define a unique numeric ID for your WASM module\nmuglWasm.set_context_memory(CONTEXT_ID, exports.memory);\n```\n\nIn the AssemblyScript WASM module, you can then use `getCanvasById` to get a canvas handle for creating a device:\n```javascript\nimport { getCanvasById, WebGL } from 'mugl';\nconst CONTEXT_ID = 123; // This must be the same ID as above\nconst device = WebGL.requestWebGL2Device(getCanvasById(CONTEXT_ID, 'canvasId'));\n```\n\nSee the [examples source code](./packages/examples) on how to build an AssemblyScript mugl app.\n\n## License\nThis repository and the code inside it is licensed under the MIT License. Read [LICENSE](./LICENSE) for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandykswong%2Fmugl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandykswong%2Fmugl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandykswong%2Fmugl/lists"}