Babylon.js-8 光照

参考链接:https://doc.babylonjs.com/babylon101/lights

光照影响3d场景中mesh的渲染效果。在BabylonJS中,光照的默认允许数量是4,但是可以增加。

光源主要分为以下几个部分:

点光源

我们使用以下代码创建点光源

1
const light = new BABYLON.PointLight(name,position,scene)

其中position是点光源的位置。下面使用以下代码演示点光源,使光源处于一个球的正上方,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  var createScenePointLight = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);


/**************************************************************/

var light = new BABYLON.PointLight("light", new BABYLON.Vector3(0, 10, 0), scene);

// Create a sphere which diameter is 8

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material

return scene;
}
const canvasPointLight = document.getElementById('renderCanvas-8-pointlight')
const enginePointLight = new BABYLON.Engine(canvasPointLight,true)
const scenePointLight = createScenePointLight(enginePointLight,canvasPointLight)
enginePointLight.runRenderLoop(function(){scenePointLight.render()})

效果如下:

直射光源

我们使用以下代码创建直射光源

1
const light = new BABYLON.DirectionalLight(name,direction,scene)

其中direction是直射光源的方向。下面使用以下代码演示直射光源,使光源方向从上往下(方向:(0,-1,0))打到一个球上,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  var createSceneDirectionalLight = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);


/**************************************************************/

var light = new BABYLON.DirectionalLight("light", new BABYLON.Vector3(0, -1, 0), scene);

// Create a sphere which diameter is 8

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material

return scene;
}
const canvasDirectionalLight = document.getElementById('renderCanvas-8-directionallight')
const engineDirectionalLight = new BABYLON.Engine(canvasDirectionalLight,true)
const sceneDirectionalLight = createSceneDirectionalLight(engineDirectionalLight,canvasDirectionalLight)
engineDirectionalLight.runRenderLoop(function(){sceneDirectionalLight.render()})

效果如下:

聚光灯光源

我们使用以下代码创建聚光灯光源

1
const light = new BABYLON.SpotLight(name,position,direction,angle,exponent,scene)

其中position指聚光灯光源的位置,direction是聚光灯光源的方向,angle指聚光灯的辐射角度[0,π],指数exponent指聚光灯随距离光强的衰减程度。下面使用以下代码演示聚光灯光源,使光源在球的正上方,方向从上往下(方向:(0,-1,0)),角度为π/2,指数为50打到一个球上,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  var createSceneSpotLight = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);

/**************************************************************/
var light = new BABYLON.SpotLight("light", new BABYLON.Vector3 (0,10,0),new BABYLON.Vector3(0, -1 , 0),Math.PI/2,50,scene);
// Create a sphere which diameter is 8

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material

return scene;
}
const canvasSpotLight = document.getElementById('renderCanvas-8-spotlight')
const engineSpotLight = new BABYLON.Engine(canvasSpotLight,true)
const sceneSpotLight = createSceneSpotLight(engineSpotLight,canvasSpotLight)
engineSpotLight.runRenderLoop(function(){sceneSpotLight.render()})

效果如下:

半球光源

我们使用以下代码创建半球光源

1
const light = new BABYLON.PointLight(name,direction,scene)

其中direction指半球光源的光反射方向,由于半球光源模拟环境光,所以direction指的是光反射方向,而不是入射方向。下面使用以下代码演示半球光源,使光源方向从上往下打到一个球上,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  var createSceneHemisphericLight = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);

/**************************************************************/
var light = new BABYLON.HemisphericLight("light",new BABYLON.Vector3(0, 1, 0),scene);
// Create a sphere which diameter is 8

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material

return scene;
}

const canvasHemisphericLight = document.getElementById('renderCanvas-8-hemisphericlight')
const engineHemisphericLight = new BABYLON.Engine(canvasHemisphericLight,true)
const sceneHemisphericLight = createSceneHemisphericLight(engineHemisphericLight,canvasHemisphericLight)
engineHemisphericLight.runRenderLoop(function(){sceneHemisphericLight.render()})

效果如下:

上面已经提过,一个材质默认能够渲染4种光源,但我们可以修改材质的maxSimultaneousLights属性来使其支持更多的光源。

