认识光源

来源:互联网 发布:php网络验证源码 编辑:程序博客网 时间:2024/04/30 08:24

光源基类

在Threejs中,光源用Light表示,它是所有光源的基类。它的构造函数是:
THREE.Light (color)
它有一个参数color,接受一个16进制的颜色值。例如要定义一种红色的光源,我们可以这样来定义:
Var light = new THREE.Light(0xFF0000);


由基类派生出来的其他种类光源

THREE.Light只是其他所有光源的基类,要让光源除了具有颜色的特性之外,我们需要其他光源。看看,下面的类图,是目前光源的继承结构。





环境光

经过多次反射而来的光称为环境光(或者也可以这么说:无法确定光最初的方向的光就叫环境光。比如阴天的时候没有太阳,你无法确定光是从哪里照射出来的。)


环境光的颜色会影响整个场景,并且其光线没有特定的来源,所以你无须指定它的位置。在使用其它光源的同时使用环境光,目的是弱化阴影或添加一些颜色。


环境光用THREE.AmbientLight来表示,它的构造函数如下所示:
AmbientLight( color,intensity )
color: 光的颜色
intensity  : 光的强度,默认是1.0,就是说是100%强度的灯光

例子 :
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <style>        body{padding: 0; margin: 0; overflow: hidden;}    </style>    <title>环境光</title> </head><body>  <div id="WebGL-output"></div> </body><script src='three.js'></script><script src='dat.gui.js'></script><script>var scene = new THREE.Scene();   var axes = new THREE.AxisHelper(100);  scene.add(axes);  var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    camera.position.set(-8,8,20);  camera.lookAt(scene.position);  var renderer = new THREE.WebGLRenderer();   renderer.setSize(window.innerWidth, window.innerHeight);  renderer.setClearColor('#fff');document.body.appendChild(renderer.domElement);  //矩形var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());mshFloor.position.set( 0, -1, 0 );scene.add(mshFloor)//立方体   var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({      color : 0x7777ff })); cube.position.set(0,0.5,0); scene.add(cube); //环境光var light = new THREE.AmbientLight(0xffffff);light.position.set( 0, 5, 0 );    scene.add(light);    //小球,它的位置就是光源的位置var sphereLight = new THREE.SphereGeometry(0.2);    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);    scene.add(sphereLightMesh);    //GUI    var controls = new function(){    this.color = light.color.getHex();    this.intensity = light.intensity;    this.light_x = light.position.x;    this.light_y = light.position.y;    this.light_z = light.position.z;    }    var gui = new dat.GUI();gui.addColor(controls, 'color').onChange(function (e) {    light.color = new THREE.Color(e);});gui.add(controls, 'intensity', 0,1).onChange(function (e) {    light.intensity = e;});gui.add(controls, 'light_x', -50,50).onChange(function (e) {    light.position.x = e;    sphereLightMesh.position.x = e;});gui.add(controls, 'light_y', -50,50).onChange(function (e) {    light.position.y = e;    sphereLightMesh.position.y = e;});gui.add(controls, 'light_z', -50,50).onChange(function (e) {    light.position.z = e;    sphereLightMesh.position.z = e;});//更新函数function updata(){     cube.rotation.y +=0.01;      axes.rotation.y +=0.01;     mshFloor.rotation.y +=0.01;     renderer.render(scene, camera);      requestAnimationFrame(updata);  }  updata();  //窗口事件window.onresize = function(){renderer.setSize(window.innerWidth, window.innerHeight);  }</script></html>

效果图:


从上面的例子可以看出,光的位置对环境光是没有影响的。



点光源

点光源是一种单点发光并照射所有方向的光源。比如夜空中的照明灯。

点光源用PointLight来表示,它的构造函数如下所示:

PointLight( color, intensity, distance,decay)
color:光的颜色
intensity:光的强度,默认是1.0,就是说是100%强度的灯光
distance:光能照射到的最远的距离。
decay : 值为0~1. 此值越大,光的衰减程度越多。

