Three.js 平行光源阴影

Three.js 平行光源阴影

参考资料:Threejs中文网

阴影效果:

点光源PointLight、聚光源SpotLight、平行光DirectionalLight等都可以产生阴影,就像实际生活中的影子。

环境光AmbientLight这种没有方向的光源,不会产生阴影。

本节课给大家讲解平行光DirectionalLight的阴影效果如何实现。

平行光DirectionalLight阴影步骤

平行光DirectionalLight阴影计算最少设置

  • 1..castShadow设置产生阴影的模型对象
  • 2..castShadow设置产生阴影的光源对象
  • 3..receiveShadow设置接收阴影效果的模型
  • 4..shadowMap.enabledWebGl渲染器允许阴影渲染
  • 5..shadow.camera设置光源阴影渲染范围

1. 模型阴影投射.castShadow

模型阴影投射属性.castShadow设置产生阴影的模型对象

javascript 复制代码
// 设置产生投影的网格模型
mesh.castShadow = true;

2. 光源阴影投射属性.castShadow

和产生阴影的模型一样,光源也有阴影投射属性.castShadow属性,光源默认不产生阴影,需要代码开启。

javascript 复制代码
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 平行光设置产生阴影的光源对象,开启光源阴影的计算功能
directionalLight.castShadow = true;

3.模型阴影接收属性.receiveShadow

模型阴影接收属性.castShadow设置接收阴影的模型对象

javascript 复制代码
// 设置接收阴影的投影面
planeMesh.receiveShadow = true;

4. .shadowMap.enabled允许渲染器渲染阴影

WebGL的渲染器的阴影贴图属性.shadowMap的属性值是一个对象,.shadowMap具有.enabled.type等属性。

设置.shadowMap.enabled=true允许WebGL渲染器渲染阴影。

javascript 复制代码
// 设置渲染器,允许光源阴影渲染
renderer.shadowMap.enabled = true; 

5. 平行光阴影相机属性.shadow.camera(阴影渲染范围)

平行光DirectionalLight.shadow属性是平行光阴影对象 DirectionalLightShadow,平行光阴影对象有一个相机属性shadow.camera

平行光阴影相机属性.shadow.camera的属性值是一个正投影相机对象OrthographicCamera

javascript 复制代码
// 查看平行光阴影相机属性
console.log('阴影相机属性',directionalLight.shadow.camera);

CameraHelper可视化.shadow.camera

THREE.CameraHelper可以用来可视化正投影相机、透视投影相机对象。

javascript 复制代码
// 可视化平行光阴影对应的正投影相机对象
const cameraHelper = new THREE.CameraHelper(directionalLight.shadow.camera);
scene.add(cameraHelper);

平行光阴影相机的位置.shadow.camera.position默认就是平行光的位置属性directionalLight.position

javascript 复制代码
console.log('shadow.camera位置',directionalLight.shadow.camera.position);

5. .shadow.camera设置阴影渲染范围

.shadow.camera属性值是正投影相机OrthographicCamera,所以.shadow.camera属性的用法可以参考前面讲解过的正投影相机OrthographicCamera

javascript 复制代码
OrthographicCamera( left, right, top, bottom, near, far )

.shadow.camera作用是约束三维场景阴影计算范围,上下左右前后六个属性定义了一个长方体空间,在这个长方体空间内容的模型进行阴影计算。

javascript 复制代码
// 设置三维场景计算阴影的范围
directionalLight.shadow.camera.left = -50;
directionalLight.shadow.camera.right = 50;
directionalLight.shadow.camera.top = 200;
directionalLight.shadow.camera.bottom = -100;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 600;

如果.shadow.camera的渲染范围设置不合理,可能会出现看不到阴影或者阴影不完整的现象。比如你把代码中.far.right等相机属性设置小一些,观察阴影变化。

测试:改变平行光位置.position观察阴影变化

你可以改变平行光位置.position属性,观察光源阴影相机属性.shadow.camera变化,观察平行光的阴影变化。

阴影范围.shadow.camera

前面平行光阴影计算 讲解过,通过光源的阴影相机属性.shadow.camera,来控制阴影的渲染范围,下面继续.shadow.camera的讲解。

平行光阴影相机属性.shadow.camera回顾

  • 平行光DirectionalLight.shadow属性是平行光阴影对象 DirectionalLightShadow
  • 平行光阴影对象DirectionalLightShadow有一个相机属性.camera
  • .shadow.camera属性值(正投影相机OrthographicCamera)

CameraHelper可视化.shadow.camera

为了方便观察阴影渲染的范围,需要把平行光对应的阴影相机.shadow.camera可视化显示。

javascript 复制代码
new THREE.CameraHelper(directionalLight.shadow.camera);

参数测试

下面先在上节课代码基础上给大家改参数体验下相机渲染范围参数对阴影的影响。

课件演示文件中,提供了批量创建了多个长方体,用于阴影范围设置测试。

设置相机.shadow.camera长方体范围

根据3D场景渲染范围,去设置.shadow.camera长方体尺寸参数,一般比你要渲染的范围稍微大一些即可,过小阴影不显示或显示不完整,过大很多可能阴影偏模糊,你可以比较下面两个参数的阴影渲染差异。

javascript 复制代码
directionalLight.shadow.camera.left = -50*10;
directionalLight.shadow.camera.right = 50*10;
javascript 复制代码
directionalLight.shadow.camera.left = -50*100;
directionalLight.shadow.camera.right = 50*100;

调节光源位置

光源位置影响平行光阴影相机.shadow.camera的位置,所以要根据渲染范围调整光源的位置。

你可以比较测试两个不同的光源位置,对应阴影渲染效果。

javascript 复制代码
directionalLight.position.set(100, 60, 50);
javascript 复制代码
directionalLight.position.set(100*2, 60*2, 50*2);

确定阴影计算范围

其实平行光阴影范围的设置,你可以类比以前正投影机位置、长方体可视化空间的设置。

  • 1.先大概确定下3D场景中需要阴影计算范围,不用精确,有一个数量级就行,比如几百、几千。
  • 2..shadow.camera.left.right.top.bottom.near.far属性定义的长方体空间
  • 3..shadow.camera的位置(光源位置影响.shadow.camera的位置)

需要阴影范围数量级:z方向尺寸1000左右,xy方向100左右。

javascript 复制代码
for (let i = -3; i < 4; i++) {
    const mesh2 = mesh.clone();
    // 设置产生投影的网格模型
    mesh2.castShadow = true;
    mesh2.position.z = 100 * i;
    group.add(mesh2);
}

根据尺寸数量级设置阴影渲染范围

比如光线是从斜上方照射下来,模型y方向高度100左右,这时候y可以设置为100左右,xz也可以根据渲染范围先给个大概尺寸。

javascript 复制代码
directionalLight.position.set(100, 100, 100);
// 平行光默认从.position指向坐标原点

光线方向,你可以改变xz坐标来调整

javascript 复制代码
directionalLight.position.set(-100, 100, -100);

渲染范围可以都先给个几百量级的值,不用精准,先设置,在微调。

javascript 复制代码
// 设置三维场景计算阴影的范围
directionalLight.shadow.camera.left = -100;
directionalLight.shadow.camera.right = 100;
directionalLight.shadow.camera.top = 100;
directionalLight.shadow.camera.bottom = -100;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 100;
相关推荐
明辉光焱8 分钟前
[Electron]总结:如何创建Electron+Element Plus的项目
前端·javascript·electron
牧码岛29 分钟前
Web前端之汉字排序、sort与localeCompare的介绍、编码顺序与字典顺序的区别
前端·javascript·web·web前端
开心工作室_kaic1 小时前
ssm111基于MVC的舞蹈网站的设计与实现+vue(论文+源码)_kaic
前端·vue.js·mvc
晨曦_子画1 小时前
用于在 .NET 中构建 Web API 的 FastEndpoints 入门
前端·.net
慧都小妮子1 小时前
Spire.PDF for .NET【页面设置】演示:在 PDF 文件中添加图像作为页面背景
前端·pdf·.net·spire.pdf
咔咔库奇1 小时前
ES6基础
前端·javascript·es6
Jiaberrr1 小时前
开启鸿蒙开发之旅:交互——点击事件
前端·华为·交互·harmonyos·鸿蒙
徐小夕2 小时前
Flowmix/Docx 多模态文档编辑器:V1.3.5版本,全面升级
前端·javascript·架构
Json____2 小时前
学法减分交管12123模拟练习小程序源码前端和后端和搭建教程
前端·后端·学习·小程序·uni-app·学法减分·驾考题库