• 作者:老汪软件技巧
  • 发表时间:2024-09-24 17:02
  • 浏览量:

上面的案例,你会发现除了灯光的 diffuse 漫反射属性,还有 specular 高光属性。诶~这个属性是不是觉得很眼熟,因为材质上也有设置高光样式的 specularColor 和 specularTexture。

两者的区别也很好理解,灯光的 specular 决定了光源发出的高光颜色,影响所有被该光照亮的物体的高光颜色。

而材质上的 specularColor 决定了物体表面反射高光的颜色,仅影响应用了该材质的物体,它们共同作用来决定物体表面的高光效果

展示点光源是个“点”的案例

上面的案例可能不太看的出来点光源是一个点的效果,让我们来下面的这个:

将点光源的位置设置在世界坐标原点中心(0, 0, 0),然后分别在其上下左右都增加一个小球,代码如下:

var light = new BABYLON.PointLight("light", new BABYLON.Vector3(0, 0, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene);
sphere.position.y = 2;
var sphere2 = BABYLON.MeshBuilder.CreateSphere("sphere2", {}, scene);
sphere2.position.y = -2;
var sphere3 = BABYLON.MeshBuilder.CreateSphere("sphere3", {}, scene);
sphere3.position.x = 2;
var sphere4 = BABYLON.MeshBuilder.CreateSphere("sphere4", {}, scene);
sphere4.position.x = -2;

最终的效果如下:

展示点光源是个“点”的案例二

另一个案例,我们在中心创建一个小球,还有一个地板:

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 2, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// 灯光
var light = new BABYLON.PointLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0); // 设置漫反射为红色
light.specular = new BABYLON.Color3(0, 1, 0); // 设置高光为绿色
// 球
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene);
// 地板
var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 6}, scene);

效果如下:

靠近中间的地方会更亮,越边缘越暗,并且高光处也是我们设置的绿色。

平行光 DirectionalLight

DirectionalLight用于模拟来自无限远处的平行光线,类似于太阳光。它在场景中提供均匀的光照效果,适用于模拟大面积的光源。

它的主要属性除了公共的 diffuse、specular、intensity 以外,还有 diection 用于指定光源的方向,决定光线的照射方向。

DirectionalLight类的初始化参数为:

/**
 * 在场景中创建一个 DirectionalLight 对象,朝向传递的方向(Vector3)。
 * 平行光源从所有地方向给定方向发出光线。
 * 它可以投射阴影。
 * 文档: https://doc.babylonjs.com/features/featuresDeepDive/lights/lights_introduction
 * @param name 光源的名称
 * @param direction 光的方向
 * @param scene 光源所属的场景
 */
constructor(
  name: string,
  direction: Vector3,
  scene?: Scene
) {}

展示平行光是平行的案例

我们还是以上面点光源的第三个案例来做对比,创建一个小球和一个地板,看看会有什么不同的效果。

案例代码:

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 2, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// 创建平行光,且光线方向垂直朝下
var light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0, -1, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0); // 设置漫反射为红色
light.specular = new BABYLON.Color3(0, 1, 0); // 设置高光为绿色
// 球
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene);
// 地板
var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 6}, scene);

效果如下:

可以看到,相机视角垂直向下看的时候,除了高光处向四周有从黄到红的过程,其它视角在地板上的漫反射光照都是差不多的,都呈现出红色。

另外还有一点要注意,并不是说平行光就不会产生阴影效果,可以看到上面的小球也是会有阴影效果的。

聚光灯 SpotLight

SpotLight是 Babylon.js 中的一种聚光灯光源,模拟现实世界中的聚光灯效果。它从一个点发出光束,并在特定方向上逐渐扩散,形成一个锥形光束。SpotLight非常适合用于模拟舞台灯光、手电筒等场景。

对比与平行光,它多了一个 position 属性,用于定义光源的位置,同时它也有 direction 光束的方向属性。

再就是有一些关于“聚光”效果的属性,例如:

angle:光束的角度,以弧度表示。决定了光束的扩散范围。

light.angle = Math.PI / 3; // 60度

exponent: 光束的衰减系数。值越大,光束边缘越柔和。

light.exponent = 2;

SpotLight 类的初始化参数为:

/**
 * 在场景中创建一个 SpotLight 对象。聚光灯是一个简单的定向光锥。
 * 它可以投射阴影。
 * 文档: https://doc.babylonjs.com/features/featuresDeepDive/lights/lights_introduction
 * @param name 光源的名称
 * @param position 聚光灯在场景中的位置
 * @param direction 光在场景中的方向
 * @param angle 光锥的角度(以弧度表示)
 * @param exponent 光从发射点开始的衰减速度
 * @param scene 光源所属的场景
 */
constructor(
  name: string,
  position: Vector3,
  direction: Vector3,
  angle: number,
  exponent: number,
  scene?: Scene
) {}

聚光灯的基础案例

来看一个基础的案例:

定义了两个聚光灯,同时修改它们的 diffuse、specular 属性。

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 4, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// 光的方向是从一个位置直接向下一个单位向上,衰减缓慢
var light = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(-1, 1, -1), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 10, scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);
// 光的方向是从一个位置直接向下一个单位向上,衰减快
var light1 = new BABYLON.SpotLight("spotLight1", new BABYLON.Vector3(1, 1, 1), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 50, scene);
light1.diffuse = new BABYLON.Color3(0, 1, 0);
light1.specular = new BABYLON.Color3(0, 1, 0);
var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 4}, scene);			

