@oxgl-js/oxgl

中文文档
0.1.1发布于 2026/11/02BSD-3-ClauseTypeScriptES Module零依赖

符合标准的无头WebGL 1和WebGL 2

中文使用文档
文档目录14 节
  1. 安装
  2. 平台
  3. 已知的问题
  4. 使用
  5. 画布和调整大小
  6. 后端
  7. 扩展
  8. 环境损失
  9. 发布环境
  10. 错误
  11. 表演
  12. 先决条件
  13. 命令
  14. 许可证

oxgl

ci npm license

符合标准的WebGL 1和WebGL 2的Node.js,通过 角度,与SwiftShader软件回退。完整的WebGL 1和WebGL 2 api 的实现,带有扩展和上下文丢失,并根据 Khronos一致性套件;js不加修改地渲染它。

安装

npm install @oxgl-js/oxgl

预构建Linux x64和arm64 (glibc 2.34或更新版本,如Ubuntu 22.04或 Debian 12), macOS arm64, Windows x64和arm64,在Node.js 22.22.2或 更新。安装不需要Rust工具链、编译器或安装脚本:npm 只下载主机的平台包(@oxgl-js/<platform>),其中包含 本地插件及其ANGLE库。Linux与肌肉(如Alpine)有 没有建立;在那里导入oxgl会抛出一个错误 code === 'OXGL_NATIVE_MISSING'。要从源代码构建,请参见下面的先决条件 和 CONTRIBUTING.md.

平台

支持和测试:Linux x64和Linux arm64 (glibc), macOS arm64, Windows x64和Windows arm64。每个都有一个固定的ANGLE包,CI运行Rust和 节点测试和两个Khronos一致性套件在每个软件上 后端。这个 结果页面 显示每一个 的一致性页面和js示例在每个平台上的结果 最新运行的CI main,为每一个不及格的理由。 一致性结果与Linux arm64仅在这些页面中有所不同 conformance/expectations.txt 它们适用的平台列表:

  • 在x64 (Linux和Windows)上,18个deqp页面呈现为32位整数 彩色缓冲器(rgba32i, r32ui 与之相似的是,他们的图像比较失败了, 因为WebGL一致性测试中的一个bug:他们的着色器转换浮点数 刚刚超过32位整数范围,GLSL未定义 参考图像假设结果是固定的。Arm64箝位和x86没有。 原生dEQP测试在2018年修复了这个问题;WebGL端口没有。

Mac上的Docker没有向Linux容器公开GPU,因此Linux arm64运行使用 软件后端。在macOS arm64上已经检查了GPU后端路径 (苹果GPU上的ANGLE Metal):所有Node测试都通过,并且Khronos结果匹配 Linux arm64除在图像解码上的差异外,由一致性决定 Runner的canvas包(当时是node-canvas;现在 @napi-rs/canvas)。

已知的问题

  • SwiftShader初始化简单地改变进程全局状态。 这个 进程中的第一个SwiftShader上下文(backend: 'software', OXGL_BACKEND=software,或 'auto' GPU无法提供的上下文, 是否没有可用的GPU或一个GPU上下文创建失败,为 例如当GPU内存耗尽时)使角度设置 VK_ICD_FILENAMES 在Linux和Windows上,更改工作目录 几毫秒,然后恢复两者。的线程 环境或使用的相对路径在那一刻可能会出错或崩溃。 GPU后端不受影响。控制这种情况的发生,创造和毁灭 在启动其他线程之前,启动时的一个软件上下文。原因是 角的 ScopedVkLoaderEnvironment;这个条目一旦被固定就会消失 角度停止这样做(跟踪) angle/README.md“已知的上游问题”)。
  • SwiftShader可以得到一个近剪切三角形的深度错误。 与 软件后端,一个大的三角形表示可以在近平面剪辑中绘制 深度太近,隐藏了前面的几何形状。一个典型的 Case是一个由两个三角形组成的地平面,通过相机下方,其中 然后隐藏站在上面的物体。GPU后端不受影响。细分 大的几何图形(例如 new THREE.PlaneGeometry(6, 6, 32, 32) 而不是 PlaneGeometry(6, 6))避免它。在跟踪 angle/README.md, “已知上游问题”。
  • 每个使用oxgl的线程都会留下大约72字节。 角分配 在线程的第一个EGL调用时的每个线程状态,并且故意不释放 因此,创建上下文的工作线程在创建上下文时泄漏了这些字节 退出。这是每个线程,而不是每个上下文。应用程序 很多短期的工人应该重用工人。在跟踪 angle/README.md“已知的上游问题”。

使用

import { createContext } from '@oxgl-js/oxgl';

const gl = createContext({ width: 64, height: 32 });
gl.clearColor(0, 1, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

const pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4);
gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
console.log(pixels.subarray(0, 4)); // Uint8Array(4) [ 0, 255, 0, 255 ]

gl.destroy();

