Babaylon.js中常用的灯光详解(一)

世界路过没有光,那么将是一片漆黑。试想一下一位美女,穿着非常漂亮的红色连衣裙站在你的面前,如果是白天,那么,你能清晰的看到她的红色的魅影,这是因为有光。如果伸手不见五指的夜晚,你可能只能看到一片漆黑,她的衣服再漂亮,对你来说,也是一片黑色,因为没有光。

红色连衣裙美女

在3D世界中也是一样的,必须要有光。下面这幅图就是一个漂亮的球体与多个光源的效果:

Babylonjs多光源例子

图中的小点是我们绘制的光源,实际Babylon.js中光源是看不到的。


光源的几种类型

在现实生活中我们会常见一些光源,这些光源和3D世界中的光源属性相近,本章大家将学习4种Babylon.js中的光源(灯光):

  • 点光源(BABYLON.PointLight)
  • 方向光(BABYLON.DirectionalLight)
  • 聚光灯(BABYLON.SpotLight)
  • 球形光(BABYLON.HemisphericLight)

ok,开始我们的灯光秀吧。


点光源

有时候需要一个小的光源,例如一个灯泡,这些光源就是点光源。点光源常常被设置在某个位置上,然后随着离距离的变远光照强度变小。如下图:

Babylonjs点光源效果

现实世界中,点光源只能照亮周围的一段距离。

我们来看一下点光源的原型: BABYLON.PointLight API点光源

PointLight(name: string, position: Vector3, scene: Scene): PointLight
  • name: 光源的名字

  • position: 在场景中的光源位置

  • scene: 属于哪一个场景


例子1:点光源的例子

少说话,多做事,我们先看效果:

Babylonjs点光源效果 30.html ,代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <title>Babylon.js sample code</title>

        <!-- Babylon.js -->
        <script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
        <script src="https://preview.babylonjs.com/ammo.js"></script>
        <script src="https://preview.babylonjs.com/cannon.js"></script>
        <script src="https://preview.babylonjs.com/Oimo.js"></script>
        <script src="https://preview.babylonjs.com/earcut.min.js"></script>
        <script src="https://preview.babylonjs.com/babylon.js"></script>
        <script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
        <script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
        <script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
        <script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
        <script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
        <script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
        <script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>

        <style>
            html, body {
                overflow: hidden;
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }

            #renderCanvas {
                width: 100%;
                height: 100%;
                touch-action: none;
            }
        </style>
    </head>
<body>
    <canvas id="renderCanvas"></canvas>
    <script>
        var canvas = document.getElementById("renderCanvas");

        var engine = null;
        var scene = null;
        var createDefaultEngine = function() { return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil: true }); };
        
        var createScene = function () {
            var scene = new BABYLON.Scene(engine);
            var camera = new BABYLON.ArcRotateCamera("Camera", -Math.PI / 2, Math.PI / 3, 10, BABYLON.Vector3.Zero(), scene);
            camera.attachControl(canvas, true);
        	
            var light = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(0, 1, 0), scene);
        
        	var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 6}, scene);	
        
            return scene;
        
        };
        
        engine = createDefaultEngine();
        if (!engine) throw 'engine should not be null.';
        scene = createScene();

        engine.runRenderLoop(function () {
            if (scene) {
                scene.render();
            }
        });

        // Resize
        window.addEventListener("resize", function () {
            engine.resize();
        });
    </script>
</body>
</html>

代码解释如下:

  • 代码中引入了很多js文件,别管他,如果你直接写,你直接引入babylon.js就可以了。

  • 关于创建场景、相机的代码,这里就不讲了,

  • 主要看var light = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(0, 1, 0), scene);这段定义了一个聚光灯,放在(0,1,0)的位置,离地板的距离是1个单位。

  • 创建了一个平面作为地板:var ground = BABYLON.MeshBuilder.CreateGround("ground", {width: 4, height: 6}, scene);

ok,你是不是观察到地板上的灯光是白色,因为点光源是白色的。我们可以换一种点光源的颜色。


设置灯光颜色

可以通过diffuse属性来设置灯光的颜色。我们这里把点光源设置为红色,效果如下图

Babylonjs红色点光源

Babylonjs红色点光源完整代码见31.html

var light = new BABYLON.PointLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.diffuse = new BABYLON.Color3(1, 0, 0);

改变上面的diffuse颜色,并刷新浏览器,你能看到不同的颜色。

换成黄色的关键代码:

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

效果如下:

Babylonjs黄色点光源效果


点光源设置镜面光(specular)

镜面光是指高亮反光位置的颜色表现,我们经常会在玻璃上看到镜面光。

Babylonjs镜面反光

babylonjs中镜面光可以通过specular设置:

Babylonjs红色点光源+绿色镜面光完整代码见33.html

核心代码如下:

// 绿色
light.specular = new BABYLON.Color3(0, 1, 0);

33.html的效果如下:

Babylonjs绿色镜面高光


移动光源的位置

点光源会不会随着距离而衰减呢,肯定是会的,这里我们做一个实验,只需要将光源的位置这只得越来越远就可以了。

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

上面的代码中改变第2个位置参数的y坐标,就可以让光源离平面越来越远了。

Babylonjs光源距离1:33.html

Babylonjs光源距离2:34.html

Babylonjs光源距离3:35.html

我们对比一下效果,不解释相应大家都会明白的。

Babylonjs镜面高光 Babylonjs点光源位置设置 Babylonjs点光源距离为3

看一下光晕越来越大,越来越淡,说明光源距离地面越来越远了。