尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
three.js PointLightShadow 深度解析:点光源全方位阴影的配置、六面深度贴图与渲染原理
three.js PointLightShadow 深度解析点光源全方位阴影的配置、六面深度贴图与渲染原理【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.jsPointLightShadow是 three.js 中PointLight点光源专用的阴影配置对象负责管理点光源在世界中全方向投射阴影所需的内部相机、深度贴图尺寸以及各类阴影采样参数。本文以 PointLightShadow 官方文档页 为骨架结合当前仓库中 PointLightShadow.js、LightShadow.js、PointLight.js 与 WebGLShadowMap.js 等源码实现完整讲解它的构造函数、属性体系、实际使用步骤与底层六面立方体贴图渲染原理。读完本文你将掌握点光源阴影的完整配置方法、性能瓶颈的成因以及在不同渲染器/阴影类型下的兼容性边界。概述与类继承关系官方文档原句Represents the shadow configuration of point lights.表示点光源的阴影配置。由于点光源从单个位置向四周 360° 发光它的阴影也与方向光DirectionalLightShadow、聚光灯SpotLightShadow截然不同必须记录以光源为球心、全方向各个方向上的深度信息才能正确判断场景中任意位置是否处于点光源的阴影中。继承链LightShadow → PointLightShadow从源码 PointLightShadow.js 可以看出它的继承关系import { LightShadow } from ./LightShadow.js; import { PerspectiveCamera } from ../cameras/PerspectiveCamera.js; class PointLightShadow extends LightShadow { constructor() { super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); this.isPointLightShadow true; } } export { PointLightShadow };也就是说LightShadowsrc/lights/LightShadow.js是所有光阴影的抽象基类承载了bias、normalBias、mapSize、radius、map、autoUpdate等通用阴影属性以及矩阵更新、序列化等通用方法PointLightShadow只做两件事向基类传入一台透视相机作为点光源观察世界的视角并标记自身的类型标志isPointLightShadow true。使用入口Light 上的 shadow 属性PointLightShadow不会由你手动实例化而是在创建PointLight时自动挂载到其.shadow属性上。见 PointLight.js/** * This property holds the lights shadow configuration. * type {PointLightShadow} */ this.shadow new PointLightShadow();因此日常使用时的访问链是pointLight.shadow例如pointLight.shadow.mapSize.set( 512, 512 )。构造函数new PointLightShadow()签名如下new PointLightShadow()构造函数不接受任何参数。在 PointLightShadow.js 中构造过程的核心是调用基类构造函数并传入super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );这行代码揭示了点光源阴影的本质渲染器为点光源创建了一台专用的透视相机参数含义如下参数值作用fov90度视锥体垂直张角。配合立方体贴图的每个面每面恰好覆盖 90°×90° 的立体角使用aspect1纵横比 1:1保证每个立方体面是正方形视口near0.5近裁剪面小于该距离的物体不会被记录进深度far500远裁剪面超出该距离的物体不产生阴影值得注意的是这个默认far 500只在不设置PointLight.distance时生效——当PointLight实例设置了最大照明距离distance后渲染器会用light.distance替换相机far详见下文渲染原理一节这与 PointLight 源码中distance 0表示无限远不衰减的语义是对应的。属性.isPointLightShadow : boolean只读这是PointLightShadow最重要的一个自有属性属性值说明isPointLightShadowtrue只读类型标志用于类型测试官方文档原句This flag can be used for type testing.该标志可用于类型测试。在 PointLightShadow.js 中被赋值为true。它并非摆设而是被底层渲染路径反复使用的关键分支依据例如ShadowNode.js 中用shadow.isPointLightShadow ! true判定是否走VSM方差阴影贴图采样分支WebGLShadowMap.js 中同样用它决定是否对阴影贴图执行 VSM 模糊 passShadowNode.js 中决定阴影深度纹理取普通深度纹理还是 VSM 水平模糊纹理。继承自 LightShadow 的核心属性PointLightShadow的属性主要继承自基类 LightShadow.js下列表格完整列出对实际效果影响最大的配置项默认值均以当前仓库源码为准属性类型默认值说明cameraPerspectiveCamera见上文光源观察世界的相机直接决定阴影记录范围intensitynumber1阴影强度取值区间[0, 1]biasnumber0深度偏移微调量级约0.0001可减轻阴影痤疮等伪影biasNode?Nodefloatnullbias的节点版本仅WebGPURenderer支持一旦定义bias失效normalBiasnumber0沿法线偏移采样位置适合大场景浅入射角下的阴影痤疮代价是阴影可能变形radiusnumber1大于 1 时模糊阴影边缘类型为BasicShadowMap时无效blurSamplesnumber8VSM 阴影贴图模糊的采样数mapSizeVector2(512, 512)阴影贴图宽高需为 2 的幂越大越清晰但越耗性能mapTypenumberUnsignedByteType阴影纹理的类型map?RenderTargetnull渲染期间内部生成的深度图立方体贴图渲染目标mapPass?RenderTargetnullVSM 路径下内部生成的分布图matrixMatrix4新的Matrix4模型到阴影相机空间矩阵渲染期间内部计算autoUpdatebooleantrue是否自动更新阴影needsUpdatebooleanfalse手动置true并调用一次render以强制更新与方向光/聚光灯阴影最大的不同是mapSize的语义是每个立方体面的尺寸六个面共享因此总纹理开销约等于 6 ×mapSize²详见性能小节。点光源阴影的 far 联动light.distance点光源阴影相机默认near 0.5、far 500但far会被PointLight的distance覆盖。逻辑在 WebGLShadowMap.jsconst far light.distance || camera.far; if ( far ! camera.far ) { camera.far far; camera.updateProjectionMatrix(); }即light.distance非 0 时用distance作为阴影远裁剪面保证只有灯光实际照射范围内的物体投影distance 0无限远时退回相机默认far 500。这意味着如果希望无限远点光源的阴影覆盖更大范围需要显式放大相机 far例如light.shadow.camera.far 2000; // 或在受支持时配合 renderer.shadowMap在场景中启用点光源阴影完整实战示例与 three.js 所有阴影一致点光源阴影需要三处配合才能生效渲染器开关、光源与投影物体属性、接收物体属性。以官方示例 examples/webgl_shadowmap.html 的用法为参照一个最小可运行示例为import * as THREE from ./build/three.module.js; const renderer new THREE.WebGLRenderer(); renderer.shadowMap.enabled true; // 1. 打开渲染器阴影总开关 renderer.shadowMap.type THREE.PCFShadowMap; // 2. 点光源推荐 PCFShadowMap见兼容性边界 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera( 60, innerWidth / innerHeight, 0.1, 100 ); // 地面接收阴影 const ground new THREE.Mesh( new THREE.PlaneGeometry( 20, 20 ), new THREE.MeshStandardMaterial( { color: 0x888888 } ) ); ground.rotation.x - Math.PI / 2; ground.receiveShadow true; scene.add( ground ); // 投影物体 const box new THREE.Mesh( new THREE.BoxGeometry( 1, 1, 1 ), new THREE.MeshStandardMaterial( { color: 0xff0000 } ) ); box.castShadow true; // 3. 物体投射阴影 scene.add( box ); // 点光源灯丝/灯泡式全向光源 const light new THREE.PointLight( 0xffffff, 1, 0, 2 ); // distance0 无限远decay2 light.position.set( 2, 3, 2 ); light.castShadow true; // 4. 光源投射阴影 light.shadow.mapSize.set( 512, 512 ); // 5. 每个立方体面 512×512 light.shadow.bias 0.0001; // 轻微偏移抑制痤疮 scene.add( light );注意第四步中light.castShadow true会在渲染帧内把该光源加入阴影渲染列表随后renderer.shadowMap其类型见 WebGLShadowMap.js 的this.enabled、this.autoUpdate、this.needsUpdate、this.type等开关才开始工作。渲染原理点光源为什么需要六面深度贴图这是点光源阴影区别于方向光、聚光灯的核心机制。官方文档的继承页只描述了LightShadow →而真正的六面渲染逻辑位于 WebGLShadowMap.js。1. 创建立方体深度渲染目标当检测到light.isPointLight时WebGLShadowMap.js渲染器创建的shadow.map不是普通 2D 渲染目标而是WebGLCubeRenderTarget并配套CubeDepthTextureshadow.map new WebGLCubeRenderTarget( _shadowMapSize.x ); shadow.map.depthTexture new CubeDepthTexture( _shadowMapSize.x, UnsignedIntType );一个立方体贴图共有 6 个面X/-X/Y/-Y/Z/-Z分别记录点光源朝六个方向观察到的深度。2. 逐个面摆好影子相机并渲染渲染循环对每个光源先求出渲染面数WebGLShadowMap.jsconst faceCount shadow.map.isWebGLCubeRenderTarget ? 6 : shadow.getViewportCount();点光源命中6 个面的分支。随后在 WebGLShadowMap.js 中每一帧对 6 个面分别执行把内部透视相机放到点光源的世界位置camera.position.copy( _lightPositionWorld )通过预置的_cubeDirections[ face ]六组单位方向与_cubeUps[ face ]六组上向量让相机lookAt朝向对应面camera.updateMatrixWorld()后用投影矩阵 × 视图逆矩阵生成该面的投影矩阵与视锥体用于物体剔除renderer.setRenderTarget( shadow.map, face )把渲染目标切到立方体贴图的第face个面并clear()WebGLShadowMap.js用MeshDistanceMaterial内部距离材质见下节把所有castShadow的网格渲染进该面深度。3. 帧率与性能的第一来源6 倍开销从上述流程可以推断每帧点光源会把场景中的投射物渲染 6 次6 个立方体面各一次。这就是文档注释里mapSize越高越好但越耗计算时间在点光源上被放大 6 倍的原因。若同时存在最大纹理尺寸限制渲染器会按shadowFrameExtents换算并钳制每个面的大小WebGLShadowMap.js不会无限放大。兼容性边界哪些阴影类型可用、哪些不可用围绕isPointLightShadow这个标志当前仓库对点光源阴影的类型支持存在两个明确的硬性边界均有源码警告为证VSMVSMShadowMap不支持点光源。WebGLShadowMap.js 会输出WebGLShadowMap: VSM shadow maps are not supported for PointLights. Use PCF or BasicShadowMap instead.并跳过该光源。因为 VSM 的两次水平/垂直模糊 pass 是针对单一 2D 深度图设计的与 6 面深度图结构冲突WebGLShadowMap.js 中也明确以shadow.isPointLightShadow ! true作为执行 VSM pass 的前提。PCFSoftShadowMap在当前仓库的 WebGL 路径中已回退为PCFShadowMapWebGLShadowMap.js 输出PCFSoftShadowMap has been removed. Using PCFShadowMap instead.。因此在 WebGL 渲染器下点光源阴影实际可用的是BasicShadowMap硬阴影、无滤波与PCFShadowMapPCF 软阴影radius 1的边缘模糊只在 PCF 下有效。而 TSL/WebGPU 节点路径中点光源阴影走的是 PointShadowNode.js 的pointShadow( light, shadow )节点同样会用到shadow.isPointLightShadow来判断是否采用立方体深度采样见 ShadowNode.js从而在底层代码中复用点光源不适用 VSM 两趟模糊的结论。用 MeshDistanceMaterial 自定义点光源的投影材质为了让点光源记录到光源的距离而非普通深度渲染器内部使用 MeshDistanceMaterial官方文档描述其为A material used internally for implementing shadow mapping with point lights。在 WebGLShadowMap.js 中可以看到选取规则const customMaterial ( light.isPointLight true ) ? object.customDistanceMaterial : object.customDepthMaterial; result ( light.isPointLight true ) ? _distanceMaterial : _depthMaterial;这带来一个实用的扩展点把某个网格的customDistanceMaterial替换成自定义的MeshDistanceMaterial实例即可控制该网格在点光源阴影中如何投影。例如保留透明贴图细节、让透明区域不投影正如 MeshDistanceMaterial.js 顶部注释所示把实例赋给Object3D.customDistanceMaterial以保证物体透明部分不投影。需要复制一份默认材质修改时可在该物体的onBeforeShadow/onAfterShadow钩子中按需调整钩子在 WebGLShadowMap.js 中被调用。序列化与资源释放PointLightShadow本身只新增了类型标志序列化工作由继承方法完成序列化PointLight的 toJSON 会将shadow.toJSON()写入data.object.shadow而 LightShadow.js 的toJSON()输出intensity、bias、normalBias、radius、blurSamples、mapSize以及内部相机剔除matrix——这正是编辑器导出与ObjectLoader.parse重建点光源阴影配置的依据拷贝LightShadow.copyLightShadow.js会克隆相机并逐项复制上述配置PointLight的 copy 则通过this.shadow source.shadow.clone()复制整个阴影对象释放PointLight.dispose 会调用this.shadow.dispose()进而释放 GPU 上的map/mapPass渲染目标LightShadow.js。在你的应用移除点光源时调用light.dispose()即可避免 GPU 资源泄漏。点光源阴影调优速查综合源码语义实践中针对PointLightShadow的常用调优手段可归结为控制 mapSize 与数量mapSize每增大 1 倍6 个面合计开销增大 4×6 倍多盏点光源叠加时要格外克制优先用light.shadow.mapSize.set( 256, 256 )起步根据场景范围设置相机范围对distance 0的无限远点光源按需调大light.shadow.camera.far对设置了distance的点光源则无需手动设置渲染器自动联动对抗伪影出现阴影痤疮时把light.shadow.bias从0.0001起逐步微调大场景浅入射角痤疮优先考虑normalBias选择正确的类型点光源在 WebGL 渲染器下只使用PCFShadowMap或BasicShadowMap需要柔和边缘时用radius 1PCF需要最高性能时用BasicShadowMap静态场景省电阴影静止时设置light.shadow.autoUpdate false需要更新时再置needsUpdate true并触发一次渲染两个开关均继承自 LightShadow.js透明物体的投影细节通过给网格赋customDistanceMaterial new THREE.MeshDistanceMaterial(...)定制其点光源投影行为。小结PointLightShadow虽然代码量极少仅 31 行的 PointLightShadow.js却在 three.js 阴影体系中扮演了承上启下的角色它通过向LightShadow基类注入PerspectiveCamera( 90, 1, 0.5, 500 )与只读标志isPointLightShadow把点光源 全方向光源的几何事实转化为每帧渲染 6 面立方体深度图的渲染管线并依托isPointLightShadow标志在各渲染路径中正确禁用不兼容的 VSM、启用立方体深度采样。理解了它的构造与这一套底层分支逻辑你就能精准地预测并控制点光源阴影的画质与性能开销。【免费下载链接】three.jsJavaScript 3D Library.项目地址: https://gitcode.com/GitHub_Trending/th/three.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