1
2
var material = new BABYLON.StandardMaterial("mat", scene);
material.maxSimultaneousLights = 6;

我们看一个例子,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
var createSceneMaxSimulaneousLights = function (engine,canvas) {
var scene = new BABYLON.Scene(engine);

// Setup camera
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, BABYLON.Vector3.Zero(), scene);
camera.setPosition(new BABYLON.Vector3(-10, 10, 0));
camera.attachControl(canvas, false);

// Lights
var light0 = new BABYLON.PointLight("Omni0", new BABYLON.Vector3(0, 10, 0), scene);
var light1 = new BABYLON.PointLight("Omni1", new BABYLON.Vector3(0, -10, 0), scene);
var light2 = new BABYLON.PointLight("Omni2", new BABYLON.Vector3(10, 0, 0), scene);
var light3 = new BABYLON.DirectionalLight("Dir0", new BABYLON.Vector3(1, -1, 0), scene);
var light4 = new BABYLON.PointLight("Omni3", new BABYLON.Vector3(10, 0, 0), scene);
var light5 = new BABYLON.PointLight("Omni4", new BABYLON.Vector3(10, 0, 0), scene);

var material = new BABYLON.StandardMaterial("kosh", scene);
var sphere = BABYLON.Mesh.CreateSphere("Sphere", 16, 3, scene);

// Creating light sphere
var lightSphere0 = BABYLON.Mesh.CreateSphere("Sphere0", 16, 0.5, scene);
var lightSphere1 = BABYLON.Mesh.CreateSphere("Sphere1", 16, 0.5, scene);
var lightSphere2 = BABYLON.Mesh.CreateSphere("Sphere2", 16, 0.5, scene);
var lightSphere4 = BABYLON.Mesh.CreateSphere("Sphere4", 16, 0.5, scene);
var lightSphere5 = BABYLON.Mesh.CreateSphere("Sphere5", 16, 0.5, scene);

lightSphere0.material = new BABYLON.StandardMaterial("red", scene);
lightSphere0.material.diffuseColor = new BABYLON.Color3(0, 0, 0);
lightSphere0.material.specularColor = new BABYLON.Color3(0, 0, 0);
lightSphere0.material.emissiveColor = new BABYLON.Color3(1, 0, 0);

lightSphere1.material = new BABYLON.StandardMaterial("green", scene);
lightSphere1.material.diffuseColor = new BABYLON.Color3(0, 0, 0);
lightSphere1.material.specularColor = new BABYLON.Color3(0, 0, 0);
lightSphere1.material.emissiveColor = new BABYLON.Color3(0, 1, 0);

lightSphere2.material = new BABYLON.StandardMaterial("blue", scene);
lightSphere2.material.diffuseColor = new BABYLON.Color3(0, 0, 0);
lightSphere2.material.specularColor = new BABYLON.Color3(0, 0, 0);
lightSphere2.material.emissiveColor = new BABYLON.Color3(0, 0, 1);

lightSphere4.material = new BABYLON.StandardMaterial("blue", scene);
lightSphere4.material.diffuseColor = new BABYLON.Color3(0, 0, 0);
lightSphere4.material.specularColor = new BABYLON.Color3(0, 0, 0);
lightSphere4.material.emissiveColor = new BABYLON.Color3(1, 1, 0);

lightSphere5.material = new BABYLON.StandardMaterial("blue", scene);
lightSphere5.material.diffuseColor = new BABYLON.Color3(0, 0, 0);
lightSphere5.material.specularColor = new BABYLON.Color3(0, 0, 0);
lightSphere5.material.emissiveColor = new BABYLON.Color3(0, 1, 1);

// Sphere material
material.diffuseColor = new BABYLON.Color3(1, 1, 1);
sphere.material = material;
material.maxSimultaneousLights = 16;

// Lights colors
light0.diffuse = new BABYLON.Color3(1, 0, 0);
light0.specular = new BABYLON.Color3(1, 0, 0);

light1.diffuse = new BABYLON.Color3(0, 1, 0);
light1.specular = new BABYLON.Color3(0, 1, 0);

