You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js实现无实体投射的动态墙面阴影?恐怖游戏开发问询

能否在Three.js中渲染无投射源的阴影?

当然可行!这种“无来源幽灵阴影”简直是恐怖游戏的标配效果,刚好有几种靠谱的实现方式,你提到的阴影地图方案完全能做到,下面给你详细拆解:

方法一:用隐形光源+隐形投射物实现阴影地图效果

这是最贴合你需求的方案——利用Three.js原生阴影系统,通过“隐藏光源和投射物”来制造阴影无来源的假象:

  • 创建隐形光源:选定向光或聚光灯(定向光更适合墙面大面积阴影),把它的visible设为false,这样玩家看不到光源,但它依然能投射阴影。记得开启castShadow = true,并调整阴影参数提升清晰度(比如mapSize设为2048×2048,视锥体范围适配你的墙面)。
  • 制作隐形投射物:创建一个模型(平面、自定义异形都可以),把它的材质visible设为false,但开启castShadow = true。这个物体就是阴影的“幕后黑手”,玩家看不到它,但它会被隐形光源照射,在墙面上投出阴影。
  • 墙面设置:确保墙面的receiveShadow设为true,这样它才能接收阴影。
  • 动态阴影动画:只要动画这个隐形投射物的位置、旋转甚至顶点形态,阴影就会跟着诡异晃动——比如给顶点加随机扰动,模拟幽灵阴影的不规则感。

给你一段极简的示例代码:

// 1. 创建隐形定向光
const ghostLight = new THREE.DirectionalLight(0xffffff, 1);
ghostLight.visible = false;
ghostLight.castShadow = true;
// 优化阴影质量
ghostLight.shadow.mapSize.set(2048, 2048);
ghostLight.shadow.camera.near = 0.5;
ghostLight.shadow.camera.far = 50;
ghostLight.shadow.camera.left = -10;
ghostLight.shadow.camera.right = 10;
ghostLight.position.set(5, 0, 3); // 调整位置让阴影落在墙面上
scene.add(ghostLight);

// 2. 创建隐形阴影投射物(带随机顶点扰动的平面)
const casterGeo = new THREE.PlaneGeometry(6, 6);
// 给顶点加随机偏移,让阴影看起来扭曲诡异
casterGeo.vertices.forEach(v => {
  v.z += Math.random() * 0.6 - 0.3;
});
casterGeo.verticesNeedUpdate = true;
const casterMat = new THREE.MeshBasicMaterial({ visible: false });
const shadowCaster = new THREE.Mesh(casterGeo, casterMat);
shadowCaster.castShadow = true;
shadowCaster.position.set(0, 0, 2); // 放在光源和墙面之间
scene.add(shadowCaster);

// 3. 墙面设置接收阴影
const wallGeo = new THREE.PlaneGeometry(20, 20);
const wallMat = new THREE.MeshStandardMaterial({ color: 0x2a2a2a });
const wall = new THREE.Mesh(wallGeo, wallMat);
wall.receiveShadow = true;
wall.position.set(0, 0, 0);
scene.add(wall);

// 4. 动画投射物,让阴影动态变化
function animate() {
  requestAnimationFrame(animate);
  // 缓慢旋转
  shadowCaster.rotation.z += 0.003;
  // 实时扰动顶点,模拟不规则晃动
  casterGeo.vertices.forEach(v => {
    v.z += (Math.random() * 0.012 - 0.006);
  });
  casterGeo.verticesNeedUpdate = true;
}
animate();

方法二:动态纹理投影(备选方案)

如果你的阴影形状特别复杂(比如想投射动态视频里的阴影),可以用动态纹理直接投影到墙面上:

  • 用Canvas实时生成阴影纹理,或者加载视频纹理
  • 创建一个平面作为“投影器”,使用透明材质,只保留纹理的阴影区域(半透明黑色),放在墙面前方
  • 或者用自定义着色器实现纹理投影,这种方式不需要依赖阴影地图,视觉效果更灵活

不过如果你更偏好Three.js原生阴影的真实感,第一种方法绝对是首选。

小提示

  • 阴影地图分辨率越高,阴影越清晰,建议设为2048或4096(根据性能调整)
  • 调整隐形光源的位置和角度,确保阴影精准落在目标墙面上
  • 如果场景有其他光源,可以通过shadow.bias参数避免阴影出现异常瑕疵

内容的提问来源于stack exchange,提问作者Devon Jarvis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:55:09