效果如下:

官网案例地址:

光源课件__光源教学课件

半球光 HemisphericLight

HemisphericLight是 Babylon.js 中的一种半球光源,模拟从天空和地面反射的环境光。它从一个方向发出光线,并且有一个对立方向的环境光,适用于模拟自然光照效果。

这里提到的对立方向的环境光是什么意思呢?指的是它的特有属性 groundColor: 地面反射光的颜色,影响物体表面未被直接光照射部分的颜色。在等会的案例中就能看到它发挥的作用了。

HemisphericLight 类的初始化参数为:

    /**
     * 根据传入的方向(Vector3)在场景中创建一个HemisphericLight对象。
     * 该对象模拟环境光,因此传入的方向是光的反射方向,而不是入射方向。
     * HemisphericLight不能投射阴影。
     * 文档:https://doc.babylonjs.com/features/featuresDeepDive/lights/lights_introduction
     * @param name 灯光的名称
     * @param direction 灯光反射的方向
     * @param scene 灯光所属的场景
     */
    constructor(
      name: string,
      direction: Vector3,
      scene?: Scene
    ) {}

半球光的基础案例

定义一个球,同时设置一个半球光,设置它的漫反射与高光、还有地面反射光颜色:

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 4, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// 光的方向是向上和向左
var light = new BABYLON.HemisphericLight("hemiLight", new BABYLON.Vector3(-1, 1, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);
light.groundColor = new BABYLON.Color3(0, 1, 0);
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene);	

效果如下:

可以看到,这个球的上半部分是被反射成了红色,也就是 diffuse 的颜色,另外一部分,靠近地面的部分被反射成了绿色,这就是 groundColor 的作用,你可以理解为它是来自相反方向的光。

官方案例地址:

材质对光的限制

这部分直接看材质那一篇文章即可:

开光灯 setEnabled()

使用灯上的 setEnabled()方法即可:

light.setEnabled(false); // 关灯
light.setEnabled(true); // 开灯

调节灯光强度及到达距离强度 intensity

灯光强度的调节直接设置 intensity 即可:

intensity的默认值是 1。

light0.intensity = 0.5; // 调暗
light1.intensity = 2.4; // 调亮

到达的距离 range

对于点光源和聚光灯,还可以使用 range 属性设置光线到达的距离,例如:

默认值为 Number.MAX_VALUE,即 JS 中数字的最大值。

light.range = 100;

案例练习灯光案例一

实现以下效果:

提示:半球光、diffuse、specular、groundColor、ambientColor。

------------------------------- 分割线 -------------------------------

在线预览地址:

代码实现:

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 4, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
scene.ambientColor = new BABYLON.Color3(1, 1, 1);
//Light direction is up and left
var light = new BABYLON.HemisphericLight("hemiLight", new BABYLON.Vector3(-1, 1, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);
light.specular = new BABYLON.Color3(0, 1, 0);
light.groundColor = new BABYLON.Color3(0, 1, 0);
var redMat = new BABYLON.StandardMaterial("redMat", scene);
redMat.ambientColor = new BABYLON.Color3(1, 0, 0);
var greenMat = new BABYLON.StandardMaterial("redMat", scene);
greenMat.ambientColor = new BABYLON.Color3(0, 1, 0);
//No ambient color
var sphere0 = BABYLON.MeshBuilder.CreateSphere("sphere0", {}, scene);
sphere0.position.x = -1.5;	
//Red Ambient  
var sphere1 = BABYLON.MeshBuilder.CreateSphere("sphere1", {}, scene);
sphere1.material = redMat;
//Green Ambient
var sphere2 = BABYLON.MeshBuilder.CreateSphere("sphere2", {}, scene);
sphere2.material = greenMat;
sphere2.position.x = 1.5;	

灯光案例二

实现以下效果:

提示词:聚光灯、diffuse。

------------------------------- 分割线 -------------------------------

在线预览地址:

代码实现:

var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2,  Math.PI / 4, 5, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
//red light
var light = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(-Math.cos(Math.PI/6), 1 , -Math.sin(Math.PI/6)), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 1.5, scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);
//green light
var light1 = new BABYLON.SpotLight("spotLight1", new BABYLON.Vector3(0, 1, 1 - Math.sin(Math.PI / 6)), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 1.5, scene);
light1.diffuse = new BABYLON.Color3(0, 1, 0);
//blue light
var light2 = new BABYLON.SpotLight("spotLight2", new BABYLON.Vector3(Math.cos(Math.PI/6), 1, -Math.sin(Math.PI/6)), new BABYLON.Vector3(0, -1, 0), Math.PI / 2, 1.5, scene);
light2.diffuse = new BABYLON.Color3(0, 0, 1);
var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 4}, scene);

后语

知识无价,支持原创!这篇文章主要是给大家介绍了一下 Babylon.js 中如何使用灯光,当然这些都还只是基础的用法。掌握了这些之后,起码能让我们的场景“亮堂”起来了。

喜欢霖呆呆的小伙伴还希望可以关注霖呆呆的公众号 LinDaiDai

我会不定时的更新一些前端方面的知识内容以及自己的原创文章。

你的鼓励就是我持续创作的主要动力 。