light2.diffuse = new BABYLON.Color3(0, 0, 1);
light2.specular = new BABYLON.Color3(0, 0, 1);

light3.diffuse = new BABYLON.Color3(1, 1, 1);
light3.specular = new BABYLON.Color3(1, 1, 1);

light4.diffuse = new BABYLON.Color3(1, 1, 0);
light4.specular = new BABYLON.Color3(1, 1, 0);

light5.diffuse = new BABYLON.Color3(0, 1, 1);
light5.specular = new BABYLON.Color3(0, 1, 1);

// Animations
var alpha = 0;
scene.beforeRender = function () {
light0.position = new BABYLON.Vector3(10 * Math.sin(alpha), 0, 10 * Math.cos(alpha));
light1.position = new BABYLON.Vector3(10 * Math.sin(alpha), 0, -10 * Math.cos(alpha));
light2.position = new BABYLON.Vector3(10 * Math.cos(alpha), 0, 10 * Math.sin(alpha));
light4.position = new BABYLON.Vector3(10 * Math.cos(alpha), 10 * Math.sin(alpha), 0);
light5.position = new BABYLON.Vector3(10 * Math.sin(alpha), -10 * Math.cos(alpha), 0);

lightSphere0.position = light0.position;
lightSphere1.position = light1.position;
lightSphere2.position = light2.position;
lightSphere4.position = light4.position;
lightSphere5.position = light5.position;

alpha += 0.01;
};

return scene;
}
const canvasMaxSimulaneousLights = document.getElementById('renderCanvas-8-maxsimulaneouslights')
const engineMaxSimulaneousLights = new BABYLON.Engine(canvasMaxSimulaneousLights,true)
const sceneMaxSimulaneousLights = createSceneMaxSimulaneousLights(engineMaxSimulaneousLights,canvasMaxSimulaneousLights)
engineMaxSimulaneousLights.runRenderLoop(function(){sceneMaxSimulaneousLights.render()})

效果如下:

小心! 这样做会使BabylonJS产生更大的着色器导致一些低端设备不适用。在这种情况下,BabylonJS会试图恢复到之前的效果。

我们可以使用light的setEnabled方法来开启或关闭光照,例如我们一秒钟切换一下光照开关,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  var createSceneOnOff = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);


/**************************************************************/

var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1 , 0),scene);

setInterval(()=>{

light.setEnabled(!light.isEnabled())

},1000)
// Create a sphere which diameter is 8

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material

return scene;
}
const canvasOnOff = document.getElementById('renderCanvas-8-onoff')
const engineOnOff = new BABYLON.Engine(canvasOnOff,true)
const sceneOnOff = createSceneOnOff(engineOnOff,canvasOnOff)
engineOnOff.runRenderLoop(function(){sceneOnOff.render()})

效果如下:

我们可以使用light的intensity属性来设置光照的强度,(默认1),例如我们从0缓慢增加光强到1,再缓慢减为0,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var createSceneIntensity = function (engine,canvas) {
// This creates a basic Babylon Scene object (non-mesh)
var scene = new BABYLON.Scene(engine);

// This creates and positions an ArcRotateCamera;
var camera = new BABYLON.ArcRotateCamera("camera", -Math.PI/2,Math.PI/2,20,new BABYLON.Vector3(0, 0, 0), scene);

var material =new BABYLON.StandardMaterial("material",scene)

material.diffuseColor=new BABYLON.Color3(0,1,0)


// This targets the camera to scene origin
camera.setTarget(BABYLON.Vector3.Zero());

// This attaches the camera to the canvas
camera.attachControl(canvas, false);


/**************************************************************/

var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1 , 0),scene);

light.intensity = 0
// Create a sphere which diameter is 8


var sphere = BABYLON.MeshBuilder.CreateSphere("sphere",{diameter:8},scene)

sphere.material=material;

let dir=0
scene.registerBeforeRender(()=>{
if(!dir)
light.intensity +=0.005
else
light.intensity -=0.005
if(light.intensity>=1) dir=1
else if(light.intensity<=0) dir=0
})


