光和光的应用
1、点光Point Light
点光被定义为在3D世界中一个唯一的点,然后光从这个点向各个方向发射。有一个很形象的例子来比喻点光,那就是电灯泡。
//第二个参数是点光的位置。
1 | var light = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(1, 10, 1), scene); |
2、平行光Directional Light
平行光由方向定义(真是令人惊讶!…不知道老外为啥要惊讶),光从指定方向的任意位置发出,具有无限的范围。平行光的一个形象例子就是太阳光,就好比太阳照射到地球一样,会把地球面对太阳的方向全部照亮。
//第二个参数表示平行光的方向
1 | var light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0, -1, 0), scene); |
3、聚光灯Spot Light
聚光灯由位置position,方向direction,角度angle和指数exponent定义。上面的数值决定了圆锥形光束该从什么位置开始,然后朝哪个方向照射。
角度angle(以弧度为单位)定义了聚光灯圆锥形光束的大小(照亮的区域),指数exponent决定了光在到达目标的途中时,按距离衰减的速度。
1 | //第2个参数是位置、第3个参数是方向,第4个参数角度angle,第5个参数指数exponent |
4、半球光Hemispheric Light
半球光是模拟环境光的简便方法,它由一个方向参数定义,位于世界坐标中心(0,0,0),一般设置灯光方向朝正上方。而灯光只有设置了颜色属性,才能看到完整的效果。
1 | //第2个参数是方向 |
5、灯光颜色属性
灯光具有三个会影响颜色的属性
漫反射diffuse和镜面反射specular对上述4种灯光都会起作用
而底色groundColor仅适用于半球光Hemispheric Light
灯光最大数量限制
Babylon.js可以创建和注册任意数量的灯光,但是我们要注意单个标准材质只能同时处理有限的灯光效果(默认是4个,这意味着只有一开始创建的前4个灯光有作用)。不过我们能够对这个最大数量进行修改。
1 | var material = new BABYLON.StandardMaterial("mat", scene); |
指定照亮哪些物体
当创建一个灯光时,场景中所有的物体都会被照亮。有2种方法可以让某些物体不被照亮:一种是把需要排除的物体加入到excludedMeshes数组中,另一种是把需要照亮的物体加入到includedOnlyMeshes数组中,不在数组中的物体将不被照亮。两个方法应都有各自适应的使用情况,可能物体的数量也是一个考量因素,例如:照亮的多于不照亮的物体,使用排除excludedMeshes,否则使用includedOnlyMeshes。在以下的示例中,展示两个属性的使用方法,即从light0排除了2个物体,只用light1照亮同样2个物体,最终的效果就是light0照亮其余23个物体,而light1照亮2个物体。
光照法线Lighting Normals
灯光如何对物体做出反应,这取决于物体顶点设置的值,我们称为法线,如下图,箭头表示光照法线的方向。图片中包含两个平面Plane和两个灯光,一个是聚光灯Spot light,另一个是点光Point light。当法线的箭头指向你时,你看到的是平面的正面,背面则是相反的一侧。
光照贴图Lightmaps
复杂光照效果的计算成本非常高,可能会引起性能问题,所以为了节省资源,我们可以使用光照贴图Lightmaps,它可以提前将计算好的光照信息存储在物体的纹理中,相当于光照不用逐帧计算,以达到增加性能的效果。
1 | var lightmap = new BABYLON.Texture("lightmap.png", scene); //新建纹理 |
注意:要将纹理用作阴影贴图Shadowmap而不是光照贴图Lightmap,请将material.useLightmapAsShadowmap设置为true。
场景中场景灯光与光照贴图的混合方式可以进行设置,这依赖于灯光的lightmapMode属性。
//默认模式,表示在灯光应用到场景开始发光后,与光照贴图进行混合。
This will cause lightmap texture to be blended after the lighting from this light is applied.
light.lightmapMode = BABYLON.Light.LIGHTMAP_DEFAULT;
//与默认模式类似,只是仅将光照贴图应用到灯光的镜面反射发光和阴影上
This is the same as LIGHTMAP_DEFAULT except only the specular lighting and shadows from the light will be applied.
light.lightmapMode = BABYLON.Light.LIGHTMAP_SHADOWSONLY;
//与默认模式类似,只是仅将光照贴图应用到灯光的和阴影上
This is the same as LIGHTMAP_DEFAULT except only the shadows cast from this light will be applied.
light.lightmapMode = BABYLON.Light.LIGHTMAP_SPECULAR;
** 投影纹理Projection Texture**
在某些情况下,从纹理定义灯光效果更好,因为灯光的漫反射只有常规的一个基本颜色,效果不够炫酷。想象一下我们正在模拟灯光透过教堂玻璃反射到地面上的五颜六色效果(中国人可能很少知道教堂玻璃,如下图)。对于投影或者KTV气氛灯,也基本是这种很多颜色的灯光效果。
1 | var spotLight = new BABYLON.SpotLight("spot02", new BABYLON.Vector3(30, 40, 30), |
纹理打包程序Texture Packer
纹理打包程序Texture Packer,
把来自于多个材质的纹理打包成为一系列图片,这个类似于css sprite雪碧图。
但需要权衡的是,每个纹理都将按比例缩放到固定的大小,并可能导致一些纹理图片的相互混淆,webGL的限制也可能会成为一个瓶颈。
打包程序将为纹理创建一系列的帧,这个纹理是所有材质所对应的纹理通道的集合,且是唯一的;
然后再为被打包材质对应的每个通道生成一张图片;最后,通过修改物体的目标UV#,以使其与打包程序生成的纹理对应帧匹配,这个UV值是通过物体构造函数进行传递的。打包程序假定所有纹理都是一个正方形,即使不是,程序也会把这个纹理贴图放到正方形的框内。
1 | let pack = new BABYLON.TexturePacker(name, targetMeshes, options, scene); |