Skip to content

aidizhi/aibo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#爱播爱播最新地址 视频 官方 https://455555.xyz

WebGL 2.0 Bundle Size License MPL-2.0 npm version Brutalism

TinyGL · 轻量级 WebGL 3D 渲染引擎

一个面向现代浏览器的极简 WebGL 2.0 场景图渲染引擎。
无依赖 · 零抽象泄漏 · 原始着色器控制权


概述

TinyGL 是一款轻量级的 WebGL 3D 渲染引擎,围绕**场景图(Scene Graph)**模式构建,专为需要在浏览器中实现高质量 3D 渲染的开发者设计。不同于 Three.js 的全功能框架路线,TinyGL 追求的是:

  • 极小体积 — 核心库 gzip 后约 12 kB,适合嵌入式与移动端场景
  • 无隐藏开销 — 所有渲染路径可追溯,不引入不可见的 draw call
  • 原生着色器 — GLSL 代码完全由开发者掌控,引擎仅提供 uniform 绑定与 varying 管道
  • WASM 友好 — 数学库核心路径预留 WASM 编译接口(目前以 JS TypedArray 实现)

TinyGL 的设计哲学受 Brutalism(粗野主义) 风格影响:不修饰、不包装、不做过度抽象。API 暴露底层 WebGL 调用语义,让开发者对每一步 GPU 指令都有清晰认知。

适用场景

场景 说明
3D 数据可视化 GIS、点云、科学计算渲染
产品配置器 轻量嵌入式 3D 展示
创意编码 Shader art、生成艺术、互动装置
教育/原型 理解 WebGL 管线与 3D 数学的教学工具

架构总览

┌─────────────────────────────────────────────────────────┐
│                      Application Layer                    │
│              (用户代码 / 游戏逻辑 / 交互控制)                │
├─────────────────────────────────────────────────────────┤
│                     Scene Graph API                       │
│   Scene ──┬── Group ──┬── Mesh (Geometry + Material)      │
│           │           └── Light (Point / Directional)     │
│           └── Camera (Perspective / Orthographic)        │
├─────────────────────────────────────────────────────────┤
│                    Render Pipeline                         │
│  Culling ──▶ Sorting ──▶ Uniform Upload ──▶ Draw Calls   │
├──────────┬──────────────────────┬────────────────────────┤
│ Math Lib │    Shader System     │    WebGL 2.0 Backend    │
│ mat4     │  Vertex Shader (GLSL)│  VAO / VBO / FBO       │
│ vec3     │  Fragment Shader     │  Texture Units          │
│ vec4     │  Uniform Binder      │  Blend / Depth / Stencil│
│ quat     │  Varying Pipeline    │  MSAA / MRT (WIP)       │
├──────────┴──────────────────────┴────────────────────────┤
│                   Platform / Build                        │
│       esbuild (bundle) · npm (publish) · Tape (test)      │
└─────────────────────────────────────────────────────────┘

快速开始

安装

npm install tinygl-engine

最简场景

以下代码展示了一个完整的 TinyGL 场景搭建流程:创建渲染器、定义几何体、编写着色器、挂载到场景图并启动渲染循环。

import { TinyGL, Scene, PerspectiveCamera, Mesh, BoxGeometry, mat4 } from 'tinygl-engine';

// ── 1. 初始化渲染器 ──
const canvas = document.getElementById('viewport');
const renderer = new TinyGL(canvas, {
  antialias: true,
  alpha: false,
  powerPreference: 'high-performance'
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x0a0a0a, 1.0);

// ── 2. 创建场景与相机 ──
const scene = new Scene();
const camera = new PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 2, 5);
camera.lookAt(0, 0, 0);

// ── 3. 定义着色器材质 ──
const material = new ShaderMaterial({
  vertexShader: `
    attribute vec3 aPosition;
    attribute vec3 aNormal;

    uniform mat4 uModelMatrix;
    uniform mat4 uViewMatrix;
    uniform mat4 uProjectionMatrix;
    uniform mat4 uNormalMatrix;

    varying vec3 vNormal;
    varying vec3 vWorldPos;

    void main() {
      vec4 worldPos = uModelMatrix * vec4(aPosition, 1.0);
      vWorldPos = worldPos.xyz;
      vNormal   = mat3(uNormalMatrix) * aNormal;
      gl_Position = uProjectionMatrix * uViewMatrix * worldPos;
    }
  `,
  fragmentShader: `
    precision mediump float;

    varying vec3 vNormal;
    varying vec3 vWorldPos;

    uniform vec3 uLightDir;
    uniform vec3 uBaseColor;

    void main() {
      vec3 N = normalize(vNormal);
      vec3 L = normalize(uLightDir);
      float diff = max(dot(N, L), 0.0);
      float ambient = 0.15;
      vec3 color = uBaseColor * (ambient + diff * 0.85);
      gl_FragColor = vec4(color, 1.0);
    }
  `,
  uniforms: {
    uLightDir:  { value: [1.0, 1.5, 2.0] },
    uBaseColor: { value: [0.85, 0.22, 0.12] }
  }
});

