Threejs源码系列- WebGLRenderer (3)projectObject函数

WebGLRender - projectObject函数

projectObject函数,作用是递归遍历场景中的 3D 对象,筛选出需要渲染的对象并将其添加到渲染列表(currentRenderList)中。

js 复制代码
function projectObject( object, camera, groupOrder, sortObjects ) {
 // ...
}

参数说明

  • object:当前处理的 3D 对象(可能是模型、灯光、组等)。
  • camera:当前渲染使用的相机,用于可见性判断和深度计算。
  • groupOrder:当前对象所属组的排序值,用于控制渲染顺序。
  • sortObjects:是否需要计算对象深度以用于排序(影响透明/不透明对象的渲染顺序)。

关键逻辑解析

可见性过滤
js 复制代码
// 对象自身不可见,直接跳过
if (object.visible === false) return; 
// 检查对象层级是否在相机可见层级内
const visible = object.layers.test(camera.layers);
Group类型
js 复制代码
   
    if (object.isGroup) {
        // 更新组排序值,子对象继承该排序
        groupOrder = object.renderOrder; 
    } 
LOD类型
js 复制代码
 if ( object.isLOD ) {
    // 根据相机距离更新显示的细节层级
    if (object.autoUpdate === true) object.update(camera); 
} 
Light类型
js 复制代码
if ( object.isLight ) {
    // 将光源加入渲染状态,用于后续光照计算
    currentRenderState.pushLight( object );
    // 若光源投射阴影,加入阴影列表
    if ( object.castShadow ) {
        currentRenderState.pushShadow( object );
    }
}
Sprite类型
js 复制代码
 if ( object.isSprite ) {
    // 未开启视锥体剔除,或精灵在相机视锥体内
    if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
        if ( sortObjects ) {
            // 计算精灵在屏幕空间的 z 坐标(用于排序)
            _vector4.setFromMatrixPosition( object.matrixWorld ).applyMatrix4( _projScreenMatrix );
        }
        // 更新精灵的几何数据
        const geometry = objects.update( object );
        const material = object.material;
        if (material.visible) {
            // 将精灵加入渲染列表
            currentRenderList.push(object, geometry, material, groupOrder, _vector4.z,null);
        }
    }
}
Mesh类型、Line类型、Points类型
js 复制代码
// 未开启视锥体剔除,或对象在相机视锥体内
if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
    // 更新几何体数据(如缓冲、绑定等)
    const geometry = objects.update(object); 
    const material = object.material;

    if ( sortObjects ) {
        // 计算对象在屏幕空间的 z 坐标(用于排序)
        if ( object.boundingSphere !== undefined ) {
            // 优先使用对象自身的包围球
            if ( object.boundingSphere === null ) object.computeBoundingSphere();
            _vector4.copy( object.boundingSphere.center );
        } else {
            // 否则使用几何体的包围球
            if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
            _vector4.copy( geometry.boundingSphere.center );
        }

        // 转换到屏幕空间
        _vector4.applyMatrix4( object.matrixWorld ).applyMatrix4( _projScreenMatrix );
    }

    // 处理多材质情况(几何体分组对应不同材质)     
    if ( Array.isArray( material ) ) {

        const groups = geometry.groups;

        for ( let i = 0, l = groups.length; i < l; i ++ ) {

            const group = groups[ i ];
            const groupMaterial = material[ group.materialIndex ];

            if ( groupMaterial && groupMaterial.visible ) {

                currentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group );

            }

        }

    } else if ( material.visible ) {
        // 单一材质,直接加入渲染列表
        currentRenderList.push( object, geometry, material, groupOrder, _vector4.z, null );
    }
}
处理子元素
js 复制代码
const children = object.children;

for ( let i = 0, l = children.length; i < l; i ++ ) {

    projectObject( children[ i ], camera, groupOrder, sortObjects );

}
相关推荐
阿里巴啦3 小时前
用React+Three.js 做 3D Web版搭建三维交互场景:模型的可视化摆放与轻量交互
前端·react·three.js·模型可视化·web三维·web三维交互场景
阿里巴啦2 天前
React + Three.js + R3F + Vite 实战:可交互的三维粒子化展厅
react.js·three.js·粒子化·drei·postprocessing·三维粒子化
叫我詹躲躲2 天前
基于 Three.js 的 3D 地图可视化:核心原理与实现步骤
前端·three.js
map_3d_vis3 天前
JSAPIThree 加载单体三维模型学习笔记:SimpleModel 简易加载方式
学习笔记·three.js·gltf·glb·初学者·三维模型·mapvthree·jsapithree·simplemodel
Addisonx6 天前
深度复盘 III: 核心逻辑篇:构建 WebGL 数字孪生的“业务中枢”与“安全防线”
webgl·three.js
爱看书的小沐6 天前
【小沐学WebGIS】基于Three.JS绘制二三维地图地球晨昏效果(WebGL / vue / react )
javascript·vue.js·gis·webgl·three.js·opengl·晨昏线
Addisonx9 天前
深度复盘: WebGL 数字孪生前端架构:如何打造高颜值、高性能的 Web 3D 可视化系统
three.js
BUG创建者11 天前
thee.js完成线上展厅demo
开发语言·前端·javascript·css·html·css3·three.js
一千柯橘21 天前
从摄影新手到三维光影师:Three.js 核心要素的故事
前端·three.js
big男孩22 天前
OrbitControls 的完整原理
three.js