本章的主要內容javascript
1 three.js有哪些可用的光源html
2 何時用什麼光源、java
3 如何調整配置各類光源web
4 如何建立鏡頭炫光app
一 光源dom
光源大概有7種,性能
其中基礎光源有4種webgl
環境光(AmbientLight會它的顏色會添加到整個場景和全部對象的當前顏色上),ui
點光源(PointLight空間中的一點,朝全部的方向發射光線),this
聚光燈光源(SpotLight這種光源有聚光的效果,相似於檯燈,吊燈,手電筒),
方向光(DirectionalLight也稱無限光,從這種光源發出的光線能夠看做是平行的,例如太陽光)
特殊光源有3種(這三種咱們後面再詳述)
半球光光源(HemisphereLight,能夠爲室內場景建立更加天然的光照效果,模擬反光面和光線微弱的天氣)
面光源(AreaLight使用這種光源能夠指定散發光線的平面,而不是空間的一個點)
鏡頭炫光(LensFlare這不是一種光源,可是經過該炫光能夠爲場景中的光源添加炫目的效果)
1.1 環境光
AmbientLight光源的顏色會影響到整個場景,
環境光沒有特定的光源,是模擬漫反射的一種光源,所以不須要指定位置
它能將燈光均勻地照射在場景中每一個物體上面,通常狀況下用來弱化陰影或者添加一些顏色到環境中,
所以不能將AmbientLight做爲場景中的惟一光源,那樣的會就會致使下圖左邊的狀況,
右邊爲使用了SpotLight光源,並使用AmbientLight用來弱化SpotLight生成的生硬的陰影,
注意一下AmbientLight會將顏色應用於整個場景,所以使用AmbientLight的時候,用色應該儘可能的保守,若是顏色過於明亮,畫面顏色就會飽和
var ambiColor = "#0c0c0c"; var ambientLight = new THREE.AmbientLight(ambiColor); scene.add(ambientLight); //環境光不須要設置光源的位置等信息,只須要一個顏色便可,這個顏色就是漫反射到全部對象上的顏色
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="dat.gui.js"></script> <script type="text/javascript" src="AsciiEffect.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //var scene function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影 //生成一個座標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一塊兒,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); /*var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//須要陰影,方塊進行投射陰影*/ //聚光燈光源 /*var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(-40,60,-10); spotLight.castShadow=true;*/ var ambientLight=new THREE.AmbientLight("#0c0c0c"); scene.add(ambientLight); //將相機,渲染器,座標軸,平面都追加到場景中,而後對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); //scene.add(cube); //scene.add(spotLight); //var effect=new THREE.AsciiEffect(render); ///effect.setSize(window.innerWidth,window.innerHeight); document.getElementById("WebGL-output").append(render.domElement); var controls=new function(){ this.rotationSpeed=0.02; this.numberofObject=scene.children.length; this.addCube=function(){ var cubeSize=Math.ceil(Math.random()*3); var cubeGeometry=new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize); var cubeMaterial=new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}); var cube=new THREE.Mesh(cubeGeometry,cubeMaterial); cube.castShadow=true; cube.name="cube-"+scene.children.length; cube.position.x=-30+Math.round(Math.random()*planeGeometry.parameters.width); cube.position.y=Math.round(Math.random()*5); cube.position.z=-20+Math.round(Math.random()*planeGeometry.parameters.height); scene.add(cube); this.numberofObject=scene.children.length; }; this.removeCube=function(){ var allChildren=scene.children; var lastChild=allChildren[allChildren.length-1]; if(lastChild instanceof THREE.Mesh){ scene.remove(lastChild); this.numberofObject=scene.children.length; } }; }; var gui=new dat.GUI(); gui.add(controls,"rotationSpeed",0,0.5); gui.add(controls,"addCube"); gui.add(controls,"removeCube"); gui.add(controls,"numberofObject").listen();; function renderScene(){ scene.traverse(function (e) { if (e instanceof THREE.Mesh && e != plane) { e.rotation.x += controls.rotationSpeed; e.rotation.y += controls.rotationSpeed; e.rotation.z += controls.rotationSpeed; } }); requestAnimationFrame(renderScene); render.render(scene, camera); } //scene.fog=new THREE.Fog(0xffffff,0.015,100); renderScene(); } window.onload = init; </script> </body> </html>
1.2 點光源
點光源是一種單點發光,照射所有方向的光源,例如生活中的照明彈就屬於點光源,
因爲點光源是向全部方向發射光線,所以不會產生陰影,
它有顏色color,強度intensity,距離distance,位置position,是否可見visible等幾個屬性,
PointLight光源的distance屬性決定的是光線能夠照射多遠,值爲0時,表示光線的亮度不會隨着距離的增長而遞減
其中左圖爲強度較小的狀況,右圖爲強度較大的狀況
var pointColor = "#ccffcc"; var pointLight = new THREE.PointLight(pointColor); pointLight.distance = 100;//距離,決定了光線能夠照射多遠 pointLight.intensity = 1;//強度 scene.add(pointLight);
1.3 聚光燈光源
SpotLight聚光燈光源有一種錐形的效果,例如平常生活中的手電筒,燈籠等,該光源具備下面的屬性
var pointColor = "#ffffff"; var spotLight = new THREE.SpotLight(pointColor); spotLight.position.set(-40, 60, -10); spotLight.castShadow = true; spotLight.shadowCameraNear = 2; spotLight.shadowCameraFar = 200; spotLight.shadowCameraFov = 30; spotLight.target = plane; /*設置聚光燈光源的target屬性,爲3D空間的一個點,target屬性的值爲Object3D var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); spotLight.target = target; */ spotLight.distance = 0; spotLight.angle = 0.4; scene.add(spotLight);
屬性 | 描述 |
castShadow(投影) | 設置爲true,則該光源能夠產生陰影 |
shadowCameraNear | 從距離光源的哪一點開始生成陰影 |
shadowCameraFar | 從距離光源哪一點開始中止生成陰影 |
shadowCameraFov | 造成陰影的視場 |
target | 決定了光源的方向,若是target屬性的值出現移動的狀況,那麼光源也會跟着該target進行移動,該值必須爲Object3D類型,所以能夠是geom,也能夠是具體的某一個點,這個代碼中會有體現 |
angle | 光源照射出來的光柱有多寬 |
exponent | 光強衰減指數,距離光源越遠,光照強度越弱,可是減弱的速度是由該值控制 |
shadowCameraVisible | 經過設置此值,能夠看到光源在哪裏,以及如何產生陰影,即該值主要用於調試 |
shadowDarkness | 陰影強度,即陰影有多黑,場景渲染後該值不能夠再修改了 |
shadowMapWidth | 多少像素用來生成陰影,若是陰影的邊緣看起來不夠光滑良莠不齊,那麼能夠考慮加大該值,該值同shadowDarkness,場景渲染後不可修改 |
distance | 距離target的距離 |
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="dat.gui.js"></script> <script type="text/javascript" src="AsciiEffect.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //var scene function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影 //生成一個座標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一塊兒,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); /*var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//須要陰影,方塊進行投射陰影*/ //聚光燈光源 /**/var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(0,20,0);
spotLight.castShadow=true;
spotLight.target=plane;//光源照射的方向
spotLight.angle=Math.PI/3;//光源的角度
spotLight.shadowCameraNear=2;
spotLight.shadowCameraFar=20;
spotLight.shadowCameraVisible=true;
scene.add(spotLight); //環境光 /*var ambientLight=new THREE.AmbientLight("#0c0c0c"); scene.add(ambientLight);*/ //點光源 /* var pointLight=new THREE.PointLight(0xffffff); pointLight.position.set(0,10,10); pointLight.distance=100; pointLight.castShadow=true; pointLight.intensity=3; scene.add(pointLight);*/ var lightGeometry=new THREE.BoxGeometry(4,4,4); var lightMaterial=new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}); var light=new THREE.Mesh(lightGeometry,lightMaterial); light.position.set(0,20,0); scene.add(light); //將相機,渲染器,座標軸,平面都追加到場景中,而後對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); //scene.add(cube); // //var effect=new THREE.AsciiEffect(render); ///effect.setSize(window.innerWidth,window.innerHeight); document.getElementById("WebGL-output").append(render.domElement); var controls=new function(){ this.rotationSpeed=0.02; this.numberofObject=scene.children.length; this.addCube=function(){ var cubeSize=Math.ceil(Math.random()*3); var cubeGeometry=new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize); var cubeMaterial=new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}); var cube=new THREE.Mesh(cubeGeometry,cubeMaterial); cube.castShadow=true; cube.name="cube-"+scene.children.length; cube.position.x=-30+Math.round(Math.random()*planeGeometry.parameters.width); cube.position.y=Math.round(Math.random()*5); cube.position.z=-20+Math.round(Math.random()*planeGeometry.parameters.height); scene.add(cube); this.numberofObject=scene.children.length; }; this.removeCube=function(){ var allChildren=scene.children; var lastChild=allChildren[allChildren.length-1]; if(lastChild instanceof THREE.Mesh){ scene.remove(lastChild); this.numberofObject=scene.children.length; } }; }; var gui=new dat.GUI(); gui.add(controls,"rotationSpeed",0,0.5); gui.add(controls,"addCube"); gui.add(controls,"removeCube"); gui.add(controls,"numberofObject").listen();; function renderScene(){ requestAnimationFrame(renderScene); render.render(scene, camera); } //scene.fog=new THREE.Fog(0xffffff,0.015,100); renderScene(); } window.onload = init; </script> </body> </html>
1.4 DirectinalLight---方向光光源(相似於太陽光的一種光源)
該光源能夠看作是距離很遠很遠的光源,以致於該光源所發出的全部光線都是相互平行的,
方向光光源的一個範例就是太陽,方向光光源不像聚焦光那樣離目標越遠越暗淡,被方向光光源照亮的整個區域接收到的光強是同樣的
方向光光源的shadowCameraNear,far,left,right,top,bottom六個屬性構成了一個方塊的範圍,
在這個方塊的範圍內的全部對象均可以投影或者接收投影,包圍對象的方塊範圍定義的越緊密,投影的效果越好
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="dat.gui.js"></script> <script type="text/javascript" src="AsciiEffect.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //var scene function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影 //生成一個座標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一塊兒,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); /*var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//須要陰影,方塊進行投射陰影*/ //聚光燈光源 /*var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(0,20,0); spotLight.castShadow=true; spotLight.target=plane;//光源照射的方向 spotLight.angle=Math.PI/3;//光源的角度 spotLight.shadowCameraNear=2; spotLight.shadowCameraFar=20; spotLight.shadowCameraVisible=true; scene.add(spotLight);*/ //環境光 /*var ambientLight=new THREE.AmbientLight("#0c0c0c"); scene.add(ambientLight);*/ //點光源 /* var pointLight=new THREE.PointLight(0xffffff); pointLight.position.set(0,10,10); pointLight.distance=100; pointLight.castShadow=true; pointLight.intensity=3; scene.add(pointLight);*/ /*方向光光源*/ var pointColor = "white"; var directionalLight = new THREE.DirectionalLight(pointColor); directionalLight.position.set(0,10,0); directionalLight.castShadow = true; directionalLight.shadowCameraNear =6; directionalLight.shadowCameraFar =10; directionalLight.shadowCameraLeft =-5; //directionalLight.shadowCameraLeft = 10; directionalLight.shadowCameraRight =5; directionalLight.shadowCameraTop =5; directionalLight.shadowCameraBottom =-5; directionalLight.shadowCameraVisible=true; //directionalLight.distance = 5; directionalLight.target=plane; directionalLight.intensity = 0.5; //directionalLight.shadowMapHeight = 1024; //directionalLight.shadowMapWidth = 1024; scene.add(directionalLight); var lightGeometry=new THREE.BoxGeometry(1,1,1); var lightMaterial=new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}); var light=new THREE.Mesh(lightGeometry,lightMaterial); light.position.set(0,10,0); scene.add(light); //將相機,渲染器,座標軸,平面都追加到場景中,而後對場景和相機進行渲染 scene.add(camera); scene.add(render); //scene.add(axes); scene.add(plane); //scene.add(cube); // //var effect=new THREE.AsciiEffect(render); ///effect.setSize(window.innerWidth,window.innerHeight); document.getElementById("WebGL-output").append(render.domElement); var controls=new function(){ this.rotationSpeed=0.02; this.numberofObject=scene.children.length; this.addCube=function(){ var cubeSize=Math.ceil(Math.random()*3); var cubeGeometry=new THREE.BoxGeometry(cubeSize,cubeSize,cubeSize); var cubeMaterial=new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}); var cube=new THREE.Mesh(cubeGeometry,cubeMaterial); cube.castShadow=true; cube.name="cube-"+scene.children.length; cube.position.x=-30+Math.round(Math.random()*planeGeometry.parameters.width); cube.position.y=Math.round(Math.random()*5); cube.position.z=-20+Math.round(Math.random()*planeGeometry.parameters.height); scene.add(cube); this.numberofObject=scene.children.length; }; this.removeCube=function(){ var allChildren=scene.children; var lastChild=allChildren[allChildren.length-1]; if(lastChild instanceof THREE.Mesh){ scene.remove(lastChild); this.numberofObject=scene.children.length; } }; }; var gui=new dat.GUI(); gui.add(controls,"rotationSpeed",0,0.5); gui.add(controls,"addCube"); gui.add(controls,"removeCube"); gui.add(controls,"numberofObject").listen();; function renderScene(){ requestAnimationFrame(renderScene); render.render(scene, camera); } //scene.fog=new THREE.Fog(0xffffff,0.015,100); renderScene(); } window.onload = init; </script> </body> </html>
1.5 半球光源----HemisphereLight
這種光源能夠爲室外場景建立更加天然的光照效果
咱們模擬室外光照的時候,可使用方向光源來模擬太陽,再添加一個環境光源,爲場景添加基礎色
可是這樣看起來不太天然,由於室外的光並不都是來自於上方,不少是來自於空氣的散射和地面的反射,以及其餘物體的反射
因此在使用方向光源來模擬太陽的狀況下再添加一個半球光就天然多了
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="dat.gui.js"></script> <script type="text/javascript" src="AsciiEffect.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> //var scene function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); scene.add(camera); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true; //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影 scene.add(render); //生成一個地面的平面,該地面的材質再也不只是顏色,而是一個圖片 var textureGrass = THREE.ImageUtils.loadTexture("grasslight-big.jpg"); textureGrass.wrapS = THREE.RepeatWrapping; textureGrass.wrapT = THREE.RepeatWrapping; textureGrass.repeat.set(4, 4); var planeGeometry = new THREE.PlaneGeometry(1000, 200, 20, 20); var planeMaterial = new THREE.MeshLambertMaterial({map: textureGrass}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; scene.add(plane); //生成一個方塊 var cubeGeometry=new THREE.BoxGeometry(10,10,10); var cubeMaterial=new THREE.MeshLambertMaterial({color:"red"}); var cube=new THREE.Mesh(cubeGeometry,cubeMaterial); cube.castShadow=true; cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; scene.add(cube); //生成半球光源 var hemiLight=new THREE.HemisphereLight(0x0000ff,0x00ff00,0.6); hemiLight.position.set(0,500,0); hemiLight.groundColor = new THREE.Color(0x00ff00);//設置地面發出的光線的顏色 hemiLight.color = new THREE.Color(0x0000ff);//設置天空發出的光線的顏色 hemiLight.intensity = 0.6; scene.add(hemiLight); //生成聚光燈 var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.lookAt(plane); scene.add(spotLight0); //生成一個方向光,模擬太陽光 var pointColor = "#ffffff"; var dirLight = new THREE.DirectionalLight(pointColor); dirLight.position.set(0, 10, 0); dirLight.castShadow = true; dirLight.target = plane; dirLight.shadowCameraNear = 0.1; dirLight.shadowCameraFar = 200; dirLight.shadowCameraLeft = -50; dirLight.shadowCameraRight = 50; dirLight.shadowCameraTop = 50; dirLight.shadowCameraBottom = -50; dirLight.shadowMapWidth = 2048; dirLight.shadowMapHeight = 2048; scene.add(dirLight); document.getElementById("WebGL-output").append(render.domElement); function renderScene(){ requestAnimationFrame(renderScene); render.render(scene, camera); } scene.fog=new THREE.Fog(0xffffff,0.015,100); renderScene(); } window.onload = init; </script> </body> </html>
1.6 平面光光源------AreaLight
平面光光源能夠定義爲一個發光的矩形
1 因爲該光源是THREE.js的擴展,須要引入擴展庫
2 平面光源是一種很複雜的光源,所以不能再使用WebGLRenderer對象了,該對象會形成嚴重的性能損失
3 所以在處理複雜光源或者多個光源的時候,使用WebGL的延遲渲染器WebGLDeferredRenderer
<!DOCTYPE html> <html> <head> <title>Example 03.06 - Area Light</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <script type="text/javascript" src="../libs/WebGLDeferredRenderer.js"></script> <script type="text/javascript" src="../libs/ShaderDeferred.js"></script> <script type="text/javascript" src="../libs/RenderPass.js"></script> <script type="text/javascript" src="../libs/EffectComposer.js"></script> <script type="text/javascript" src="../libs/CopyShader.js"></script> <script type="text/javascript" src="../libs/ShaderPass.js"></script> <script type="text/javascript" src="../libs/FXAAShader.js"></script> <script type="text/javascript" src="../libs/MaskPass.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> var camera; // once everything is loaded, we run our Three.js stuff. function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create a camera, which defines where we're looking at. camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); scene.add(camera); // create a render and set the size // var renderer = new THREE.WebGLRenderer(); var renderer = new THREE.WebGLDeferredRenderer({ width: window.innerWidth, height: window.innerHeight, scale: 1, antialias: true, tonemapping: THREE.FilmicOperator, brightness: 2.5 }); // renderer.setSize(window.innerWidth, window.innerHeight); // renderer.shadowMapEnabled = true; // create the ground plane var planeGeometry = new THREE.PlaneGeometry(70, 70, 1, 1); var planeMaterial = new THREE.MeshPhongMaterial({color: 0xffffff, specular: 0xffffff, shininess: 200}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); // plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 0; plane.position.y = 0; plane.position.z = 0; // add the plane to the scene scene.add(plane); // position and point the camera to the center of the scene camera.position.x = 20; camera.position.y = 30; camera.position.z = 21; camera.lookAt(new THREE.Vector3(0, 0, -30)); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(renderer.domElement); // call the render function var step = 0; var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.intensity = 0.1; spotLight0.lookAt(plane); scene.add(spotLight0); var areaLight1 = new THREE.AreaLight(0xff0000, 3);// color和instensity areaLight1.position.set(-10, 10, -35); areaLight1.rotation.set(-Math.PI / 2, 0, 0); areaLight1.width = 4; areaLight1.height = 9.9; scene.add(areaLight1); var areaLight2 = new THREE.AreaLight(0x00ff00, 3); areaLight2.position.set(0, 10, -35); areaLight2.rotation.set(-Math.PI / 2, 0, 0); areaLight2.width = 4; areaLight2.height = 9.9; scene.add(areaLight2); var areaLight3 = new THREE.AreaLight(0x0000ff, 3); areaLight3.position.set(10, 10, -35); areaLight3.rotation.set(-Math.PI / 2, 0, 0); areaLight3.width = 4; areaLight3.height = 9.9; scene.add(areaLight3); var planeGeometry1 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry1Mat = new THREE.MeshBasicMaterial({color: 0xff0000}); var plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat); plane1.position.copy(areaLight1.position); scene.add(plane1); var planeGeometry2 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry2Mat = new THREE.MeshBasicMaterial({color: 0x00ff00}); var plane2 = new THREE.Mesh(planeGeometry2, planeGeometry2Mat); plane2.position.copy(areaLight2.position); scene.add(plane2); var planeGeometry3 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry3Mat = new THREE.MeshBasicMaterial({color: 0x0000ff}); var plane3 = new THREE.Mesh(planeGeometry3, planeGeometry3Mat); plane3.position.copy(areaLight3.position); scene.add(plane3); var controls = new function () { this.rotationSpeed = 0.02; this.color1 = 0xff0000; this.intensity1 = 2; this.color2 = 0x00ff00; this.intensity2 = 2; this.color3 = 0x0000ff; this.intensity3 = 2; }; var gui = new dat.GUI(); gui.addColor(controls, 'color1').onChange(function (e) { areaLight1.color = new THREE.Color(e); planeGeometry1Mat.color = new THREE.Color(e); scene.remove(plane1); plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat); plane1.position.copy(areaLight1.position); scene.add(plane1); }); gui.add(controls, 'intensity1', 0, 5).onChange(function (e) { areaLight1.intensity = e; }); gui.addColor(controls, 'color2').onChange(function (e) { areaLight2.color = new THREE.Color(e); planeGeometry2Mat.color = new THREE.Color(e); scene.remove(plane2); plane2 = new THREE.Mesh(planeGeometry2, planeGeometry2Mat); plane2.position.copy(areaLight2.position); scene.add(plane2); }); gui.add(controls, 'intensity2', 0, 5).onChange(function (e) { areaLight2.intensity = e; }); gui.addColor(controls, 'color3').onChange(function (e) { areaLight3.color = new THREE.Color(e); planeGeometry3Mat.color = new THREE.Color(e); scene.remove(plane3); plane3 = new THREE.Mesh(planeGeometry1, planeGeometry3Mat); plane3.position.copy(areaLight3.position); scene.add(plane3); }); gui.add(controls, 'intensity3', 0, 5).onChange(function (e) { areaLight3.intensity = e; }); render(); function render() { stats.update(); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } } window.onload = init; </script> </body> </html>
1.7 鏡頭眩光----LensFlare
當咱們直接朝着太陽拍照時就會出現鏡頭眩光,對於遊戲或者三維圖像來講,鏡頭眩光會使得場景看起來更真實
<!DOCTYPE html> <html> <head> <title>Example 03.07 - Lensflarest</title> <script type="text/javascript" src="../libs/three.js"></script> <script type="text/javascript" src="../libs/stats.js"></script> <script type="text/javascript" src="../libs/dat.gui.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <div id="Stats-output"> </div> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> // once everything is loaded, we run our Three.js stuff. function init() { var stats = initStats(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); scene.fog = new THREE.Fog(0xaaaaaa, 0.010, 200); // create a camera, which defines where we're looking at. var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // create a render and set the size var renderer = new THREE.WebGLRenderer({antialias: true, alpha: true}); renderer.setClearColor(new THREE.Color(0xaaaaff, 1.0)); renderer.setSize(window.innerWidth, window.innerHeight); renderer.shadowMapEnabled = true; // 生成一個平面的地面 var textureGrass = THREE.ImageUtils.loadTexture("grasslight-big.jpg"); textureGrass.wrapS = THREE.RepeatWrapping; textureGrass.wrapT = THREE.RepeatWrapping; textureGrass.repeat.set(4, 4); var planeGeometry = new THREE.PlaneGeometry(1000, 200, 20, 20); var planeMaterial = new THREE.MeshLambertMaterial({map: textureGrass}); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; // add the plane to the scene scene.add(plane); // create a cube var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff3333}); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // position the cube cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; // add the cube to the scene scene.add(cube); var sphereGeometry = new THREE.SphereGeometry(4, 25, 25); var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff}); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // position the sphere sphere.position.x = 10; sphere.position.y = 5; sphere.position.z = 10; sphere.castShadow = true; // add the sphere to the scene scene.add(sphere); // position and point the camera to the center of the scene camera.position.x = -20; camera.position.y = 15; camera.position.z = 45; camera.lookAt(new THREE.Vector3(10, 0, 0)); // 增長環境光,弱化陰影,使得場景看起來更真實 var ambiColor = "#1c1c1c"; var ambientLight = new THREE.AmbientLight(ambiColor); scene.add(ambientLight); // 增長聚光燈,爲場景增長亮度 var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.lookAt(plane); scene.add(spotLight0); var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); var pointColor = "#ffffff"; // 增長方向光光源,模擬太陽 var spotLight = new THREE.DirectionalLight(pointColor); spotLight.position.set(30, 10, -50); spotLight.castShadow = true; spotLight.shadowCameraNear = 0.1; spotLight.shadowCameraFar = 100; spotLight.shadowCameraFov = 50; spotLight.target = plane; spotLight.distance = 0; spotLight.shadowCameraNear = 2; spotLight.shadowCameraFar = 200; spotLight.shadowCameraLeft = -100; spotLight.shadowCameraRight = 100; spotLight.shadowCameraTop = 100; spotLight.shadowCameraBottom = -100; spotLight.shadowMapWidth = 2048; spotLight.shadowMapHeight = 2048; scene.add(spotLight); // add the output of the renderer to the html element document.getElementById("WebGL-output").appendChild(renderer.domElement); // call the render function var step = 0; // used to determine the switch point for the light animation var invert = 1; var phase = 0; var controls = new function () { this.rotationSpeed = 0.03; this.bouncingSpeed = 0.03; this.ambientColor = ambiColor; this.pointColor = pointColor; this.intensity = 0.1; this.distance = 0; this.exponent = 30; this.angle = 0.1; this.debug = false; this.castShadow = true; this.onlyShadow = false; this.target = "Plane"; }; var gui = new dat.GUI(); gui.addColor(controls, 'ambientColor').onChange(function (e) { ambientLight.color = new THREE.Color(e); }); gui.addColor(controls, 'pointColor').onChange(function (e) { spotLight.color = new THREE.Color(e); }); gui.add(controls, 'intensity', 0, 5).onChange(function (e) { spotLight.intensity = e; }); var textureFlare0 = THREE.ImageUtils.loadTexture("lensflare0.png"); var textureFlare3 = THREE.ImageUtils.loadTexture("lensflare3.png"); var flareColor = new THREE.Color(0xffaacc); /*參數1:紋理,眩光的材質 參數2:尺寸,眩光的大小,-1的話就是使用材質自己大小 參數3:距離,光源(0)到相機(1)的距離 參數4:融合,//當眩光有多種材質的時候,這些材質如何融合在一塊兒 參數5:顏色,眩光的顏色*/ var lensFlare = new THREE.LensFlare(textureFlare0, 350, 0.0, THREE.AdditiveBlending, flareColor); lensFlare.add(textureFlare3, 60, 0.6, THREE.AdditiveBlending); lensFlare.add(textureFlare3, 70, 0.7, THREE.AdditiveBlending); lensFlare.add(textureFlare3, 120, 0.9, THREE.AdditiveBlending); lensFlare.add(textureFlare3, 70, 1.0, THREE.AdditiveBlending); lensFlare.position.copy(spotLight.position); scene.add(lensFlare); render(); function render() { stats.update(); // rotate the cube around its axes cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; // bounce the sphere up and down step += controls.bouncingSpeed; sphere.position.x = 20 + ( 10 * (Math.cos(step))); sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step))); requestAnimationFrame(render); renderer.render(scene, camera); } function initStats() { var stats = new Stats(); stats.setMode(0); // 0: fps, 1: ms // Align top-left stats.domElement.style.position = 'absolute'; stats.domElement.style.left = '0px'; stats.domElement.style.top = '0px'; document.getElementById("Stats-output").appendChild(stats.domElement); return stats; } }; window.onload = init; </script> </body> </html>
總結
環境光源沒有位置概念,會將顏色應用到場景的每個物體上,主要做用是弱化陰影,給場景添加顏色
點光源相似於照明彈,朝全部的方向發光,所以不產生陰影
聚光燈光源相似於手電筒,造成錐形的光束,隨着距離的增長而變弱,能夠設定生成陰影
方向光光源相似於太陽,從很遠的地方發出的平行光束,距離越遠,衰減的越多
想要一個天然的室外效果,除了添加環境光弱化陰影,添加聚光燈爲場景增長光線,還須要使用半球光光源將天空和空氣以及地面的散射計算進去,使得更天然,更真實
平面光光源定義了一個發光的發光體,須要使用webgl的延遲渲染機制
眩光效果,在有太陽的時候使用眩光光源,會使得場景更真實