// ── 4. 创建网格并挂载到场景 ──
const geometry = new BoxGeometry(2, 2, 2);
const mesh = new Mesh(geometry, material);

// 使用 mat4 进行变换
mat4.translate(mesh.localMatrix, mesh.localMatrix, [0, 1, 0]);
mat4.rotateY(mesh.localMatrix, mesh.localMatrix, performance.now() * 0.001);

scene.add(mesh);

// ── 5. 渲染循环 ──
function animate(time) {
  requestAnimationFrame(animate);

  // 动态旋转
  mat4.rotateY(mesh.localMatrix, mat4.create(), time * 0.001);
  mat4.rotateX(mesh.localMatrix, mesh.localMatrix, time * 0.0005);

  renderer.render(scene, camera);
}
animate(0);

// ── 6. 响应窗口尺寸变化 ──
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

着色器系统

TinyGL 的着色器系统采用 显式声明 模式,不自动注入任何 uniform 或 attribute。开发者需要自行在 GLSL 中声明所有变量,引擎负责将 JavaScript 侧的 uniform 值绑定到 GPU。

着色器编写规范

┌──────────────────────────────────────────────────┐
│              Vertex Shader (顶点着色器)             │
│                                                    │
│  输入:  attribute — 顶点位置、法线、UV、自定义数据    │
│         uniform  — 模型矩阵、视图矩阵、投影矩阵       │
│  输出:  varying  — 传递给片元着色器的插值数据         │
│  终点:  gl_Position — 裁剪空间坐标                   │
├──────────────────────────────────────────────────┤
│           Fragment Shader (片元着色器)               │
│                                                    │
│  输入:  varying  — 来自顶点着色器的插值数据           │
│         uniform  — 光源参数、材质参数、时间等         │
│  输出:  gl_FragColor — 最终像素颜色                  │
└──────────────────────────────────────────────────┘

Uniform 类型映射

GLSL 类型 JavaScript 输入格式 示例
uniform float Number 0.75
uniform vec2 [Number, Number] [1.0, 0.5]
uniform vec3 [Number, Number, Number] [1.0, 0.0, 0.0]
uniform vec4 [Number, Number, Number, Number] [1, 1, 1, 1]
uniform mat4 Float32Array(16) mat4.create()
uniform sampler2D WebGLTexture textureUnit

自定义 Attribute

// 通过 geometry.setAttribute 添加自定义顶点属性
geometry.setAttribute('aCustomAttr', {
  data: new Float32Array([...]),
  size: 3,       // 每顶点分量数
  type: gl.FLOAT,
  normalized: false
});

数学库

TinyGL 内置一套面向列主序(column-major)的线性数学工具集,兼容 WebGL uniformMatrix4fv 的内存布局要求。所有函数均为纯函数,不修改输入参数(除非明确命名 out 参数)。

核心 API

mat4 — 4x4 矩阵运算

import { mat4 } from 'tinygl-engine/math';

const out = mat4.create();            // 单位矩阵
const translation = mat4.create();
const rotation = mat4.create();

mat4.translate(translation, mat4.create(), [0, 2.5, -3]);
mat4.rotateY(rotation, mat4.create(), Math.PI / 4);

// 组合变换:先旋转再平移
mat4.multiply(out, translation, rotation);

// 透视投影矩阵
const proj = mat4.create();
mat4.perspective(proj, Math.PI / 3, aspect, 0.1, 1000);

// 观察矩阵
const view = mat4.create();
const eye = [0, 5, 10], center = [0, 0, 0], up = [0, 1, 0];
mat4.lookAt(view, eye, center, up);

vec3 — 三维向量运算

import { vec3 } from 'tinygl-engine/math';

const a = [1, 0, 0];
const b = [0, 1, 0];

const cross = vec3.cross([], a, b);           // 叉积
const dot   = vec3.dot(a, b);                 // 点积
const len   = vec3.length(a);                 // 模长
const norm  = vec3.normalize([], a);           // 归一化
const lerp  = vec3.lerp([], a, b, 0.5);        // 线性插值

quat — 四元数(实验性)

import { quat } from 'tinygl-engine/math';