createContext({ width, height, backend, webgl2, attributes, canvas }) 返回 一个 WebGLRenderingContext,或者 WebGL2RenderingContext 当 webgl2 是 true。不需要窗口系统、显示服务器或画布。 width 和 height 必须是0到2147483647之间的整数(0等于1);大一号 实现的限制提供了一个较小的绘图缓冲区与相同的方面 比率,检查一下 drawingBufferWidth 和 drawingBufferHeight.

attributes 以 WebGLContextAttributes 浏览器的 getContext 需要(alpha, depth, stencil, antialias, premultipliedAlpha, preserveDrawingBuffer, powerPreference, failIfMajorPerformanceCaveat), 使用相同的默认值; getContextAttributes() 报告分配了什么。 在浏览器中, antialias 默认为 true,它给出了一个4个样本缓冲 加上一个解析缓冲区,大约是单采样RGBA8内存的9倍 缓冲区;通过 antialias: false 当你不需要的时候。无头缓冲器是 从来没有出现过,所以它的内容一直存在 preserveDrawingBuffer 是多少。 failIfMajorPerformanceCaveat: true 拒绝软件后端:with 'auto' 它表现为 'gpu',与 'software' 它把 OXGL_CONTEXT_CREATION_FAILED.

画布和调整大小

gl.canvas 是 canvas 选项的对象,或者 HeadlessCanvas (一个 EventTarget 与 width 和 height)。设置 gl.canvas.width 或者 height 调整绘图缓冲区的大小,就像HTML一样 画布。 gl.resize(width, height) (不是WebGL的一部分)做同样的任何 上下文,也在更新 HeadlessCanvas. 调整大小将清除缓冲区和 保持所有其他状态,包括视窗。

接受画布和上下文的库,比如three.js,可以同时使用两者:

import * as THREE from 'three';
import { createContext } from '@oxgl-js/oxgl';

const gl = createContext({ width: 256, height: 256, webgl2: true });
const renderer = new THREE.WebGLRenderer({ canvas: gl.canvas, context: gl });
renderer.setSize(256, 256, false); // false: a HeadlessCanvas has no style

npm run threejs 渲染three.js自己的WebGL示例(release r186) 并将每一帧与版本保存的参考截图进行比较 有关它(见 CONTRIBUTING.md). 在带有软件后端的Linux arm64上,为 它运行的354个示例(three.js自己的测试也跳过了377个示例):

  • 228在three.js的阈值内匹配它们的引用(0.1%的像素);
  • 67个像素的差异高达5%:63个像素在线,多边形和文本边缘,其中 SwiftShader栅格化不同于制作参考的GPU, 在画布上绘制的HTML,运行程序不渲染;
  • 59 .不匹配。其中51个达到极限的测试跑者而不是 oxgl:它拒绝的远程资产,用CSS、SVG或2D画布绘制的页面; 视图放置由CSS流布局,HTML内容围绕画布,模块 工人,或没有 AudioContext. 8个不同的已知原因:SwiftShader (3; 包括在“已知问题”下几近被剪断的三角形),随机噪声 (3), SwiftShader中更多的压缩纹理格式,和一个挂钟 计时器。没有一个是无法解释的。

后端

backend呈现与
'auto' (默认)平台GPU后端(macOS上的Metal, Linux上的Vulkan, Windows上的D3D11),或者SwiftShader(如果失败)
'gpu'仅支持GPU后端;抛出 OXGL_GPU_UNAVAILABLE 如果失败了
'software'SwiftShader (CPU),无需GPU或GPU驱动即可工作

CPU驱动程序(SwiftShader, llvmpipe, lavapipe, WARP)永远不会算作GPU。如果 GPU后端初始化失败,它不会重试,直到进程 将重新启动。创建一个GPU上下文失败,例如GPU耗尽 记忆,只影响那一次呼唤。

这个 OXGL_BACKEND 环境变量(auto, gpu,或者 software) 覆盖了 backend 选择。它从调用线程中读取 process.env 在每一个 createContext 调用,这样worker就可以设置自己的。一个 空值将被忽略。

扩展

getSupportedExtensions() 列表中列出了angular可以启用的WebGL扩展 上下文的后端,和 getExtension(name) 启用一个并返回它的对象 (每次调用都是同一个对象)。在软件后端,包括 ANGLE_instanced_arrays, OES_vertex_array_object, WEBGL_draw_buffers, OES_texture_float, OES_texture_half_float, EXT_color_buffer_float, EXT_color_buffer_half_float, EXT_texture_filter_anisotropic, WEBGL_depth_texture, WEBGL_multi_draw, S3TC, ETC, ASTC, BPTC和RGTC compressed-texture扩展, WEBGL_lose_context 还有调试扩展。 WEBGL_color_buffer_float 没有提供(SwiftShader不能渲染到 RGBA/FLOAT 纹理),也不是定时器查询扩展。

环境损失

丢失的背景 WEBGL_lose_context.loseContext() 或者在后端 火灾 webglcontextlost 在以后的任务中;调用 preventDefault() 它允许恢复,之后 webglcontextrestored 火灾和上下文以新的状态再次呈现。之前创建的对象 丢失之后无效,就像在浏览器中一样。