strix 渗透测试技能实战:npx Confusion(包运行器身份混淆)的检测、验证与上报

strix 渗透测试技能实战:npx Confusion(包运行器身份混淆)的检测、验证与上报

strix 渗透测试技能实战:npx Confusion(包运行器身份混淆)的检测、验证与上报 【免费下载链接】strix Open-source AI penetration testing tool to find and fix your app’s vulnerabilities. 项目地址: https://gitcode.com/GitHub_Tren…

📅 2026/9/8 23:09:24
Sling:轻量化工业物联网在线调试工具实战指南

Sling:轻量化工业物联网在线调试工具实战指南

Sling|超好用的轻量化工业物联网在线调试工具上个月去一个客户现场调灌装线的数据采集,对方机房里堆着三台边缘网关,里面跑着 Modbus TCP、OPC UA、还有一路走 MQTT 上云的采集脚本。我打开笔记本,先把 Modbus Poll、MQTTX、Wires…

📅 2026/9/8 23:09:24
LLaVA-OneVision 模型详解与实战指南:在 Transformers 中使用多模态视觉语言模型完成单图、多图与视频推理

LLaVA-OneVision 模型详解与实战指南:在 Transformers 中使用多模态视觉语言模型完成单图、多图与视频推理

LLaVA-OneVision 模型详解与实战指南:在 Transformers 中使用多模态视觉语言模型完成单图、多图与视频推理 【免费下载链接】transformers 🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vis…

