展示HN:Mystral Native – 使用WebGPU原生运行JavaScript游戏(无需浏览器)
Show HN: Mystral Native – Run JavaScript games natively with WebGPU (no browser)

原始链接: https://github.com/mystralengine/mystralnative

## Mystral Native.js:原生运行网页游戏 Mystral Native.js 是一个轻量级运行时,允许开发者构建和运行 JavaScript/TypeScript 游戏,作为原生桌面应用程序在 macOS、Windows 和 Linux 上运行——无需浏览器。它利用熟悉的 Web API,如 WebGPU、Canvas、Audio 和 fetch,提供了一种“游戏的 Electron”替代方案,但去除了 Chromium 的开销。 目前处于早期 Alpha 阶段,Mystral Native.js 支持对 WebGPU、Canvas 2D、Web Audio 和 fetch 执行 JS。 提供了 iOS 和 Android 的嵌入选项,并计划未来支持主机平台。 **主要特性:** * **原生性能:** 利用 WebGPU 实现原生渲染。 * **熟悉 API:** 使用标准的 Web API 进行游戏开发。 * **跨平台:** 支持 macOS、Windows、Linux、iOS 和 Android。 * **打包:** 游戏可以编译成独立的可执行文件进行分发。 * **灵活配置:** 提供 JS 引擎(V8、QuickJS、JSC)和 WebGPU 后端(Dawn、wgpu-native)的选择。 **入门:** 安装可以通过 CLI 或下载预构建的二进制文件来完成。 示例,包括“Hello Triangle”演示和一个更复杂的 Sponza 场景,可在 [itch.io](https://mystralengine.github.io/mystralnative/) 上找到。 更多详细信息和文档请访问 [mystralengine.github.io/mystralnative](https://mystralengine.github.io/mystralnative)。

## Mystral Native:JavaScript 游戏的轻量级运行时 Mystral Native 是一款新的轻量级原生运行时,旨在无需像 Chromium 这样的浏览器即可运行 JavaScript/TypeScript 游戏,将其作为独立的桌面和移动应用程序。它作为跨平台游戏部署挑战的解决方案,提供了类似于 Web 开发的开发体验(使用 WebGPU、Canvas 2D、Web Audio 以及 `requestAnimationFrame` 等熟悉 API),但与基于 Electron 的解决方案相比,生成的原生二进制文件明显更小(约 25MB 运行时)。 它利用 Dawn/wgpu-native 用于 WebGPU,SDL3 用于窗口管理和事件,以及 V8(或 QuickJS/JSC 等替代方案)用于 JavaScript 执行。Mystral Native 将代码编译为 macOS、Linux 和 Windows 的单个可执行文件,并为 iOS 和 Android 提供嵌入 API。 目前处于早期 Alpha 阶段,该项目旨在提供跨平台的统一 WebGPU 体验,避免 Webview 的不一致性。该项目是开源的(MIT 许可),并寻求反馈 – 仓库和文档地址:[https://github.com/mystralengine/mystralnative](https://github.com/mystralengine/mystralnative)。
相关文章

原文

Mystral Native.js

Discord Release MIT License

Run JavaScript/TypeScript games natively with WebGPU. Mystral Native.js is a lightweight runtime that lets you write games using familiar Web APIs (WebGPU, Canvas, Audio, fetch) and run them as native desktop applications on macOS, Windows, and Linux.

Think of it as "Electron for games" but without Chromium — just your game code, a JS engine, and native WebGPU rendering.

Note

Mystral Native.js is in early alpha. The core features work — execute JS against WebGPU, Canvas 2D, Web Audio, and fetch — with runtimes available for macOS, Windows, and Linux. Embedding is available for iOS and Android, with a future goal of console support. To see a production build, check out the Sponza demo on itch.io.

Option 1: Install via CLI (Recommended)

macOS / Linux:

curl -fsSL https://mystralengine.github.io/mystralnative/install.sh | bash

Windows (PowerShell):

irm https://mystralengine.github.io/mystralnative/install.ps1 | iex

This detects your platform, downloads the latest release, installs to ~/.mystral/ (or $HOME\.mystral\ on Windows), and adds mystral to your PATH. Then run the examples:

# macOS / Linux
cd ~/.mystral
mystral run examples/triangle.js
mystral run examples/mystral-helmet.js  # GLTF loading demo
# Windows (PowerShell)
cd $HOME\.mystral
mystral run examples\triangle.js
mystral run examples\mystral-helmet.js  # GLTF loading demo

Option 2: Download Prebuilt Binary

Download the latest release for your platform from the releases page:

Platform Download
macOS (Apple Silicon) mystral-macOS-arm64-v8-dawn.zip
macOS (Intel) mystral-macOS-x64-v8-dawn.zip
Windows mystral-windows-x64-v8-dawn.zip
Linux mystral-linux-x64-v8-dawn.zip
unzip mystral-macOS-arm64-v8-dawn.zip
cd mystral-macOS-arm64-v8-dawn
./mystral run examples/triangle.js

Option 3: Build from Source

git clone https://github.com/mystralengine/mystralnative.git
cd mystralnative

# Install bun if you don't have it
curl -fsSL https://bun.sh/install | bash

# Download dependencies
bun install
bun run deps:download

# Configure with V8 + Dawn (recommended)
cmake -B build \
  -DMYSTRAL_USE_V8=ON \
  -DMYSTRAL_USE_DAWN=ON \
  -DMYSTRAL_USE_QUICKJS=OFF \
  -DMYSTRAL_USE_WGPU=OFF

# Build
cmake --build build --parallel

# Run an example
./build/mystral run examples/triangle.js

Here's a complete "Hello Triangle" — the traditional first GPU program:

// hello-triangle.js
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();
const context = canvas.getContext("webgpu");
const format = navigator.gpu.getPreferredCanvasFormat();
context.configure({ device, format });

const shader = device.createShaderModule({
  code: `
    @vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4f {
      var pos = array<vec2f, 3>(
        vec2f( 0.0,  0.5),
        vec2f(-0.5, -0.5),
        vec2f( 0.5, -0.5)
      );
      return vec4f(pos[i], 0.0, 1.0);
    }

    @fragment fn fs() -> @location(0) vec4f {
      return vec4f(1.0, 0.5, 0.2, 1.0); // orange
    }
  `,
});

const pipeline = device.createRenderPipeline({
  layout: "auto",
  vertex: { module: shader, entryPoint: "vs" },
  fragment: { module: shader, entryPoint: "fs", targets: [{ format }] },
});

function render() {
  const encoder = device.createCommandEncoder();
  const pass = encoder.beginRenderPass({
    colorAttachments: [{
      view: context.getCurrentTexture().createView(),
      clearValue: { r: 0.1, g: 0.1, b: 0.1, a: 1 },
      loadOp: "clear",
      storeOp: "store",
    }],
  });
  pass.setPipeline(pipeline);
  pass.draw(3);
  pass.end();
  device.queue.submit([encoder.finish()]);
  requestAnimationFrame(render);
}
render();

Save it and run:

mystral run hello-triangle.js

You'll see an orange triangle on a dark background — rendered natively via WebGPU with no browser involved.

# Basic WebGPU triangle
mystral run examples/triangle.js

# 3D rotating cube
mystral run examples/simple-cube.js

# Full 3D scene with PBR lighting (Dawn builds only)
mystral run examples/mystral-helmet.js

# Day/night cycle demo with atmosphere
mystral run examples/daynight.js

# Sponza palace with day/night, torches, fireflies (Dawn builds only)
mystral run examples/sponza.js

# Custom window size
mystral run examples/simple-cube.js --width 1920 --height 1080

# Watch mode — auto-reload on file changes
mystral run game.js --watch

# Headless screenshot (for CI/testing)
mystral run examples/simple-cube.js --headless --screenshot output.png
Example Description
triangle.js Minimal WebGPU — orange triangle
simple-cube.js 3D cube with matrices
test-audio.js Web Audio API test
test-gamepad.js Gamepad API test
mystral-helmet.js Full Mystral Engine with DamagedHelmet model
daynight.js Day/night cycle with atmosphere, stars, moon, torches
sponza.js Sponza palace with day/night cycle, torches, fireflies

Bundling for Distribution

Package your game into a single executable that players can run with no dependencies:

# Compile into a standalone binary (Linux/Windows)
mystral compile game.js --include assets --out dist/my-game
./dist/my-game

# Create a standalone .bundle for macOS .app packaging
mystral compile game.js --include assets --bundle-only --out dist/game.bundle

See the distribution guide for platform-specific packaging details including macOS .app bundles, code signing, and more.

Use the production build script to create stripped, optimized, asset-filtered builds locally (mirrors CI):

# Full production build of Sponza demo (strips binary, filters assets, creates .app + .zip)
./scripts/build-production.sh

# Build a different demo
./scripts/build-production.sh --demo helmet