const q = quat.create();
quat.fromEuler(q, Math.PI / 6, 0, Math.PI / 3);  // 欧拉角转四元数
quat.normalize(q, q);

// 四元数转旋转矩阵
const rotMat = mat4.create();
mat4.fromQuat(rotMat, q);

完整数学 API 速查

模块 方法 说明
mat4 .create() 创建 4x4 单位矩阵
mat4 .multiply(out, a, b) 矩阵乘法
mat4 .translate(out, a, v) 平移变换
mat4 .rotateX/Y/Z(out, a, rad) 绕轴旋转
mat4 .scale(out, a, v) 缩放变换
mat4 .perspective(out, fov, asp, near, far) 透视投影
mat4 .ortho(out, l, r, b, t, n, f) 正交投影
mat4 .lookAt(out, eye, center, up) 观察矩阵
mat4 .invert(out, a) 矩阵求逆
mat4 .transpose(out, a) 矩阵转置
mat4 .fromQuat(out, q) 四元数转矩阵
vec3 .create() 零向量
vec3 .cross(out, a, b) 叉积
vec3 .dot(a, b) 点积
vec3 .normalize(out, a) 归一化
vec3 .lerp(out, a, b, t) 线性插值
vec3 .transformMat4(out, a, m) 矩阵变换
quat .create() 单位四元数
quat .fromEuler(out, x, y, z) 欧拉角转换
quat .multiply(out, a, b) 四元数乘法
quat .slerp(out, a, b, t) 球面插值

场景图 API

TinyGL 的场景图采用树形结构,每个节点继承自 Node3D 基类,支持层级变换与全局矩阵自动更新。

核心类

继承自 说明
Node3D 场景图基础节点,提供 localMatrix / worldMatrix
Scene Node3D 场景根节点,管理渲染队列
Group Node3D 逻辑分组容器,不影响渲染
Mesh Node3D 可渲染网格,绑定 Geometry + Material
Camera Node3D 抽象相机基类
PerspectiveCamera Camera 透视投影相机
OrthographicCamera Camera 正交投影相机
Geometry 顶点数据容器(VBO 属性声明)
ShaderMaterial 自定义 GLSL 着色器材质
PointLight Node3D 点光源(衰减参数可配)
DirectionalLight Node3D 平行光(方向 + 颜色)

节点方法

const group = new Group();
const child = new Mesh(geometry, material);

group.add(child);          // 添加子节点
group.remove(child);       // 移除子节点
group.traverse((node) => { // 深度遍历
  console.log(node.type);
});

// 世界矩阵访问(自动计算父级变换累积)
console.log(child.worldMatrix);

渲染管线

TinyGL 的每帧渲染遵循以下管线流程:

┌────────────┐    ┌────────────┐    ┌──────────────────┐    ┌────────────┐
│  Update     │───▶│  Frustum   │───▶│  Uniform Upload   │───▶│  Draw      │
│  Scene Graph│    │  Culling   │    │  (per material)   │    │  Calls     │
└────────────┘    └────────────┘    └──────────────────┘    └────────────┘
      │                 │                    │                     │
  遍历场景图        基于相机          将 mat4/vec3/uniform     调用
  更新 worldMatrix  视锥体剔除         上传至 GPU uniform       gl.drawElements
  & dirty flags    不在视野内的        缓冲区                  或 gl.drawArrays
                    节点跳过渲染

管线阶段说明

  1. Scene Graph Update — 自顶向下遍历场景图,计算每个节点的 worldMatrix = parent.worldMatrix * localMatrix,标记 dirty 脏标志
  2. Frustum Culling — 将每个 Mesh 的包围球(Bounding Sphere)变换到世界空间后,与相机视锥体的 6 个平面进行相交测试
  3. Uniform Upload — 按材质分组(material batching),同一材质的 Mesh 共享 uniform 绑定状态,减少 GPU 状态切换
  4. Draw Calls — 通过 VAO 绑定顶点属性,执行索引化或非索引化绘制

构建与打包

TinyGL 使用 esbuild 作为构建工具,追求极致的打包速度与极小的产物体积。

项目结构

aibo/
├── src/
│   ├── core/            # 渲染器核心 (TinyGL, WebGL context)
│   ├── scene/           # 场景图 (Scene, Node3D, Mesh, Camera)
│   ├── geometry/        # 几何体 (BoxGeometry, PlaneGeometry, SphereGeometry)
│   ├── material/        # 材质系统 (ShaderMaterial, UniformBinder)
│   ├── math/            # 数学库 (mat4, vec3, quat)
│   ├── shader/          # 着色器编译与链接
│   └── utils/           # 工具函数
├── test/                # Tape 单元测试
├── esbuild.config.js    # 构建配置
├── package.json
└── README.md