发布环境

destroy() (不是WebGL的一部分)释放上下文的本地资源 并将其置于lost状态:之后的调用什么都不做, getError() 返回 CONTEXT_LOST_WEBGL 偶尔地 NO_ERROR,以及绘图缓冲器 大小读作 0. 一个上下文变得无法访问,没有 destroy() 是 垃圾回收后释放。

错误

无效选项引发 TypeError 或者 RangeError. 其他的失败 Error 与一个 code:

code导致
OXGL_GPU_UNAVAILABLEbackend: 'gpu' (选项或 OXGL_BACKEND)无法创建上下文
OXGL_INVALID_BACKENDOXGL_BACKEND 有别的值吗 auto, gpu, software,或空的
OXGL_CONTEXT_CREATION_FAILED没有后端可以创建上下文,例如WebGL 2在没有OpenGL ES 3.0的后端,或者 failIfMajorPerformanceCaveat 通过软件后端
OXGL_NATIVE_MISSING本机插件或其ANGLE库丢失或加载失败

WebGL错误通过 getError(),如在浏览器中。

表演

npm run bench 测量每个呼叫开销,抽取,转移和两个3 .js 场景。在Linux arm64 Docker(16核,软件后端,每个案例2秒):

情况下结果
enable (一个状态调用:WebIDL转换和本机调用)11.6 M呼叫/s
uniform4f7.3 M呼叫/s
drawArrays一个小三角形53k /s
bufferSubData, 1 MiB32 GB / s
texSubImage2D, 512×512 rgba826 GB / s
readPixels, 256×256 rgba83.3 GB / s
Three.js, 1000个点亮的网格52帧/秒
三个。js,一个128×64-segment点亮球1230帧/秒

draw的开销与直接调用ANGLE相同(51.9 k draw /s) cargo test -p oxgl-sys --test angle --release raw_draw_rate -- --ignored): 时间是SwiftShader的,GPU后端绘制得更快。oxgl补充道 每次呼叫约100纳秒。

在GPU后端(macOS arm64, ANGLE Metal, Apple M4 Max)上也是如此 基准测试给出了715 k的小帧/秒和830帧/秒的1000网格 three.js场景。

先决条件

从源构建:

  • rustup. 固定工具链 rust-toolchain.toml 是 第一次使用时自动安装。
  • Node.js 22.22.2或更新版本(engines 在 package.json)。
  • libclang,它在构建时生成EGL/GLES绑定 macOS的命令行工具, libclang-dev (或任何LLVM安装), Windows上的LLVM。集 LIBCLANG_PATH 如果没有找到。
  • 为 npm run conformance: ffmpeg(带ffprobe),用于解码 套房的视频。
  • 对于许可证检查:在版本CI引脚处拒绝货和约货 (CARGO_DENY_VERSION 和 CARGO_ABOUT_VERSION 在 .github/workflows/ci.yml),安装有 cargo install --locked cargo-deny@<version> 和 cargo install --locked cargo-about@<version> --features cli.

命令

npm install        # install JS tooling
npm run build      # build the native addon (release) and the TypeScript package into dist/
npm run lint       # rustfmt, clippy (pedantic, warnings as errors), ESLint, tsc, license check
npm test           # node:test suites in test/ (run after build)
npm run conformance   # Khronos WebGL conformance suites, judged against conformance/expectations.txt
npm run threejs    # three.js's WebGL examples, judged against threejs/expectations.txt
npm run notices    # regenerate THIRD_PARTY_NOTICES after changing Rust dependencies
cargo test --workspace --exclude oxgl-node   # Rust tests (oxgl-node is tested from Node)

规范和变更建议存在于 openspec/;运行OpenSpec npx openspec. CONTRIBUTING.md 描述CI检查以及如何在本地运行每个检查。

许可证

BSD-3-Clause;看到 LICENSE. 捆绑第三方组件及其许可证 都列在 THIRD_PARTY_NOTICES.

版本与发布记录

@oxgl-js/oxgl 共发布 2 个版本,首次发布于 2026/11/02;过去 12 个月发布了 2 个版本。

版本发布日期距今
0.1.1latest2026/11/021 天前
0.0.0-stage2026/11/021 天前

关于 @oxgl-js/oxgl 的常见问题

@oxgl-js/oxgl 是什么?

符合标准的无头WebGL 1和WebGL 2

如何安装 @oxgl-js/oxgl?

在项目目录运行 npm install @oxgl-js/oxgl,或使用 pnpm add / yarn add / bun add。

@oxgl-js/oxgl 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@oxgl-js/oxgl 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@oxgl-js/oxgl 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.22.2。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@oxgl-js/oxgl 可以商用吗?

@oxgl-js/oxgl 使用 BSD-3-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。另外不得用原作者名义为衍生产品背书。以上为概括,不构成法律意见,请以许可原文为准。

@oxgl-js/oxgl 还在维护吗?

最新版本 0.1.1 发布于 2026/11/02(1 天前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/11/02。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。