首页
/ three.js 入门与源码结构解析:从旋转立方体到 WebGL/WebGPU 双渲染器体系

three.js 入门与源码结构解析:从旋转立方体到 WebGL/WebGPU 双渲染器体系

2026-09-03 15:22:24作者:谭伦延

本文以 three.js 仓库根目录的 README 为主体,讲清这个"易用、轻量、跨浏览器的通用 JavaScript 3D 库"的定位与最小可用示例,并结合 src/ 下的模块入口、package.json 的导出映射与测试脚本,帮助你在读完之后既能跑通官方示例,又能快速定位源码、理解 three.js 当前的模块组织方式与 WebGL/WebGPU 双线渲染架构。

项目定位:一个易用的通用 3D 库

README 对项目的定义非常凝练:

The aim of the project is to create an easy-to-use, lightweight, cross-browser, general-purpose 3D library.

即创建一个易用、轻量、跨浏览器的通用 3D 库。README 同时说明了当前的构建范围:官方构建(build)只包含 WebGL 与 WebGPU 两种渲染器,而 SVG 和 CSS3D 渲染器以 addons(附加模块)的形式存在,需要按需引入。

package.json 佐证了这一定位:包名 three"type": "module",关键词覆盖了 webglwebgl2webgpuwebxrwebaudiocanvassvghtml5 等能力面(见 package.json)。当前仓库中 npm 发布的版本号为 0.185.0,而 src/constants.jsREVISION 已推进到 '186dev',说明源码正处于 r186 的开发周期中——阅读本文内容时应以该仓库快照为准。

快速上手:README 官方最小示例

README 的 "Usage" 一节给出了官方最小可运行示例:创建一个场景(Scene)、相机(Camera)和一个立方体网格(Mesh),将其加入场景,再创建 WebGLRenderer 并把视口挂到 document.body 上,最后用动画循环驱动立方体旋转。完整代码如下:

import * as THREE from 'three';

const width = window.innerWidth, height = window.innerHeight;

// init

const camera = new THREE.PerspectiveCamera( 70, width / height, 0.01, 10 );
camera.position.z = 1;

const scene = new THREE.Scene();

const geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
const material = new THREE.MeshNormalMaterial();

const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

const renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( width, height );
renderer.setAnimationLoop( animate );
document.body.appendChild( renderer.domElement );

// animation

function animate( time ) {

	mesh.rotation.x = time / 2000;
	mesh.rotation.y = time / 1000;

	renderer.render( scene, camera );

}

逐行拆解这段代码中每个 API 的取值依据:

  • new THREE.PerspectiveCamera( 70, width / height, 0.01, 10 ):四个参数分别是垂直视场角 fov、宽高比 aspect、近裁剪面 near 和远裁剪面 far。从 src/cameras/PerspectiveCamera.js 的构造函数签名 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) 可以看到默认值:fov 默认 50 度、near 默认 0.1、far 默认 2000。示例中选择 near = 0.01far = 10 是为了匹配 0.2 大小的立方体与 camera.position.z = 1 的近距观察尺度;fov = 70 则让立方体在视口中占比更醒目。
  • new THREE.BoxGeometry( 0.2, 0.2, 0.2 ):边长 0.2 的立方体。由于相机位于 z=1,近裁剪面 0.01,立方体完整落在视锥体内。
  • new THREE.MeshNormalMaterial():法线着色材质,不依赖任何贴图与光源即可呈现立体感,是官方示例常用的"零依赖"选择。
  • new THREE.WebGLRenderer( { antialias: true } ):开启多采样抗锯齿。WebGLRenderer 只接受 WebGL 2 上下文——从 src/renderers/WebGLRenderer.js 的类注释可确认:"This renderer uses WebGL 2 to display scenes. WebGL 1 is not supported since r163." 构造函数源码中还会对传入的 WebGL1 上下文直接抛出 THREE.WebGLRenderer: WebGL 1 is not supported since r163. 错误(见 src/renderers/WebGLRenderer.js)。
  • renderer.setAnimationLoop( animate ):这是 three.js 官方推荐的动画驱动方式(内部基于浏览器的高帧率请求机制,并在 WebXR 场景下自动切换到 XR 会话帧回调),回调参数 time 为时间戳(毫秒),示例用 time / 2000time / 1000 让立方体沿 X、Y 轴以不同角速度旋转。

