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 );
}