经纬志
首页 / three.js / 使用示例

阴影

两排楼体在同一盏平行光下投出长短不一的影子,工具栏可切换类型、分辨率与偏置。

three.js 0.160.0 · 更新 2026-10-28
源码与运行效果
运行效果

说明

阴影来自一盏带 castShadow 的平行光。渲染器先用阴影相机 从光源位置渲染一遍深度,再在主渲染中比较深度决定哪些区域处于暗部。 阴影相机的正交范围必须包住所有投影物体,否则范围外的楼不会投影。

工具栏把容易出问题的几个参数都暴露出来:关闭阴影看纯光照效果, 换类型看边缘的软硬差别,换分辨率看锯齿,拖偏置看阴影粉刺与漏光。 显示阴影相机会画出光源视角的视景体,能直观看到覆盖范围。

设置数值说明
光源位置(−48, 60, 34)决定阴影的方向与长度
阴影相机±52,近 1、远 180覆盖 104 单位见方的地面
贴图分辨率1024 / 2048 / 4096按钮循环切换,切换前释放旧贴图
法线偏置0 – 0.2滑杆实时调整,默认 0.04
阴影类型PCFSoft / PCF / Basic边缘由柔到硬,Basic 有明显锯齿
楼体高 5 – 22.6高度由网格序号取模得到

开启阴影的三步

renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;

sun.castShadow = true;
sun.shadow.mapSize.set(2048, 2048);
sun.shadow.camera.left = -52;
sun.shadow.camera.right = 52;
sun.shadow.camera.top = 52;
sun.shadow.camera.bottom = -52;
sun.shadow.camera.near = 1;
sun.shadow.camera.far = 180;
sun.shadow.camera.updateProjectionMatrix();

// 物体要分别声明投射与接收
box.castShadow = true;
ground.receiveShadow = true;

castShadow 与 receiveShadow 必须同时配置: 只开光源、不开物体时看不到任何影子,这是最常见的遗漏。

分辨率与范围的取舍

阴影贴图的分辨率是固定的,覆盖范围越大,每个像素对应的地面尺寸越大, 影子边缘就越粗。1024 的贴图覆盖 104 单位见方时, 单个像素约对应 0.1 单位,细长杆件的影子会出现断点。

城市级场景的常见做法是让阴影相机跟随观察中心, 只覆盖视口附近几十米,而不是一次性包住整块区域。 显示阴影相机按钮就是用来检查这一步是否合理的。

偏置的作用

bias 沿深度方向偏移,normalBias 沿表面法线偏移。 两者都在缓解「阴影粉刺」——表面给自己投下的条状阴影。 法线偏置更不容易造成漏光,通常优先调它,从 0.02 起逐步加大。

偏置过大时,物体与影子之间会出现一条亮缝,影子像浮在半空。 这是偏移把实际接触点推开了。接触部位要求严格时, 应当提高贴图分辨率而不是继续加偏置。

切换参数的重建成本

改阴影类型会让所有材质重新编译着色器,示例里通过遍历场景置 needsUpdate 触发。改分辨率则要先 dispose() 旧的阴影贴图并置空,否则新尺寸不会生效。 两者都可能造成一次明显卡顿,不适合放进每帧循环。

影子不等于日照分析。这是实时渲染的近似阴影, 没有考虑大气散射、地形自遮挡与时间,也不是按真实太阳位置计算的。 需要精确日照时长的场景,应当用专门的太阳位置算法离线计算。