# Skip cmake rebuild (repackage with existing binary)
./scripts/build-production.sh --skip-build
mystral run <script.js> [options]      Run a JavaScript/TypeScript file
mystral compile <entry.js> [options]   Bundle into single executable
mystral --version                      Show version
mystral --help                         Show help

Run Options:
  --width <n>           Window width (default: 1280)
  --height <n>          Window height (default: 720)
  --title <str>         Window title
  --headless            Run with hidden window
  --watch, -w           Auto-reload on file changes
  --screenshot <file>   Take screenshot and quit
  --frames <n>          Frames before screenshot (default: 60)
  --quiet, -q           Suppress output except errors

Compile Options:
  --include <dir>       Asset directory to bundle (repeatable)
  --output, -o <file>   Output path
  --bundle-only         Create .bundle file (for .app packaging)
  --root <dir>          Root directory for bundle paths (default: cwd)
┌─────────────────────────────────────────────────────────────┐
│                   Your Game (JS/TS)                          │
│             Uses WebGPU, Canvas, Audio APIs                  │
└─────────────────────────────────────────────────────────────┘
                              │
┌─────────────────────────────────────────────────────────────┐
│                  MystralNative Runtime                       │
│   WebGPU Bindings │ Canvas 2D │ Audio │ fetch │ Input       │
└─────────────────────────────────────────────────────────────┘
        │                │           │        │
        ▼                ▼           ▼        ▼
   ┌─────────┐    ┌───────────┐  ┌─────┐  ┌──────┐  ┌───────┐
   │ V8/JSC/ │    │   Dawn/   │  │SDL3 │  │libcurl│  │ libuv │
   │ QuickJS │    │ wgpu-native│  │     │  │      │  │       │
   └─────────┘    └───────────┘  └─────┘  └──────┘  └───────┘
API Status
WebGPU ✅ Full support
Canvas 2D (Skia) ✅ Working
Web Audio ✅ Working
fetch (file/http/https) ✅ Working
URL / URLSearchParams ✅ Working
Worker (main-thread) ✅ Working
Gamepad ✅ Working
requestAnimationFrame ✅ Working
setTimeout/setInterval ✅ Working
ES Modules (import/export) ✅ Working
TypeScript (via SWC) ✅ Working
GLTF/GLB loading (incl. Draco) ✅ Working
Platform JS Engine Options WebGPU Backend
macOS (arm64) V8, JSC, QuickJS Dawn, wgpu-native
macOS (x64) V8, JSC, QuickJS Dawn, wgpu-native
Windows V8, QuickJS Dawn, wgpu-native
Linux V8, QuickJS Dawn, wgpu-native
iOS JSC, QuickJS wgpu-native
Android V8, QuickJS wgpu-native

Recommended for development (full shader compatibility):

cmake -B build \
  -DMYSTRAL_USE_V8=ON \
  -DMYSTRAL_USE_DAWN=ON \
  -DMYSTRAL_USE_QUICKJS=OFF \
  -DMYSTRAL_USE_WGPU=OFF

Alternative configurations:

Choose your JS engine:

cmake -B build -DMYSTRAL_USE_V8=ON       # Recommended — Full V8 with JIT
cmake -B build -DMYSTRAL_USE_QUICKJS=ON  # Smallest binary, good for CI
cmake -B build -DMYSTRAL_USE_JSC=ON      # macOS/iOS system engine

Choose your WebGPU backend:

cmake -B build -DMYSTRAL_USE_DAWN=ON     # Recommended — Chrome's implementation
cmake -B build -DMYSTRAL_USE_WGPU=ON     # Rust implementation, best iOS/Android support

Use MystralNative as a library in your C++ application:

#include "mystral/runtime.h"

int main() {
    mystral::RuntimeConfig config;
    config.width = 1280;
    config.height = 720;
    config.title = "My Game";

    auto runtime = mystral::Runtime::create(config);
    runtime->loadScript("game.js");
    runtime->run();
    return 0;
}

See the embedding guide for iOS, Android, and CMake integration details.

All dependencies are downloaded automatically as prebuilt binaries:

Dependency Purpose
Dawn / wgpu-native WebGPU implementation
SDL3 Windowing, input, audio
V8 / QuickJS / JSC JavaScript engine
Skia Canvas 2D rendering
libcurl HTTP requests
libuv Async I/O, timers, file watching
Draco Native Draco mesh decompression (optional)
SWC TypeScript transpiling

Prebuilt dependency binaries are managed via mystralengine/library-builder.

Full documentation is available at mystralengine.github.io/mystralnative.

Issues and PRs welcome! See the GitHub repository.

MIT License — see LICENSE for details.

联系我们 contact @ memedata.com