11-mini版WebGLGeometries

源码:github.com/buglas/thre...

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 注册表,对外只暴露 getupdate

依赖 作用
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(如 positionnormal),对每个 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」的主链路,去掉了线框、实例化、内存统计等扩展能力。

设计要点总结

  1. 职责分离:

    • WebGLGeometriesMini 管理 BufferGeometry;
    • VBO 在 WebGLAttributesMini
    • VAO 在 WebGLBindingStatesMini
  2. 按 ID 追踪:用 geometry.id 做注册表,同一 geometry 多次渲染不会重复注册。

  3. 惰性上传:update() 每帧都会调,但 WebGLAttributesMini 只在 attribute.version 变化时才真正 bufferSubData

  4. dispose 联动:geometry 销毁时,buffer 和 VAO 一起释放,保证 GPU 资源不泄漏。

相关推荐
李伟_Li慢慢1 小时前
18-mini版WebGLRenderList
前端·three.js
李伟_Li慢慢1 小时前
15-mini版WebGLMaterials
前端·three.js
ji_shuke1 小时前
Vue3 前端批量打印 PDF/图片踩坑记:跨域、合并打印、对话框闪退与按钮一直 loading
前端·pdf·状态模式·pdf打印
李伟_Li慢慢1 小时前
06-mini版WebGLState
前端·three.js
李伟_Li慢慢1 小时前
04-three.js的渲染流程概览
前端·three.js
李伟_Li慢慢1 小时前
07-WebGLProperties
前端·three.js
爱勇宝1 小时前
AI 都能写代码了,还要学计算机吗?
前端·后端·程序员
石像鬼₧魂石1 小时前
【Y2Ksoft】四季贵州水世界乐园管理系统 —— 玻璃拟态 · 单文件HTML · 开箱即用
前端·html
涛涛ing1 小时前
尤雨溪宣布:Vue 3.6 发布、Vue 4.0 启动、Vite 8 已落地
前端