光照模型

光照点光源环境光平行光LightAmbientLightPointLight聚光灯光源SpotLight半球光源属性见基类Light方法见基类LightcastShadow布尔HemisphereLight类比Geometry、Material、Mesh光照对象基类Mesh、Line、Point基类也是Object3D所有光源对象都具有平移、旋转、位置等属性或方法基类Object3DLight( color, intensity )RGB值color光强intensity 参数构造函数基类Object3D共有属性光源颜色16进制RGB模型例    0xffffffcolor光源强度0.0~1.0默认1.0intensity属性基类Object3D共有方法赋值光照对象.copy ( light)返回JSON格式的光源数据toJSON ( meta )方法DirectionalLight( color, intensity )参数同基类Light参数同基类Light参数color intensitydistancedecay同基类Light同基类Light光强光强为0距离光源距离光照衰减量参数colorintensitydistance anglepenumbra decayRGB值散射角最大值Math.PI/2光锥半径方向衰减光照距离方向衰减

  教程第一节课就提到了光照模型,只是没有展开讲解,下面的内容先总结一下不同光照模型的构造函数、方法、属性和基类。

光照对象、方法和属性

  下面的代码设置的是点光源和环境光源

28       /**
29        * 光源设置
30        */
31       //点光源
32       var point=new THREE.PointLight(0xffffff);
33       point.position.set(400,200,300);//点光源位置
34       scene.add(point);//点光源添加到场景中
35       //环境光
36       var ambient=new THREE.AmbientLight(0x444444);
37       scene.add(ambient);

构造函数参数:颜色

  第32行代码THREE.PointLight(0xffffff)通过构造函数PointLight()定义了以点光源对象,参数0xffffff表示光照颜色RGB值。

共有属性

  第33行代码point.position.set(400,200,300)通过属性position和方法set()设置了点光源对象的位置,点光源的位置设置和网格模型一样,光源对象Light和网格模型对象Mesh都有一个Object3D基类, 因此Object3D对象的属性和方法,也就是环境光源、点光源、平行光等光源对象的共有属性和共有方法。

基类Light

  创建材质对象的时候,可以通过构造函数的参数定义颜色属性,也可以先通过构造函数创建一个没有颜色的材质对象,然后通过颜色属性定义颜色值。对于光源对象一样,可查找three.js文档中的Light对象, Geometry对象是圆柱、球等几何体的基类,Material对象是所有材质对象的基类,可以对比Geometry对象、Material对象来理解Light对象,Light对象是所有光源对象的基类,其它光源对象都拥有基类Light的属性, Light对象颜色属性color属性值是Color对象,所以通过构造函数THREE.Color()可以定义color属性的属性值。可以使用下面的代码替换第32行代码,最终的效果是一样的。

    var point=new THREE.PointLight();
    point.color = new THREE.Color(0xffffff);

add方法

  光源对象和网格对象都是场景对象的顶级子对象,光源对象创建完成以后和网格模型常见完成以后以后一样,需要执行add方法把光源对象作为参数添加到场景对象中,第34行代码scene.add(point)是把点光源point添加到场景对象Scene中, 第37行代码scene.add(ambient)是把环境光源对象ambient添加到场景对象Scene中。

光源对象分类

three.js光照模型

  光照模型的作用就是模拟自然界中光照计算物体表面的颜色随着光照条件的变化, 材质对象会定义网格模型的颜色、透明度等与光学有关的参数,材质定义的颜色会与光照的颜色进行乘法或加法运算, 网格模型的像素颜色分布取决于材质颜色和光场。关于光照模型更多的底层知识可以关注《WebGL教程—光照》