📅 2026/9/8 23:09:24
MORE NEWS

更多资讯

📰

RK3588联调诊断实战:从启动链路到外设驱动的全流程排查指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

CMSIS-5源码级拆解:从内核抽象到工程落地的嵌入式开发指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

OpenCode:开源终端AI编程代理,多模型接入与工程化实战指南

最近终端 AI 编程代理(coding agent)圈子里,OpenCode 的热度蹿得很快。好几个群里都在讨论它,有人把它跟 Claude Code、Codex 放在一起对比,有人说它是“开源版 Claude Code”,还有人刚从 Codex 迁过来问我…

📰

专业视频编辑工作流全解析:从素材管理到交付验收

提到 professional editing,很多人首先想到的是一款高级剪辑软件或者复杂的特效插件。但真正把时间花在这一行之后你会发现,“专业编辑”和“会用剪辑软件”之间,差的根本不是某个炫技功能,而是从素材进场到成片交付的全流程掌控能…

📰

视觉语言模型全解析:从原理到部署微调实战

这几年搞AI的,不管你是做CV还是做NLP,几乎都会撞上同一个词:视觉语言模型。从CLIP到LLaVA,再到Qwen-VL、InternVL,每隔几个月就冒出来一个新名字,让人既兴奋又容易懵。这篇文章我想把这些模型放在一起做个系…

📰

AI视觉赋能排水管网智慧运维:从井盖检测到内涝预警

城市里的排水管网,可能是最不像“高科技”的基础设施。它深埋地下,常年被淤泥、油污、树根包裹着,平时没人注意,一下暴雨就原形毕露。作为长期接触智慧城市和AI落地项目的从业者,我在这类项目里最常见到的场景&#xf…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