return scene;
}
const canvasIntensity = document.getElementById('renderCanvas-8-intensity')
const engineIntensity = new BABYLON.Engine(canvasIntensity,true)
const sceneIntensity = createSceneIntensity(engineIntensity,canvasIntensity)
engineIntensity.runRenderLoop(function(){sceneIntensity.render()})

效果如下:

我们还可以使用light的excludedMeshes方法和includedOnlyMeshes方法来设置该光照只在特定的mesh上显示或不显示。以Babylon提供的代码作为演示,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
var createSceneExcludeIncludedOnly = function (engine,canvas) {
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 4, 8, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, false);

//Light direction is up and left
var light0 = new BABYLON.HemisphericLight("hemiLight", new BABYLON.Vector3(-1, 1, 0), scene);
light0.diffuse = new BABYLON.Color3(1, 0, 0);
light0.specular = new BABYLON.Color3(0, 1, 0);
light0.groundColor = new BABYLON.Color3(0, 1, 0);

var light1 = new BABYLON.HemisphericLight("hemiLight", new BABYLON.Vector3(-1, 1, 0), scene);
light1.diffuse = new BABYLON.Color3(1, 1, 1);
light1.specular = new BABYLON.Color3(1, 1, 1);
light1.groundColor = new BABYLON.Color3(0, 0, 0);

var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter: 0.5}, scene);

var spheres = [];
for(var i = 0; i < 25; i++) {
spheres[i] = sphere.clone("sphere" +i);
spheres[i].position.x = -2 + i%5;
spheres[i].position.y = 2 - Math.floor(i/5);
}

light0.excludedMeshes.push(spheres[7], spheres[18]);
light1.includedOnlyMeshes.push(spheres[7], spheres[18])

return scene;
}
const canvasExcludeIncludedOnly = document.getElementById('renderCanvas-8-excludedincludedonly')
const engineExcludeIncludedOnly = new BABYLON.Engine(canvasExcludeIncludedOnly,true)
const sceneExcludeIncludedOnly = createSceneExcludeIncludedOnly(engineExcludeIncludedOnly,canvasExcludeIncludedOnly)
engineExcludeIncludedOnly.runRenderLoop(function(){sceneExcludeIncludedOnly.render()})

效果如下:

法线 (Normals)

一个mesh的其中一面的顶点vertex的法线normal方向决定这个面对光照的表现,当法线指向光源时,光照最强。

如图所示,箭头方向指的是法线方向,我们可以看出,只有法线方向朝着光源(前面)的面被光照射除了颜色,而背离光源(后面)的面没有被光照影响。

光照图 (Lightmaps)

复杂光照会导致计算速度降低,影响性能。这时我们可以使用光照图来存储计算后的光照到一个纹理中:

1
2
3
var lightmap = new BABYLON.Texture("lightmap.png", scene);
var material = new BABYLON.StandardMaterial("material", scene);
material.lightmapTexture = lightmap;

提示:如果使用纹理作为shadowmap替代lightmap,请设置材质的useLightmapAsShadowmap属性为true

我们设置光源lightmapMode属性,来实现光照与光照图的混合方式。

  • BABYLON.Light.LIGHTMAP_DEFAULT 这会使光照应用到mesh后光照图材质再进行混合
  • BABYLON.Light.LIGHTMAP_SPECULAR 与BABYLON.Light.LIGHTMAP_DEFAULT相同,除了光照的镜面光和阴影将被应用
  • BABYLON.Light.LIGHTMAP_SHADOWSONLY 与BABYLON.Light.LIGHTMAP_DEFAULT相同,除了光照的阴影将被应用

使用Babylon提供的代码进行演示,首先有一张光照图的纹理图片,如图所示:

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
var createSceneLightmap = function (engine,canvas) {
// Create scene and camera
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 10, -25), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, false);

// Create light
var light = new BABYLON.PointLight("light", new BABYLON.Vector3(3, 3, 2), scene);
light.intensity = 0.7;

// Create lightmap texture on a material
var lightmap = new BABYLON.Texture("https://www.babylonjs-playground.com/textures/candleopacity.png", scene);
var groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene);
groundMaterial.lightmapTexture = lightmap;