例子 :
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <style>        body{padding: 0; margin: 0; overflow: hidden;}    </style>    <title>点光源</title> </head><body>  <div id="WebGL-output"></div> </body><script src='three.js'></script><script src='dat.gui.js'></script><script>var scene = new THREE.Scene();   var axes = new THREE.AxisHelper(100);  scene.add(axes);  var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    camera.position.set(-8,8,20);  camera.lookAt(scene.position);  var renderer = new THREE.WebGLRenderer();   renderer.setSize(window.innerWidth, window.innerHeight);  renderer.setClearColor('#fff');document.body.appendChild(renderer.domElement);  //矩形var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());mshFloor.position.set( 0, -1, 0 );scene.add(mshFloor)//立方体   var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({      color : 0x7777ff })); cube.position.set(0,0.5,0); scene.add(cube); //点光源var light = new THREE.PointLight(0xffffff, 1, 1000);light.position.set( 0, 5, 0 );    scene.add(light);    //小球,它的位置就是光源的位置var sphereLight = new THREE.SphereGeometry(0.2);    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);    scene.add(sphereLightMesh);    //GUI    var controls = new function(){    this.color = light.color.getHex();    this.intensity = light.intensity;    this.distance = light.distance;    this.light_x = light.position.x;    this.light_y = light.position.y;    this.light_z = light.position.z;    }    var gui = new dat.GUI();gui.addColor(controls, 'color').onChange(function (e) {    light.color = new THREE.Color(e);});gui.add(controls, 'intensity', 0,1).onChange(function (e) {    light.intensity = e;});gui.add(controls, 'distance', 0,1000).onChange(function (e) {    light.distance = e;});gui.add(controls, 'light_x', -50,50).onChange(function (e) {    light.position.x = e;    sphereLightMesh.position.x = e;});gui.add(controls, 'light_y', -50,50).onChange(function (e) {    light.position.y = e;    sphereLightMesh.position.y = e;});gui.add(controls, 'light_z', -50,50).onChange(function (e) {    light.position.z = e;    sphereLightMesh.position.z = e;});//更新函数function updata(){     cube.rotation.y +=0.01;      axes.rotation.y +=0.01;     mshFloor.rotation.y +=0.01;     renderer.render(scene, camera);      requestAnimationFrame(updata);  }  updata();  //窗口事件window.onresize = function(){renderer.setSize(window.innerWidth, window.innerHeight);  }</script></html>

效果图:



聚光灯

聚光灯有一种锥形的效果。比如手电筒发射出来的光。



聚光灯用SpotLight来表示,它的构造函数如下所示:
SpotLight( color, intensity, distance, angle, penumbra, decay)
color:光的颜色
intensity:光的强度,默认是1.0,就是说是100%强度的灯光
distance:光能照射到的最远的距离。
angle : 椎体的角度
penumbra : 羽化程度
decay : 值为0~1. 此值越大,光的衰减程度越多。

例子:
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <style>        body{padding: 0; margin: 0; overflow: hidden;}    </style>    <title>聚光灯</title> </head><body>  <div id="WebGL-output"></div> </body><script src='three.js'></script><script src='dat.gui.js'></script><script>var scene = new THREE.Scene();   var axes = new THREE.AxisHelper(100);  scene.add(axes);  var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    camera.position.set(-8,8,20);  camera.lookAt(scene.position);  var renderer = new THREE.WebGLRenderer();   renderer.setSize(window.innerWidth, window.innerHeight);  renderer.setClearColor('#fff');renderer.shadowMapEnabled = true;document.body.appendChild(renderer.domElement);  //矩形var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());mshFloor.receiveShadow = true;mshFloor.position.set( 0, -1, 0 );scene.add(mshFloor)//立方体   var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({      color : 0x7777ff })); cube.position.set(0,0.5,0); cube.castShadow = true;scene.add(cube); //聚光灯var light = new THREE.SpotLight(0xffffff, 1, 1000, 1);light.position.set( 0, 5, 0 );light.castShadow = true;light.shadowMapWidth = 2048;//阴影的宽度用多少像素绘制light.shadowMapHeight = 2048;//阴影的高度用多少像素绘制    scene.add(light);    //小球,它的位置就是光源的位置var sphereLight = new THREE.SphereGeometry(0.2);    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);    scene.add(sphereLightMesh);    //辅助线,帮助我们看到聚光灯angle的变化    var lightHelper = new THREE.SpotLightHelper( light );    scene.add( lightHelper );    //GUI    var controls = new function(){    this.color = light.color.getHex();    this.intensity = light.intensity;    this.distance = light.distance;    this.angle = light.angle;    this.penumbra = 1;  //聚光灯的模糊度    this.light_x = light.position.x;    this.light_y = light.position.y;    this.light_z = light.position.z;    }    var gui = new dat.GUI();gui.addColor(controls, 'color').onChange(function (e) {    light.color = new THREE.Color(e);});gui.add(controls, 'intensity', 0,1).onChange(function (e) {    light.intensity = e;});gui.add(controls, 'distance', 0,1000).onChange(function (e) {    light.distance = e;});    gui.add(controls, 'angle', 0,1).onChange(function (e) {    light.angle = e;     lightHelper.update();});gui.add(controls, 'penumbra', 0,1).onChange(function (e) {    light.penumbra = e;});gui.add(controls, 'light_x', -50,50).onChange(function (e) {    light.position.x = e;    sphereLightMesh.position.x = e;    lightHelper.update();});gui.add(controls, 'light_y', -50,50).onChange(function (e) {    light.position.y = e;    sphereLightMesh.position.y = e;    lightHelper.update();});gui.add(controls, 'light_z', -50,50).onChange(function (e) {    light.position.z = e;    sphereLightMesh.position.z = e;    lightHelper.update();});//更新函数function updata(){     cube.rotation.y +=0.01;      axes.rotation.y +=0.01;     mshFloor.rotation.y +=0.01;     renderer.render(scene, camera);      requestAnimationFrame(updata);  }  updata();  //窗口事件window.onresize = function(){renderer.setSize(window.innerWidth, window.innerHeight);  }</script></html>

