使用three.js裏的各種光源

本章的主要內容

  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的延遲渲染機制

眩光效果,在有太陽的時候使用眩光光源,會使得場景更真實

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章