1-WebGLGeometriesMini的代码
src\renderers\webgl\WebGLGeometriesMini.js
csharp
/**
* 几何体 GPU 数据管理:将 BufferGeometry 的各 attribute 同步到 WebGL buffer。
*/
function WebGLGeometriesMini( gl, attributes, bindingStates ) {
const geometries = {};
/** geometry 销毁时释放其关联的所有 VAO */
function onGeometryDispose( event ) {
const geometry = event.target;
attributes.remove( geometry.index );
for ( const name in geometry.attributes ) {
attributes.remove( geometry.attributes[ name ] );
}
geometry.removeEventListener( 'dispose', onGeometryDispose );
delete geometries[ geometry.id ];
bindingStates.releaseStatesOfGeometry( geometry );
}
/** 获取 geometry ,如果 geometry 已注册,则直接返回原 geometry 引用,否则注册 geometry 并返回 */
function get( geometry ) {
if ( geometries[ geometry.id ] === true ) return geometry;
geometry.addEventListener( 'dispose', onGeometryDispose );
geometries[ geometry.id ] = true;
return geometry;
}
/** 遍历 geometry 全部 attribute,按需创建或更新 GPU buffer
* geometry: BufferGeometry
*/
function update( geometry ) {
const geometryAttributes = geometry.attributes;
for ( const name in geometryAttributes ) {
attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
}
}
return {
get: get,
update: update,
};
}
export { WebGLGeometriesMini };
2-WebGLGeometriesMini 的功能定位
WebGLGeometries 是处于 几何体对象 和 底层 WebGL buffer 管理 之间的中间层。,它是面向BufferGeometry 的服务者。
WebGLGeometries 本身不绑定 VAO、也不发起 draw,只负责以下事务:
- 注册/追踪几何体。
- 把顶点属性同步到 WebGL buffer。
- 在 dispose 时释放资源。
- 为线框模式生成专用索引。
WebGLGeometries 的整体定位:
scss
Mesh / Line / Points
↓
WebGLObjects.update() ← 每帧调用
↓
WebGLGeometries.get() ← 注册 / 追踪 geometry
↓
WebGLGeometries.update() ← 遍历 attributes,触发 GPU 上传
↓
WebGLAttributes.update() ← 真正创建/更新 GPU buffer
↓
WebGLBindingStates ← VAO 绑定
WebGLBindingStatesMini 亦是如此,只是具体功能做了删减。
3-整体结构
php
function WebGLGeometriesMini( gl, attributes, bindingStates ) {
const geometries = {};
/** geometry 销毁时释放其关联的所有 VAO */
function onGeometryDispose( event ) {
// ...
}
function get( geometry ) {
// ...
}
function update( geometry ) {
// ...
}
return {
get: get,
update: update,
};
}
这是一个工厂函数(不是 class),闭包里维护一个 geometries 注册表,对外只暴露 get 和 update。
| 依赖 | 作用 |
|---|---|
gl |
WebGL2 上下文(当前 update 里主要用 gl.ARRAY_BUFFER) |
attributes |
WebGLAttributesMini,管理每个 BufferAttribute ↔ GPU buffer |
bindingStates |
WebGLBindingStatesMini,管理 VAO(顶点数组对象) |
4-核心函数
1. get(geometry) --- 注册几何体
kotlin
function get( geometry ) {
if ( geometries[ geometry.id ] === true ) return geometry;
geometry.addEventListener( 'dispose', onGeometryDispose );
geometries[ geometry.id ] = true;
return geometry;
}
作用:
- 首次见到某个
BufferGeometry:监听它的dispose事件,并在geometries里用geometry.id标记为已注册。 - 再次见到:直接返回,避免重复注册。
注意:geometries 存的是 true,不是 geometry 副本;真正对象仍是原来的 BufferGeometry。这个表只是「已追踪 ID 集合」。
完整版 WebGLGeometries.get(object, geometry) 还会做内存统计(info.memory.geometries++),Mini 版去掉了这部分。
2. update(geometry) --- 同步顶点属性到 GPU
查找、创建、缓存VAO。
ini
function update( geometry ) {
const geometryAttributes = geometry.attributes;
for ( const name in geometryAttributes ) {
attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
}
}
作用:遍历 geometry.attributes(如 position、normal),对每个 BufferAttribute 调用 WebGLAttributesMini.update():
- 第一次:
gl.createBuffer()+gl.bufferData()上传完整数据 - 之后:若
attribute.version变了,用gl.bufferSubData()增量更新
Mini 版只处理 geometry.attributes,不处理 geometry.index(索引 buffer)。
3. onGeometryDispose(event) --- 销毁清理
ini
function onGeometryDispose( event ) {
const geometry = event.target;
attributes.remove( geometry.index );
for ( const name in geometry.attributes ) {
attributes.remove( geometry.attributes[ name ] );
}
geometry.removeEventListener( 'dispose', onGeometryDispose );
delete geometries[ geometry.id ];
bindingStates.releaseStatesOfGeometry( geometry );
}
当用户调用 geometry.dispose() 时触发,做三件事:
1.删 GPU buffer:index + 所有 attributes 对应的 WebGL buffer。
attributes.remove() 方法在src\renderers\webgl\WebGLAttributesMini.js 中:
scss
function remove( attribute ) {
const data = buffers.get( attribute );
if ( data ) {
gl.deleteBuffer( data.buffer );
buffers.delete( attribute );
}
}
2.注销追踪:从 geometries 表移除,并移除 dispose 监听。
3.释放 VAO:bindingStates.releaseStatesOfGeometry() 删除该 geometry 关联的所有 VAO
bindingStates.releaseStatesOfGeometry() 方法在src\renderers\webgl\WebGLBindingStatesMini.js 中:
ini
function releaseStatesOfGeometry( geometry ) {
const geometryMap = bindingStates[ geometry.id ];
if ( geometryMap === undefined ) return;
for ( const programId in geometryMap ) {
const state = geometryMap[ programId ];
if ( state !== undefined ) {
if ( currentState === state ) {
currentState = null;
}
gl.deleteVertexArray( state.object );
}
}
delete bindingStates[ geometry.id ];
}
这是典型的 Three.js 资源生命周期模式:创建时注册监听,销毁时统一释放 GPU 资源,避免泄漏。
5-与完整版 WebGLGeometries.js 的对比
| 功能 | 完整版 | Mini 版 |
|---|---|---|
| 注册 / dispose 清理 | ✅ | ✅ |
| 更新 attributes | ✅ | ✅ |
内存统计 info.memory |
✅ | ❌ |
| Wireframe 索引属性 | ✅ | ❌ |
| InstancedBufferGeometry | ✅ | ❌ |
| Morph targets 等 | ✅ | ❌ |
Mini 版保留了「BufferGeometry → GPU buffer → VAO → draw」的主链路,去掉了线框、实例化、内存统计等扩展能力。
设计要点总结
-
职责分离:
WebGLGeometriesMini管理 BufferGeometry;- VBO 在
WebGLAttributesMini; - VAO 在
WebGLBindingStatesMini。
-
按 ID 追踪:用
geometry.id做注册表,同一 geometry 多次渲染不会重复注册。 -
惰性上传:
update()每帧都会调,但WebGLAttributesMini只在attribute.version变化时才真正bufferSubData。 -
dispose 联动:geometry 销毁时,buffer 和 VAO 一起释放,保证 GPU 资源不泄漏。