README 说明"如果一切顺利,你应该看到旋转的立方体"。除了最小示例,仓库在 examples/index.html 提供了数百个按主题分类的完整示例(webgl_*webgpu_*webxr_*physics_* 等),是官方文档之外最好的学习入口。

WebGLRenderer 构造参数的默认值

README 示例只演示了 antialias: true,而 src/renderers/WebGLRenderer.js 的构造函数解构了全部可配参数,默认值如下表(这些默认值是调优渲染器行为时的基准):

参数 默认值 说明
canvas 自动创建 复用的画布元素
context null 显式传入的 WebGL2 上下文(传 WebGL1 会抛错)
depth true 是否创建深度缓冲
stencil false 是否创建模板缓冲
alpha false 画布是否带 alpha 通道(透明背景)
antialias false 多采样抗锯齿
premultipliedAlpha true 预乘 alpha
preserveDrawingBuffer false 帧间保留绘制缓冲(截图场景需要,有性能代价)
powerPreference 'default' GPU 功耗偏好(如 high-performance
failIfMajorPerformanceCaveat false 软件渲染时是否直接失败
reversedDepthBuffer false 反转深度缓冲(适配特定渲染管线)
outputBufferType UnsignedByteType 输出缓冲数据类型(HDR 场景可改为浮点)

模块入口与包导出结构:读懂 import from 'three'

README 示例中的 import * as THREE from 'three' 到底导出了什么?结合仓库源码可以给出精确答案。

package.jsonexports 字段定义了包的入口映射:

"exports": {
  ".": {
    "import": "./build/three.module.js",
    "require": "./build/three.cjs"
  },
  "./examples/fonts/*": "./examples/fonts/*",
  "./examples/jsm/*": "./examples/jsm/*",
  "./addons": "./examples/jsm/Addons.js",
  "./addons/*": "./examples/jsm/*",
  "./src/*": "./src/*",
  "./webgpu": "./build/three.webgpu.js",
  "./tsl": "./build/three.tsl.js"
}

这对应了源码中四个聚合入口文件:

  1. src/Three.js —— 即 three 主包。它先 export * from './Three.Core.js' 导出核心 API,再补上 WebGL 渲染器相关类:WebGLRendererWebGLCubeRenderTargetShaderLibUniformsLibUniformsUtilsShaderChunkPMREMGeneratorWebGLUtils
  2. src/Three.Core.js —— 渲染器无关的核心层,约 188 行导出声明,覆盖 SceneObject3DMeshInstancedMeshBufferGeometry、各类几何体(export * from './geometries/Geometries.js')、全部材质(export * from './materials/Materials.js')、相机、灯光、纹理、加载器、动画系统(AnimationMixerAnimationClipAnimationAction 等)、数学工具(Matrix4QuaternionColorColorManagement)与辅助对象(AxesHelperGridHelper 等)。值得注意的是文件末尾的两处运行时逻辑:检测 __THREE_DEVTOOLS__ 全局对象并向其派发 register 事件(浏览器开发者扩展钩子),以及向 window.__THREE__ 写入 REVISION、在检测到重复实例时告警(见 src/Three.Core.js)。仓库中的 devtools/ 目录即为配套的浏览器开发者扩展。
  3. src/Three.WebGPU.js —— three/webgpu 入口,在核心层之上导出 WebGPURendererWebGPUBackendWebGLBackend(WebGL 后备后端)、通用 Renderer/RenderPipeline、节点材质(NodeMaterials)、Compute 相关类(StorageTextureStorageBufferAttribute 等)以及 TSL 命名空间。
  4. src/Three.TSL.js —— three/tsl 入口,约 675 行,将 TSL(Three Shading Language)的各个节点/工具函数以命名导出形式重新暴露(如 BRDF_GGXFnIfLoop、各类 Shadow Filter 与生命周期钩子 OnBeforeFrameUpdate 等),TSL 的完整规范文档见 docs/TSL.md

这套"核心 + 渲染器"的分层结构解释了 README 中"当前构建只含 WebGL 与 WebGPU 渲染器"的说法:Three.Core.js 不绑定任何渲染器,而 WebGL 与 WebGPU 各自叠加在其上,SVG/CSS3D 等渲染器则留在 examples/jsm 的 addons 中,可通过 three/addons/* 按需引入。

克隆仓库:用 --depth=1 避免 2GB 历史下载

README 的 "Cloning this repository" 一节特别提醒:带着完整历史克隆本仓库约需下载 2 GB。如果不需要全部提交历史,应使用 depth 参数大幅缩减体积:

git clone --depth=1 https://github.com/mrdoob/three.js.git

这条建议源于仓库积累了十余年的提交记录。浅克隆后若后续需要完整历史,可以再执行 git fetch --unshallow 补全(此为通用 git 用法,README 未展开)。

版本与变更日志

README 将变更日志(Change log)指向上游的 Releases 页面,仓库自身不维护 CHANGELOG 文件;版本演进以 npm 版本与源码 REVISION 为准。当前快照中:

另外 src/constants.js 中可以看到具体的 API 演进示例:PCFSoftShadowMap 自 r186 起被标记为 @deprecated,建议改用 PCFShadowMap。阅读旧示例代码遇到弃用警告时,可对照该文件中的注释判断迁移方向。

本地开发与测试:验证你的理解

理解源码最快的方式是跑起来并跑通测试。package.jsonscripts 字段提供了完整的开发工作流(均基于 Node.js,无额外框架依赖):

脚本 命令 用途
dev / start node utils/build/dev.js && node utils/server.js -p 8080 启动本地开发服务器(端口 8080),浏览器加载开发版构建,可边改源码边看效果
build rollup -c utils/build/rollup.config.js 用 Rollup 构建发布产物
lint npm run lint-core(即 eslint src 核心源码 ESLint 检查
test-unit node test/unit/puppeteer.unit.js --testPage=UnitTests.html --mode=headless 基于 Puppeteer 的无头单元测试(280+ 个测试文件位于 test/unit/
test-unit-addons node test/unit/puppeteer.unit.js --testPage=UnitTestsAddons.html --mode=headless addons 的单元测试
test-e2e node test/e2e/puppeteer.js 端到端测试(test/e2e/),--webgpu 可测 WebGPU 路径
test-treeshake rollup -c test/rollup.treeshake.config.js 树摇测试,验证按需导入的包体积
make-screenshot node test/e2e/puppeteer.js --make 重新生成示例截图(对应 examples/screenshots/ 下的 600+ 张 jpg)

其中 dev 脚本值得展开:它先执行 utils/build/dev.js 生成开发构建,再由 utils/server.js 起一个本地静态/服务代理,这是官方推荐的本地调试方式——配合浏览器 DevTools 扩展(devtools/)可以直接在页面上检查 three.js 场景对象的层级与属性。

小结

  • three.js 的目标是"易用、轻量、跨浏览器的通用 3D 库",官方构建内置 WebGL(仅 WebGL 2)WebGPU 两种渲染器,SVG/CSS3D 等作为 addons 提供。
  • 官方最小示例 = Scene + PerspectiveCamera + BoxGeometry + MeshNormalMaterial + WebGLRenderer.setAnimationLoop,所有构造参数默认值均可在源码中查证。
  • 包入口由 package.jsonexports 映射到四个聚合文件:src/Three.js(WebGL)、src/Three.Core.js(渲染器无关核心)、src/Three.WebGPU.js(WebGPU + Compute)、src/Three.TSL.js(着色语言 TSL),分层清晰且支持树摇。
  • 克隆仓库建议 --depth=1 以避免约 2 GB 的历史下载;本地开发用 npm run dev 起 8080 端口服务,质量保障由 Puppeteer 单测/e2e/树摇测试共同覆盖。
登录后查看全文
热门项目推荐
相关项目推荐