效果图:



方向光

方向光可以看作是距离很远的光源,比如太阳光。被方向光照亮的整个区域接收到的光的强度是一样的。你可以用方向光来模拟晚上到早上的过渡效果。

方向光用DirectionalLight来表示,它的构造函数如下所示:

DirectionalLight(color, intensity)
color :颜色
intensity :光的强度,默认是1.0,就是说是100%强度的灯光

例子:
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <style>        body{padding: 0; margin: 0; overflow: hidden;}    </style>    <title>方向光</title> </head><body>  <div id="WebGL-output"></div> </body><script src='three.js'></script><script src='dat.gui.js'></script><script>var scene = new THREE.Scene();   var axes = new THREE.AxisHelper(100);  scene.add(axes);  var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    camera.position.set(-8,8,20);  camera.lookAt(scene.position);  var renderer = new THREE.WebGLRenderer();   renderer.setSize(window.innerWidth, window.innerHeight);  renderer.setClearColor('#fff');renderer.shadowMapEnabled = true;document.body.appendChild(renderer.domElement);  //矩形var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());mshFloor.position.set( 0, -1, 0 );mshFloor.receiveShadow = true;scene.add(mshFloor)//立方体   var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({      color : 0x7777ff })); cube.position.set(0,0.5,0);cube.castShadow = true; scene.add(cube); //方向光var light = new THREE.DirectionalLight (0xffffff, 0.5);light.castShadow = true;light.position.set( 0, 5, 0 );    scene.add(light);    //小球,它的位置就是光源的位置var sphereLight = new THREE.SphereGeometry(0.2);    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);    scene.add(sphereLightMesh);    //GUI    var controls = new function(){    this.color = light.color.getHex();    this.intensity = light.intensity;    this.light_x = light.position.x;    this.light_y = light.position.y;    this.light_z = light.position.z;    }    var gui = new dat.GUI();gui.addColor(controls, 'color').onChange(function (e) {    light.color = new THREE.Color(e);});gui.add(controls, 'intensity', 0,1).onChange(function (e) {    light.intensity = e;});gui.add(controls, 'light_x', -50,50).onChange(function (e) {    light.position.x = e;    sphereLightMesh.position.x = e;});gui.add(controls, 'light_y', -50,50).onChange(function (e) {    light.position.y = e;    sphereLightMesh.position.y = e;});gui.add(controls, 'light_z', -50,50).onChange(function (e) {    light.position.z = e;    sphereLightMesh.position.z = e;});//更新函数function updata(){     cube.rotation.y +=0.01;      axes.rotation.y +=0.01;     mshFloor.rotation.y +=0.01;     renderer.render(scene, camera);      requestAnimationFrame(updata);  }  updata();  //窗口事件window.onresize = function(){renderer.setSize(window.innerWidth, window.innerHeight);  }</script></html>

效果图:



区域光

区域光也叫平面光,使用平面光你可以定义一个发光的矩形。该光源不在标准的three.js库中,而是在扩展库中,所以使用之前需要导入几个额外的js文件。
另外该光源是一种非常复杂的光源,它会对WebglRenderer对象造成非常严重的性能损失。所以使用该光源时要使用WebGLDeferredRenderer来代替WebglRenderer。

平面光用AreaLight来表示,它的构造函数如下所示:
AreaLight(color, intensity)
color :颜色
intensity :光的强度,默认是1.0,就是说是100%强度的灯光

例子 :
<!DOCTYPE html><html><head>    <meta charset="utf-8">    <style>        body{padding: 0; margin: 0; overflow: hidden;}    </style>    <title>平面光</title> </head><body>  <div id="WebGL-output"></div> </body><script src='three_AreaLight.js'></script><script src='dat.gui.js'></script><!--平面光需要导入的js库--><script type="text/javascript" src="WebGLDeferredRenderer.js"></script><script type="text/javascript" src="ShaderDeferred.js"></script><script type="text/javascript" src="RenderPass.js"></script><script type="text/javascript" src="EffectComposer.js"></script><script type="text/javascript" src="CopyShader.js"></script><script type="text/javascript" src="ShaderPass.js"></script><script type="text/javascript" src="FXAAShader.js"></script><script type="text/javascript" src="MaskPass.js"></script><script>var scene = new THREE.Scene();   var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    camera.position.set(0,30,30);  camera.lookAt(scene.position);//WebGLDeferredRenderervar renderer = new THREE.WebGLDeferredRenderer({    width: window.innerWidth,    height: window.innerHeight,    scale: 1, antialias: true,    tonemapping: THREE.FilmicOperator, brightness: 2.5 });document.body.appendChild(renderer.domElement);//平面    var mshFloor = new THREE.Mesh(    new THREE.PlaneGeometry(70, 70, 1, 1),     new THREE.MeshPhongMaterial({ color: 0xffffff, specular: 0xffffff, shininess: 200 })    );    mshFloor.rotation.x = -0.5 * Math.PI;    scene.add(mshFloor);//平面光var light = new THREE.AreaLight(0xffffff, 1.5);light.position.set(0, 5, -10);    light.rotation.set(-Math.PI / 2, 0, 0);    light.width = 2;    light.height = 4;    scene.add(light);    //伪发光的立方块    var geom = new THREE.CubeGeometry(2, 4, 0);    var mesh = new THREE.MeshBasicMaterial({color: 0xffffff})    var cube = new THREE.Mesh(geom, mesh);    cube.position = light.position;    scene.add(cube);    //GUI    var controls = new function(){    this.color = light.color.getHex();    this.intensity = light.intensity;    this.light_x = light.position.x;    this.light_y = light.position.y;    this.light_z = light.position.z;    }    var gui = new dat.GUI();gui.addColor(controls, 'color').onChange(function (e) {    light.color = new THREE.Color(e);    //重新设置材质的颜色        mesh.color = new THREE.Color(e);        scene.remove(cube);        cube = new THREE.Mesh(geom, mesh);        cube.position = light.position;        scene.add(cube);});gui.add(controls, 'intensity', 0,3).onChange(function (e) {    light.intensity = e;});gui.add(controls, 'light_x', -50,50).onChange(function (e) {    light.position.x = e;    cube.position.x = e;});gui.add(controls, 'light_y', -50,50).onChange(function (e) {    light.position.y = e;    cube.position.y = e;});gui.add(controls, 'light_z', -50,50).onChange(function (e) {    light.position.z = e;    cube.position.z = e;});//更新函数function updata(){     renderer.render(scene, camera);      requestAnimationFrame(updata); }  updata();  //窗口事件window.onresize = function(){renderer.setSize(window.innerWidth, window.innerHeight);  }</script></html>

效果图 :



生成阴影

上面的例子中,有一些光源能生成阴影,而有一些光源不能。因为在three.js中,能形成阴影的光源只有 方向光 和 聚光灯;而相对的能表现阴影效果的材质只有 LambertMaterial 和 PhongMaterial。因此在设置光源和材质的时候,一定要注意这一点。
给物体生成阴影需要4个步骤 :
1、renderer.shadowMapEnabled = true; 
告诉渲染器我们需要阴影。为此可以将shadowMapEnabled (允许阴影映射)属性设为true
2、plane.receiveShadow = true;
接受阴影的物体需要把receiveShadow 设为true
3、cube.castShadow = true;
投射阴影的物体需要啊castShadow 设为true
4、light.castShadow = true;
把光源的castShadow 也设为true (需要注意改光源是否能产生阴影)


设置阴影的像素

设置光源的 shadowMapWidth 和shadowMapHeight 可以调整阴影的真实程度。如下图 : 


设置之前


设置之后

例子 :
light.shadowMapWidth = 2048; //阴影的宽度用多少像素绘制light.shadowMapHeight = 2048; //阴影的高度用多少像素绘制



本章代码下载地址 :http://download.csdn.net/detail/qq408896436/9725640


0 0
原创粉丝点击