点光源PointLight

  点光源就像生活中的白炽灯,光线沿着发光核心向外发散,同一平面的不同位置与光线入射角是不同的,光照强度一样的情况下,光线的反射强度自然不同。 物体在自然环境下正是因为表面的不同位置对光线的反射程度不同,而呈现出立体效果。可以把上面代码中点光源注销,只保留环境光,刷新浏览器你会发现, 立方体的不再具有3D的效果,没有明显的棱角感。只有环境光的时候立方体表面的每一个位置的像素值完全一样,所以没有立体感;如果存在点光源,立方体两个外表面的光线入射角不同,光的反射百分比不同, 表面上看都是蓝色,实际上RGB值蓝色成分B的大小存在微小差异。你可以提高环境光的光照强度,或这降低点光源光照强度,你会发现立方体的棱角感讲解,立方体表面之间的分界线不再那么明显, 如果你有兴趣可以阅读计算机图形学光照模型部分知识,深入学习。

  在立方体表面取一点与点光源所在位置连线,就是点光源光线在立方体表面当前位置的入射光。为了计算入射光线的入射角自然需要设置点光源的三维坐标位置,设置点光源的位置通过position属性即可。

  构造函数格式:PointLight( color, intensity, distance, decay )

  参数intensity表示光照强度系数,默认发的情况下是1,比如PointLight( 0x080808, 0.5 )等价于PointLight( 0x040404 )。

  参数distance表示用来设置光源光线随着距离变化衰减的程度,一般在机械或工业设计的渲染中用不到,如果是为了表达点光源在雾中的衰减效果用得到。

环境光光源AmbientLight

  光线在自然环境物体之间会来回反射,宏观来看形成一个没有特定方向的光场环境,在上面代码中定义点光源的时候需要通过定义顶点光源位置来计算光线与几何体表面的夹角, 对于环境光而言不需要考虑方向,只要设置光线RGB值即可。可以注释上面代码中的环境光对象,重新刷新浏览器鼠标转动立方体你会发现立方体有些外表面是黑色的, 这很容易理解,整个三维场景仅仅设置了环境光和点光源对象,点光源对象就像生活中的白炽灯一样无法照射到物体的背面,所以当你没有设置环境光的时候,正对点光源的立方体平面呈现蓝色, 背对着点光源的立方体平面呈现黑色。你可以把第36行代码THREE.AmbientLight(0x444444)中环境光源颜色值从0x444444更改为0x888888,刷新浏览器你会发现立方体的表面颜色更加明亮。 这一点是符合实际生活的,一个物品在昏暗的室内往往会比较暗,如果放在明亮的环境下,显示效果会更家明亮。0x000000表示没有光照完全是黑色,0xffffff表示环境光的光照强度达到最大, 如果把环境光的RGB值设置为0x000000就相当于不添加环境光源对象。

  把网格模型材质的颜色设置为白色0xffffff,此时环境光颜色是0x444444,刷新页面你会发现立方体显示效果是灰白色,通过调节环境光RGB值可以调节立方体在黑色与白色之间的变化效果。 网格模型材质颜色设置为白色的同时,如果把RGB值GB都设为0,R成分为44,即0x990000,可以模拟一个红色的环境效果,刷新浏览器你会看到立方体的表面有红色效果, 稍微有一些物理光学知识应该都能理解这些现象,物体呈现到人眼睛中的颜色并不是物体本身的颜色,而是在外界光照环境作用下的反射效果, 比如你把立方体材质对象的颜色设置为蓝色,光照颜色设置为红色,你会发现立方体显示为黑色,很显然蓝色的不透明物体只反射蓝色光线,不反射红色光线,立方体没有反射任何光线自然呈现黑色。 实际生活的环境环境光的RGB三种成分通常是一样的,也就是说颜色值是黑色、白色或介于黑白之间的灰色。特殊场合下,比如现代舞台上往往会营造出各种彩色效果。

平行光源DirectionalLight

  构造函数格式:PointLight( color, intensity),与基类Light一样,相比点光源少了distance和decay两个参数。

  点光源通过设置位置,three.js引擎会计算出入射角等参数,对于平行光而言需要定义光线的方向,通过平行光源对象的属性position和target可以设置光线方向, position默认值是(0,1,0),target默认是(0,0,0),position和target两个坐标差会确定一个光线方向,不自定义属性position和target,光线默认是从上到下,也就是沿着y轴负半轴方向, 仅仅设置平行光光源,代码如下,可以看到只有立方体的顶点有颜色。

    /**平行光设置*/
    var direction = new THREE.DirectionalLight(0xffffff);
    scene.add(direction);

设置position属性

    /**平行光设置*/
    var direction = new THREE.DirectionalLight(0xffffff);
    direction.position.set(1,1,1);
    scene.add(direction);

  这样的话点光源的方向就是(1,1,1),刷新浏览器你会看到立方体的三个面显示蓝色。