esbuild 配置要点

// esbuild.config.js
const esbuild = require('esbuild');

esbuild.build({
  entryPoints: ['src/index.js'],
  bundle: true,
  minify: true,
  format: 'esm',
  target: ['es2020', 'chrome80', 'firefox78'],
  external: [],               // 零外部依赖
  outdir: 'dist',
  sourcemap: true,
  treeShaking: true,           // 摇树优化
  define: {
    'process.env.NODE_ENV': '"production"'
  }
}).catch(() => process.exit(1));

构建命令

# 开发构建(带 sourcemap)
npm run build:dev

# 生产构建(minified)
npm run build

# 运行测试
npm test

测试

使用 Tape 作为测试框架,聚焦数学库精度与 WebGL 状态验证。

npm test

测试覆盖范围:

  • mat4 — 矩阵运算精度(乘法、求逆、分解)
  • vec3 — 向量运算(叉积、归一化边界条件)
  • quat — 四元数旋转等价性验证
  • Scene Graph — 父子变换累积、worldMatrix 一致性
  • Shader Compilation — GLSL 语法校验、uniform 绑定完整性

性能优化建议

Draw Call 管理

  • 实例化渲染(Instancing) — 对大量相同几何体使用 InstancedMesh,通过 instance attribute 偏移变换,将 N 个 draw call 合并为 1 个
  • 材质批处理 — 尽量让同一场景中使用相同 Material 的 Mesh 相邻排列,减少 GPU 状态切换
  • 纹理图集 — 将小贴图合并到一张大图集上,减少 texture unit 绑定次数

GPU 端优化

  • 避免 uniform 过度更新 — 仅在值变化时上传 uniform,利用 dirty flag 机制
  • 使用 OES_element_index_uint — 当索引超过 65535 时启用 32 位索引,避免拆分 draw call
  • FLOAT vs HALF_FLOAT — 非颜色属性(位置、法线)优先使用 Float32;颜色与 UV 可降为 HalfFloat 节省带宽
  • Mipmap — 所有非RenderTarget 纹理都应生成 mipmap,设置 gl.generateMipmap,避免远处采样时的 shimmer 伪影

CPU 端优化

  • Frustum Culling — 始终启用视锥体剔除,对静态场景可预计算 BVH 加速
  • 脏标志系统 — 仅在 localMatrix 或 parent 变化时才重新计算 worldMatrix
  • 离屏预编译 — 着色器在场景加载时异步编译链接,不阻塞首帧渲染

WASM 加速(规划中)

数学库核心热路径(mat4.multiplyvec3.transformMat4 等)预留 WASM 编译接口。未来将通过 Rust 编译为 WASM 模块,替代纯 JS TypedArray 实现,预期在批量矩阵运算场景中获得 3-5x 加速。

// 预期用法(WASM 模块就绪后)
import { initWASMMath } from 'tinygl-engine/wasm';
await initWASMMath();  // 加载 .wasm 模块
// 后续所有 mat4/vec3 调用自动走 WASM 路径

贡献指南

  1. Fork 本仓库
  2. 创建特性分支:git checkout -b feature/your-feature
  3. 编写/更新测试:npm test
  4. 确保所有测试通过
  5. 提交 PR,附上变更说明

代码风格:无分号、2 空格缩进、JSDoc 注释覆盖所有公开 API。


路线图

  • 核心 Scene Graph 与渲染管线
  • mat4 / vec3 / quat 数学库
  • BoxGeometry, PlaneGeometry, SphereGeometry
  • ShaderMaterial 自定义着色器
  • PerspectiveCamera / OrthographicCamera
  • Frustum Culling
  • InstancedMesh 实例化渲染
  • PBR 材质(基于物理的渲染)
  • Shadow Mapping 阴影
  • Post-processing 后处理管线(FBO + 全屏四边形)
  • glTF 2.0 模型加载
  • WASM 数学加速模块
  • WebGPU 后端(实验性)

许可证

本项目基于 Mozilla Public License 2.0 (MPL-2.0) 开源。

This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.

MPL-2.0 是一个弱 Copyleft 许可证,允许在闭源项目中引用本库文件,但对库本身的修改必须以相同许可证开源。


TinyGL — 让 WebGL 回归本质
aidizhi 维护 · 在线演示与实验场景:aiboaibo.com
爱播爱播 © 2024-2026

About

爱播爱播官方地址导航站,永不失联。智能测速选线、防失联备份、PWA一键安装到桌面、多平台镜像。

Topics

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors