举荐:将 NSDT 场景编辑器退出你的 3D 工具链
其余系列工具:NSDT 简石数字孪生
常见光源类型
Threejs 虚构光源是对自然界光照的模仿,threejs 搭建虚构场景的时候,为了更好的渲染场景,往往须要设置不同的光源,设置不同的光照强度,就像摄影师给你拍照要设置各种辅助灯光一样。
环境光 AmbientLight
环境光是没有特定方向的光源,次要是平均整体扭转 Threejs 物体外表的明暗成果,这一点和具备方向的光源不同,比方点光源能够让物体外表不同区域明暗水平不同。
// 环境光: 环境光色彩 RGB 成分别离和物体材质色彩 RGB 成分别离相乘
var ambient = new THREE.AmbientLight(0x444444);
scene.add(ambient);// 环境光对象增加到 scene 场景中
你能够把光源色彩从 0x444444 更改为 0x888888, 能够看到 threejs 场景中的网格模型外表变的更亮。
点光源 PointLight
点光源就像生存中的白炽灯,光线沿着发光外围向外发散,同一立体的不同地位与点光源光线入射角是不同的,点光源照耀下,同一个立体不同区域是呈现出不同的明暗成果。
和环境光不同,环境光不须要设置光源地位,而点光源须要设置地位属性.position,光源地位不同,物体外表被照亮的面不同,远近不同因为衰减明暗水平不同。
你能够把案例源码中点光源地位从 (400, 200, 300) 地位扭转到(-400, -200, -300),你会发现网格模型被照亮的地位从后面变到了前面,这很失常,光源只能照亮面对着光源的面,背对着光源的无奈照射到,色彩会比拟暗。
// 点光源
var point = new THREE.PointLight(0xffffff);
// 设置点光源地位,扭转光源的地位
point.position.set(400, 200, 300);
scene.add(point);
平行光 DirectionalLight
平行光顾名思义光线平行,对于一个立体而言,立体不同区域接管到平行光的入射角一样。
点光源因为是向周围发散,所以设置好地位属性.position 就能够确定光线和物体外表的夹角,对于平行光而言, 次要是确定光线的方向, 光线方向设定好了,光线的与物体外表入射角就确定了,仅仅设置光线地位是不起作用的。
在三维空间中为了确定一条直线的方向只须要确定直线上两个点的坐标即可,所以 Threejs 平行光提供了地位.position 和指标.target 两个属性来一起确定平行光方向。指标.target 的属性值能够是 Threejs 场景中任何一个三维模型对象,比方一个网格模型 Mesh,这样 Threejs 计算平行光照耀方向的时候,会通过本身地位属性.position 和.target 示意的物体的地位属性.position 计算出来。
// 平行光
var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向:通过光源 position 属性和指标指向对象的 position 属性计算
directionalLight.position.set(80, 100, 50);
// 方向光指向对象网格模型 mesh2,能够不设置,默认的地位是 0,0,0
directionalLight.target = mesh2;
scene.add(directionalLight);
平行光如果不设置.position 和.target 属性,光线默认从上往下照耀,也就是能够认为 (0,1,0) 和(0,0,0)两个坐标确定的光线方向。
留神一点平行光光源的地位属性.position 并不示意平行光从这个地位向远处照耀,.position 属性只是用来确定平行光的照耀方向,平行光你能够了解为太阳光,从有限远处照耀过去。
聚光源 SpotLight
聚光源能够认为是一个沿着特定方会逐步发散的光源,照耀范畴在三维空间中形成一个圆锥体。通过属性.angle 能够设置聚光源发散角度,聚光源照耀方向设置和平行光光源一样是通过地位.position 和指标.target 两个属性来实现。
// 聚光光源
var spotLight = new THREE.SpotLight(0xffffff);
// 设置聚光光源地位
spotLight.position.set(200, 200, 200);
// 聚光灯光源指向网格模型 mesh2
spotLight.target = mesh2;
// 设置聚光光源发散角度
spotLight.angle = Math.PI / 6
scene.add(spotLight);// 光对象增加到 scene 场景中
光源辅助对象
Threejs 提供了一些光源辅助对象,就像 AxesHelper 可视化显示三维坐标轴一样显示光源对象, 通过这些辅助对象能够不便调试代码,查看地位、方向。
辅助对象 | 构造函数名 |
---|---|
聚光源辅助对象 | SpotLightHelper |
点光源辅助对象 | PointLightHelper |
平行光光源辅助对象 | DirectionalLightHelper |
光照计算算法
Three.js 渲染的时候光照计算还是比较复杂的,这里不进行深刻介绍,只给大家说下光源色彩和网格模型 Mesh 色彩相乘的常识,如果你有趣味能够学习计算机图形学或者 WebGL 教程。
Threejs 在渲染的时候网格模型材质的色彩值 mesh.material.color 和光源的色彩值 light.color 会进行相乘,简略说就是 RGB 三个重量别离相乘。
平行光漫反射简略数学模型:漫反射光的色彩 = 网格模型材质色彩值 x 光线色彩 x 光线入射角余弦值漫反射数学模型 RGB 重量示意:(R2,G2,B2) = (R1,G1,B1) x (R0,G0,B0) x
cosθR2 = R1 * R0 * cosθ
G2 = G1 * G0 * cosθ
B2 = B1 * B0 * cosθ
色彩相乘测试
你能够通过上面代码验证下面色彩相乘的算法,比方把网格模型的色彩设置为红色 0xffffff, 也就意味着能够反射任意光照色彩,而后把环境光和点光源只保留红色成分,绿色和蓝色成分都设置为 0。你能够看到网格模型会把渲染为红色。
// 网格模型材质设置为红色
var geometry = new THREE.BoxGeometry(100, 100, 100); //
var material = new THREE.MeshLambertMaterial({color: 0xffffff});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
// 环境光 环境光色彩 RGB 成分别离和物体材质色彩 RGB 成分别离相乘
var ambient = new THREE.AmbientLight(0x440000);
scene.add(ambient);// 环境光对象增加到 scene 场景中
// 点光源
var point = new THREE.PointLight(0xff0000);
// 设置点光源地位 光源对象和模型对象的 position 属性一样是 Vector3 对象
//PointLight 的基类是 Light Light 的基类是 Object3D 点光源对象继承 Object3D 对象的地位属性 position
point.position.set(400, 200, 300);
scene.add(point);
你还能够尝试把网格模型设置为纯蓝色 0x0000ff, 光源色彩只保留红色成分不变,你能够看到网格模型的渲染成果是彩色,因为这两个色彩相乘总有一个 RGB 重量为 0,相乘的后果是 0x00000, 也就是彩色。这也符合实际的物理法则,蓝色的物体不会反射红色的光线,熙然就是彩色成果。
如果你想模仿一个舞台的各种色彩灯光效果,能够用这种思路设置 RGB 各个重量值来实现特定色彩光源,不过个别渲染的时候 RGB 三个重量是雷同的,也就是示意红色光源,0xffffff 示意最高强度的红色光源,0x000000 相当于没有光照。
3D 建模学习工作室