// Apply lightmap to floor mesh
var ground = BABYLON.Mesh.CreateGround("ground", 20, 20, 4, scene);
ground.material = groundMaterial;
ground.receiveShadows = true;

// Create sphere which will cast shadow on floor mesh
var sphere = BABYLON.Mesh.CreateSphere("sphere1", 16, 1, scene);
sphere.position.z=-1
sphere.position.y=2;
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
shadowGenerator.addShadowCaster(sphere)

// Move light in the scene
var curTime = 0;
var lastState = 0;
var lightMapHint = document.querySelector('#lightMapHint')
lightMapHint.innerText='light.lightmapMode = BABYLON.Light.LIGHT_DEFAULT'

scene.onBeforeRenderObservable.add(()=>{
curTime+=engine.getDeltaTime();
light.position.x = Math.sin(curTime/1000)*5
var t = Math.floor(curTime/(Math.PI*2*1000))%3
if(t!==lastState){
switch(t){
case 0:
light.lightmapMode=BABYLON.Light.LIGHTMAP_DEFAULT
lightMapHint.innerText='light.lightmapMode = BABYLON.Light.LIGHTMAP_DEFAULT'
break;
case 1:
light.lightmapMode=BABYLON.Light.LIGHTMAP_SPECULAR
lightMapHint.innerText='light.lightmapMode = BABYLON.Light.LIGHTMAP_SPECULAR'
break;
case 2:
light.lightmapMode=BABYLON.Light.LIGHTMAP_SHADOWSONLY
lightMapHint.innerText='light.lightmapMode = BABYLON.Light.LIGHTMAP_SHADOWSONLY'
break;
}
lastState=t
}
})
return scene;
}
const canvasLightmap = document.getElementById('renderCanvas-8-lightmap')
const engineLightmap = new BABYLON.Engine(canvasLightmap,true)
const sceneLightmap = createSceneLightmap(engineLightmap,canvasLightmap)
engineLightmap.runRenderLoop(function(){sceneLightmap.render()})

效果如下:

投影纹理 (Projection Texture)

这个就像投影仪一样。目前只能使用聚光灯(SpotLight)进行纹理的投影。

1
2
var spotLight = new BABYLON.SpotLight("spot02", new BABYLON.Vector3(30, 40, 30),new BABYLON.Vector3(-1, -2, -1), 1.1, 16, scene);
spotLight.projectionTexture = new BABYLON.Texture("textures/stainedGlass.png", scene);

我们还可以设置light的以下属性:

  • projectionTextureNear number 投影的近距离,比这个距离近则看不到投影
  • projectionTextureFar number 投影的远距离,比这个距离远则看不到投影
  • projectionTextureUpDirection BABYLON.Vector3 定义投影的光空间的对其方向

我们使用以下代码来演示投影纹理,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 var createSceneProjectionTexture = function (engine,canvas) {
// Create scene and camera
var scene = new BABYLON.Scene(engine);
var camera = new BABYLON.ArcRotateCamera("camera1",-Math.PI/2,Math.PI/4,35,BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, false);

// Create light
var light = new BABYLON.SpotLight("light",new BABYLON.Vector3(0,30,0),new BABYLON.Vector3(0,-1,0),Math.PI/4,5, scene);
light.intensity = 0.7;
light.projectionTexture = new BABYLON.Texture("https://zzqizqute.github.io/css/images/banner.jpg",scene);
var dir = 0
scene.registerBeforeRender(()=>{
if(!dir){
light.position.y+=0.05;
}else{
light.position.y-=0.05;
}
if(light.position.y>=30)dir=1;
else if(light.position.y<=10) dir=0;
});
var ground = BABYLON.MeshBuilder.CreateGround("ground",{width:20,height:20},scene);

return scene;
}
const canvasProjectionTexture = document.getElementById('renderCanvas-8-projectiontexture')
const engineProjectionTexture = new BABYLON.Engine(canvasProjectionTexture,true)
const sceneProjectionTexture = createSceneProjectionTexture(engineProjectionTexture,canvasProjectionTexture)
engineProjectionTexture.runRenderLoop(function(){sceneProjectionTexture.render()})

效果如下: