本章的主要内容
1 three.js有哪些可用的光源
2 什么时候用什么光源、
3 如何调整配置各种光源
4 如何创建镜头炫光
一 光源
光源大概有7种,
其中基础光源有4种
环境光(AmbientLight会它的颜色会添加到整个场景和所有对象的当前颜色上),
点光源(PointLight空间中的一点,朝所有的方向发射光线),
聚光灯光源(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的延迟渲染机制
眩光效果,在有太阳的时候使用眩光光源,会使得场景更真实
相关推荐
Three.js开发指南电子版,让你更好的学习理解threejs,Three.js开发指南电子版,让你更好的学习理解threejs
《Three.js开发指南》是针对WebGL库Three.js的一本详尽教程,旨在帮助开发者深入理解和运用这个强大的3D图形库。Three.js是JavaScript的一个开源项目,它为Web浏览器提供了简单易用的接口,用于创建复杂的3D场景、...
three.js开发指南源码: 首部全面讲解Three.js开发的实用指南,循序渐进讲解Three.js的各种功能,通过大量交互示例,深入探索使用开源的Three.js库创建绚丽三维图形的实用方法和技巧。 在过去的两年里,浏览器变得...
《Three.js开发指南》共12章:第1章讲述使用Three.js库的基本步骤;第2章讲解Three.js库使用过程中所要了解的各种基础组件,包括光源、网格、几何体、材质和相机等;第3章通过具体示例讲解场景中使用的各种光源;第4...
《three.js开发必备》资源包含了三个关键组成部分:THREE.JS开发指南的PDF文档和多个版本的three.min.js库。这个资源对于想要深入理解和实践three.js的开发者来说是极其宝贵的。 首先,我们来探讨THREE.JS开发指南...
3. **几何体与形状**:three.js支持多种几何体,如立方体、球体、平面等,开发者可以通过调整参数来创建不同形状的对象。 4. **材质与纹理**:书中会详细介绍各种材质类型,如颜色材质、金属材质、多材质等,以及...
**标题解析:**"three.js开发指南及其示例源码(中文版)" 这个标题表明这是一个关于three.js的中文学习资源,它包含了开发指南和实际的示例源代码。three.js是一个基于WebGL的JavaScript库,用于在浏览器中创建3D...
本书共12章,涉及以下内容:使用Three.js创建三维场景,构建场景的基本组件,Three.js中的光源、材质、几何体以及粒子、精灵和点云,创建和加载网格、几何体,创建动画和移动摄像机,加载和使用纹理,自定义着色器和...
第 1 章介绍 Three.js 和 WebGL 的背景资料,并通过简单的例子帮助读者实现第一个Three.js 应用。 第 2 章介绍照相机的设定。 第 3、4、5 章分别介绍几何形状、材质和网格,即如何在场景中添加物体。 第 6 章介绍...
这个"Three.js 开发指南源码-3"很可能是针对 Three.js 的一系列教程或示例代码的第三部分,旨在帮助开发者更深入地理解和掌握 Three.js 的使用。在这里,我们将深入探讨 Three.js 的基础知识,特别是与 "textures" ...
《THREE.JS开发指南》是一本专注于介绍WebGL库Three.js的专业书籍,旨在帮助开发者深入理解和高效使用这个强大的3D图形库。Three.js是JavaScript的一个框架,它为WebGL提供了一个简单易用的接口,使得在网页上创建...
**Three.js 开发包第123版** Three.js 是一款强大的JavaScript库,它使得WebGL(Web图形库)的使用变得简单易行,从而在网页上实现3D图形的渲染。WebGL是一种基于OpenGL标准的JavaScript API,允许在浏览器中进行...
第3章 使用Three.js里的各种光源 3.1 探索Three.js库提供的光源 3.2 学习基础光源 3.3 总结 第4章 使用Three.js的材质 4.1 理解共有属性 4.2 从简单的网格材质(基础、深度和面)开始 4.3 学习高级材质 4.4 ...
首部全面讲解Three.js开发的实用指南,循序渐进讲解Three.js的各种功能,通过大量交互示例,深入探索使用开源的Three.js库创建绚丽三维图形的实用方法和技巧。 在过去的两年里,浏览器变得更加强大了,而且能够作为...
《three.js开发指南 第2版源码》是一个与WebGL相关的资源包,专注于three.js库的深入学习和实践。three.js是JavaScript中最受欢迎的3D图形库,它为WebGL提供了一个高级接口,使得在浏览器中创建交互式3D场景变得容易...
THREE.JS开发指南。Three.js是一款开源的主流3D绘图JS引擎。
- **第 1 章**:介绍 Three.js 和 WebGL 的背景知识,并引导读者实现首个 Three.js 应用。 - **重点**:Three.js 的基本原理与安装配置,以及 WebGL 的基础知识。 - **实践**:通过一个简单的示例来演示如何初始化...
《Three.js开发指南》是一本深入探讨WebGL库Three.js的专业书籍,其配套代码提供了丰富的实践案例和示例,帮助读者更好地理解和应用three.js进行3D网页开发。Three.js是JavaScript的一个库,它封装了复杂的WebGL接口...
首部全面讲解Three.js开发的实用指南,循序渐进讲解Three.js的各种功能,通过大量交互示例,深入探索使用开源的Three.js库创建绚丽三维图形的实用方法和技巧。, 在过去的两年里,浏览器变得更加强大了,而且能够作为...
- **第3、4、5章**:详细介绍如何创建和操作几何体、材质以及网格对象,包括基本几何体的生成、材质属性的调整等。 - **第6章**:讲解动画制作的基本原理和技巧,例如关键帧动画和物理引擎的集成。 - **第7章**:...