控制光源
分别按 1、2、3 键启用或禁用聚光灯、点光源和平行光。
本教程介绍如何在 PlayCanvas 中启用或禁用光源,并修改光源颜色和强度。还可以控制范围等其他光源属性,详细信息见 API 文档。
还应注意,各种光源属性的取值范围不同。例如红、绿、蓝分量在 0 到 1 之间,本例中的强度则在 0 到 10 之间变化。部分光源还有专属属性,例如聚光灯的锥角。
光照控制指令
if (app.keyboard.wasPressed(pc.KEY_1)) {
this.spot.light.enabled = !this.spot.light.enabled;
}
这行代码切换 spot 实体上光源组件的启用状态。
this.color1 = new pc.Color(1, 1, 1);
声明新的颜色数组,前三个值分别影响红、绿、蓝分量。
var s = Math.abs(Math.sin(1 + this.timer));
var r = 1-s/2;
var g = s-0.2;
var b = 0.55+s/2;
this.color1.set(r, g, b);
this.spot.light.color = this.color1;
this.spot.light.intensity = 10*s;
这些代码根据正弦波为 r、g、b 变量赋值,再通过 color1.set(x, y, z) 更新前面声明的颜色,最后将其赋给光源属性。强度则按正弦规律在最大值 10 和 0 之间变化。
备注
通过 entity.light.color.r 访问并修改红色分量不会生效。只有对光源 color 属性本身的修改才会被检测,因此必须赋入完整的 pc.Color,例如 entity.light.color = new pc.Color(1, 1, 1);。
基本配置
除新场景默认创建的平行光外,我们还添加了聚光灯和点光源,分别作为基础手电筒模型和球体模型的子级。控制脚本挂在根实体上。球体和手电筒又共同挂到场景中心的空实体下,便于旋转。完整编辑器场景和脚本见此项目中的 controllingLights 场景。
上述 PlayCanvas 应用的完整代码如下。
- ESM
- 传统脚本
import { Script, KEY_1, KEY_2, KEY_3, Color } from 'playcanvas';
export class LightHandler extends Script {
static scriptName = "lightHandler";
// initialize code called once per entity
initialize() {
const app = this.app;
this.spot = app.root.findByName("SpotLight");
this.point = app.root.findByName("PointLight");
this.directional = app.root.findByName("DirectionalLight");
this.pivot1 = app.root.findByName("Pivot1");
this.pivot2 = app.root.findByName("Pivot2");
this.timer = 0;
this.color1 = new Color(1, 1, 1);
this.color2 = new Color(1, 1, 1);
this.color3 = new Color(1, 1, 1);
};
// update code called every frame
update(dt) {
var app = this.app;
this.pivot();
if (app.keyboard.wasPressed(KEY_1)) {
this.spot.light.enabled = !this.spot.light.enabled;
}
if (app.keyboard.wasPressed(KEY_2)) {
this.point.light.enabled = !this.point.light.enabled;
}
if (app.keyboard.wasPressed(KEY_3)) {
this.directional.light.enabled = !this.directional.light.enabled;
}
// a counter that is used as input to sin the functions determining light properties for all lights.
this.timer += dt;
// these 3 code blocks assign color and intensity values that vary according to a sin function
// all sin inputs are in radians
var s = Math.abs(Math.sin(1 + this.timer));
var r = 1-s/2;
var g = s-0.2;
var b = 0.55+s/2;
this.color1.set(r, g, b);
this.spot.light.color = this.color1;
this.spot.light.intensity = 10*s;
s = Math.abs(Math.sin(2 + this.timer));
r = s/2;
g = 0.25+s/2;
b = 1.0-s;
this.color2.set(r, g, b);
this.point.light.color = this.color2;
this.point.light.intensity = 10*s;
s = Math.abs(Math.sin(3 + this.timer));
r = 0.25+s/2;
g = 0.75-s/2;
b = 0.25+s/2;
this.color3.set(r, g, b);
this.directional.light.color = this.color3;
this.directional.light.intensity = 3*(1-s);
}
// this function rotates all three lights about their parent entities (all at the centre of the scene) to easily create circular motion.
pivot() {
this.pivot1.rotate(0, 2, 0);
this.pivot2.rotate(0, -3, 0);
}
}
var LightHandler = pc.createScript('lightHandler');
// initialize code called once per entity
LightHandler.prototype.initialize = function() {
var app = this.app;
this.spot = app.root.findByName("SpotLight");
this.point = app.root.findByName("PointLight");
this.directional = app.root.findByName("DirectionalLight");
this.pivot1 = app.root.findByName("Pivot1");
this.pivot2 = app.root.findByName("Pivot2");
this.timer = 0;
this.color1 = new pc.Color(1, 1, 1);
this.color2 = new pc.Color(1, 1, 1);
this.color3 = new pc.Color(1, 1, 1);
};
// update code called every frame
LightHandler.prototype.update = function(dt) {
var app = this.app;
this.pivot();
if (app.keyboard.wasPressed(pc.KEY_1)) {
this.spot.light.enabled = !this.spot.light.enabled;
}
if (app.keyboard.wasPressed(pc.KEY_2)) {
this.point.light.enabled = !this.point.light.enabled;
}
if (app.keyboard.wasPressed(pc.KEY_3)) {
this.directional.light.enabled = !this.directional.light.enabled;
}
// a counter that is used as input to sin the functions determining light properties for all lights.
this.timer += dt;
// these 3 code blocks assign color and intensity values that vary according to a sin function
// all sin inputs are in radians
var s = Math.abs(Math.sin(1 + this.timer));
var r = 1-s/2;
var g = s-0.2;
var b = 0.55+s/2;
this.color1.set(r, g, b);
this.spot.light.color = this.color1;
this.spot.light.intensity = 10*s;
s = Math.abs(Math.sin(2 + this.timer));
r = s/2;
g = 0.25+s/2;
b = 1.0-s;
this.color2.set(r, g, b);
this.point.light.color = this.color2;
this.point.light.intensity = 10*s;
s = Math.abs(Math.sin(3 + this.timer));
r = 0.25+s/2;
g = 0.75-s/2;
b = 0.25+s/2;
this.color3.set(r, g, b);
this.directional.light.color = this.color3;
this.directional.light.intensity = 3*(1-s);
};
// this function rotates all three lights about their parent entities (all at the centre of the scene) to easily create circular motion.
LightHandler.prototype.pivot = function () {
this.pivot1.rotate(0, 2, 0);
this.pivot2.rotate(0, -3, 0);
};