Three.js開發指南---使用three.js的材質(第四章)

 

材質就像物體的皮膚,決定了幾何體的外表,例如是否像草地/金屬,是否透明,是否顯示線框等javascript

一 材質html

  THREE.js的材質分爲多種,Three.js提供了一個材質基類THREE.Material,java

  該基類擁有three.js全部材質的公有屬性,分爲三類:基礎屬性,融合屬性,高級屬性web

  基礎屬性:ID,name,透明度,是否可見,是否須要刷新等算法

  融合屬性:決定了物體如何與背景融合canvas

  高級屬性:能夠控制WEBGL上下文渲染物體的方法,大多數狀況下,是不會用這些屬性,咱們這裏再也不討論數組

   1.1 基礎屬性緩存

屬性 描述
ID(描述符) 用來標識材質,在建立時賦值
name(名稱) 經過該屬性克賦予該材質名稱
opacity(透明度) 定義物體有多透明,與transparent屬性一塊兒使用
transparent(是否透明) 設置爲true時,會根據opacity的值來設置透明度,設置爲false時,則只着色
overdraw(過分描繪) 當使用THREE.CanvasRenderer畫布渲染器繪製對象的時候,物體之間可能會有空隙,這時設置該值爲true,多邊形會被渲染的稍微大一點,
visible(是否可見) 定義該材質是否可見
side(側面)

決定了幾何體的哪一面應用該材質,app

THREE.FrontSide應用到幾何體的前(外)面;dom

THREE.BackSide應用到幾何體的後(內)面;

THREE.DoubleSide應用到幾何體的內外兩側

needUpdate(是否刷新) 設置該值爲true後,若是材質發生改變,就會使用新的材質刷新它的緩存

  

 

 

  1.2 融合屬性

屬性 描述  
blending(融合) 決定物體上的材質如何跟背景融合,通常是NormalBlending,這種模式通常只顯示材質的上層  
blendsrc(融合源)

經過指定融合源,融合目標來指定源如何跟目標融合以及融合時如何使用目標,以達到建立自定義的融合模式

融合源的默認值SrcAlphaFactor:使用alpha透明度通道進行融合

融合目標的默認值OneMinusSrcAlphaFactor:融合目標也使用融合源的alpha通道進行融合

blendingequation只讀blendsrc和blenddst的值的疊加方式建立自定義的融合方式

 
blenddst(融合目標)  
blendingequation(融合公式)  

  1.3 基礎材質(MeshBasicMaterial)

     MeshBasicMaterial是一種簡單的材質,這種材質不考慮光照的影響。

    使用這種材質的網格會被渲染成一些簡單的平面多邊形,並且能夠經過設置wireframe的值會顯示幾何體的線框

屬性 描述
color 設置材質的顏色
wireframe 是否將材質渲染成線框
wireframeLinewidth 若是設置了wireframe的值,則該屬性則設置了線框的寬度,即線框的寬度
wireframeLinecap(線框的端點)

該屬性定義了線框模式下端點的顯示方式,有butt平,round圓,square方,

可是在實際的應用中,該值很難看出效果,並且webglrenderer不支持該屬性

wireframeLinejoin(線框線段鏈接點)  定義線段的鏈接點如何顯示,webglrenderer不支持該屬性
 shading(着色方式)

 THREE.SmoothShading平滑着色,和THREE.FlatShading平面着色,

平面着色的話,每一個面是什麼顏色就會被渲染成什麼顏色,

而平滑着色的話可使物體的表面看起來變的更光滑一些

 vertexColors(頂點顏色) 能夠經過該屬性爲每個頂點定義不一樣的顏色,可是canvasRenderer不支持
 fog(霧化) 當前材質是否會受全局霧化效果的影響
side(面)

該屬性能夠指定幾何體的哪一個面應用了材質,

因爲材質多應用於物體前面的面上,

因此當旋轉的時候,會有一部分時間是不可見的(實際上是物體背面沒有應用材質)

side屬性的值有front(只有物體的前面應用材質)和double(先後都應用材質)

 

 

 

 

<!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="CanvasRenderer.js"></script>
    <script type="text/javascript" src="Projector.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;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
        //生成一個canvas的渲染器,渲染器有什麼不一樣?
        var canvasRender=new THREE.CanvasRenderer();
        canvasRender.setSize(window.innerWidth,window.innerHeight);
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        //scene.add(canvasRender);
        
        
        //生成基本材質,並將該材質應用於下面中的球體,方塊或者平面
        var material=new THREE.MeshBasicMaterial({color: 0x77777ff});
        
        material.needsUpdate=true;
        
        //生成一個地面平面,並添加到場景中
        //參數:長,寬,長分爲多少份,寬分爲多少份
        var groundGeometry = new THREE.PlaneGeometry(100, 200, 20, 20);
        var groundMaterial = new THREE.MeshBasicMaterial({color: 0x777777});
        var ground = new THREE.Mesh(groundGeometry, groundMaterial);
        ground.receiveShadow = true;
        ground.rotation.x = -0.5 * Math.PI;
        scene.add(ground);
        
        //生成一個方塊,並添加到場景中
        var cubeGeometry=new THREE.BoxGeometry(10,10,10);
        var cube=new THREE.Mesh(cubeGeometry,material);
        cube.castShadow=true;
        cube.position.set(0,3,2);
        scene.add(cube);
        
        //生成一個圓球,暫時不添加到場景,使用圖形界面選擇物體        
        var sphereGeometry=new THREE.SphereGeometry(10,10,10);
        var sphere=new THREE.Mesh(sphereGeometry,material);
        sphere.castShadow=true;
        sphere.position.set(0,3,2);
        //scene.add(sphere);
        //生成一個平面,暫時不添加到場景,使用圖形界面選擇物體        
        var planeGeometry=new THREE.PlaneGeometry(10,10,10);
        var plane=new THREE.Mesh(planeGeometry,material);
        plane.position.set(0,3,2);
        
        //生成環境光,弱化陰影
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);
        
        
        //生成聚光燈
        var spotLight0 = new THREE.SpotLight(0xffffff);
        spotLight0.position.set(-40, 60, -10);
        spotLight0.castShadow=true;
        scene.add(spotLight0);
        
        //增長圖形控制界面
        var controls=new function(){
            this.rotationSpeed=0.02;
            this.opacity=material.opacity;//透明度
            this.transparent=material.transparent;
            this.visible=material.visible;
            
            this.wireframe=material.wireframe;
            this.shading=material.shading;
            this.wireframeLineWidth=material.wireframeLineWidth;
            this.selectedMesh = "矩形";
            this.switchRender=function(){
                if(render instanceof THREE.WebGLRenderer){
                    render=canvasRender;
                }else{
                    render=webGLrender;
                }
                document.getElementById("WebGL-output").innerHTML='';
                document.getElementById("WebGL-output").appendChild(render.domElement);
            }
            this.color=material.color.getStyle();
        };
        
        var gui=new dat.GUI();
        //上面controls裏面的opacity必須與下面的一致
        var childGui=gui.addFolder("材質的共有屬性");
        childGui.add(controls,"opacity",0,1).onChange(function(e){
            material.opacity=e;
        });
        //注意,當opacity設置的值不爲1時,以opacity爲主
        childGui.add(controls,"transparent").onChange(function(e){
            material.transparent=e;
        });
        childGui.add(controls,"wireframe").onChange(function(e){
            material.wireframe=e;
        });
        //若是visible的值爲false,即不可見,無論opacity的值爲多少,物體都是不可見的
        childGui.add(controls,"visible").onChange(function(e){
            material.visible=e;
        });
        //addColor注意,增長顏色的圖形控制,須要使用addColor方法
        childGui.addColor(controls,"color").onChange(function(e){
            
            material.color.setStyle(e);
        });
        childGui.add(controls,"selectedMesh",["cube","sphere","plane"]).onChange(function(e){
            scene.remove(plane);
            scene.remove(cube);
            scene.remove(sphere);
            switch(e){
                case 'cube':
                    scene.add(cube);
                break;
                case 'sphere':
                    scene.add(sphere);
                break;
                case 'plane':
                    scene.add(plane);
                break;
            }
        });
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致,即上面代碼的switchRender必須與下面語句的switchRender保持一致
        gui.add(controls, 'switchRender');
        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.4 基於深度着色的材質------MeshDepthMaterial

    該種材質的外觀不是由光照或者材質屬性visible決定的,而是物體和相機的距離決定,

    所以使用這種材質很容易建立出逐漸消失的效果

    注意這個demo使用了場景的overrideMaterial屬性

 

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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();
        
        //這裏咱們使用場景的overrideMaterial屬性,即場景中的全部物體都應用這一種材質
 scene.overrideMaterial = new THREE.MeshDepthMaterial(); //生成一個相機
        //參數:視場,長寬比,近面,遠面
        var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,10,100);
        camera.position.x=-50;
        camera.position.y=40;
        camera.position.z=50;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
        
    
        //生成一個方塊,並添加到場景中
        var cubeGeometry=new THREE.BoxGeometry(10,10,10);
        var cube=new THREE.Mesh(cubeGeometry,new THREE.MeshLambertMaterial({"color":0xeeeeee}));
        cube.castShadow=true;
        cube.position.set(0,3,2);
        scene.add(cube);
        
        
        
        //增長圖形控制界面
        var controls=new function(){
            this.cameraNear=camera.near;
            this.cameraFar=camera.far;
            this.rotationSpeed=0.02;
            this.addCube=function(){
                var size=Math.random()*3+3;
                var cubeGeo=new THREE.BoxGeometry(4,4,10,10);
                var cube=new THREE.Mesh(cubeGeo,new THREE.MeshLambertMaterial({color:Math.random()*0xffffff}));
                cube.castShadow=true;
                cube.position.x = -60 + Math.round((Math.random() * 100));
                cube.position.y = Math.round((Math.random() * 10));
                cube.position.z = -100 + Math.round((Math.random() * 150));
                scene.add(cube);
            }
            
        };
        
        var gui=new dat.GUI();
        gui.add(controls,"cameraNear",0,50).onChange(function(e){
            camera.near=e;
        });
        gui.add(controls,"cameraFar",0,50).onChange(function(e){
            camera.far=e;
        });
        gui.add(controls,"rotationSpeed",0,0.3);
        gui.add(controls, 'addCube');
        
        for(var i=0;i<10;i++){
            controls.addCube();
        }
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致
        
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            scene.traverse(function(e){
                if(e instanceof THREE.Mesh){
                    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.5 聯合材質

    當一個幾何體應用多種材質的時候,使用的就不是THREE.Mesh來建立網格了,

    而是THREE.SceneUtil.createMultiMaterialObject方法

    另外須要注意的細節,咱們須要把MeshBasicMaterial材質的transparent值設置爲true,

    只有材質的transparent的值爲true,three.js纔會檢查該材質的blending屬性,進行融合操做

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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,10,100);
        camera.position.x=-50;
        camera.position.y=40;
        camera.position.z=50;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
        
        //增長圖形控制界面
        var controls=new function(){
            this.cameraNear=camera.near;
            this.cameraFar=camera.far;
            this.rotationSpeed=0.02;
            this.addCube=function(){
                var size=Math.random()*3+3;
                var cubeGeo=new THREE.BoxGeometry(4,4,10,10);
                var basicMaterial=new THREE.MeshBasicMaterial({
                    color: 0x00ff00,
                    transparent: true,//注意這裏必定要設置基礎材質的透明度爲true
 blending: THREE.MultiplyBlending //這裏的融合方式選擇的是MultiplyBlending
                    //即最終展現的顏色是前景顏色和背景的顏色相乘後獲得的
                });
                var depthMaterial=new THREE.MeshDepthMaterial();
                var cube=new THREE.SceneUtils.createMultiMaterialObject(cubeGeo,[basicMaterial,depthMaterial]); //cube.children[1].scale.set(0.99,0.99,0.99);
                cube.castShadow=true;
                cube.position.x = -60 + Math.round((Math.random() * 100));
                cube.position.y = Math.round((Math.random() * 10));
                cube.position.z = -100 + Math.round((Math.random() * 150));
                scene.add(cube);
            }
            
        };
        
        var gui=new dat.GUI();
        gui.add(controls,"cameraNear",0,50).onChange(function(e){
            camera.near=e;
        });
        gui.add(controls,"cameraFar",0,50).onChange(function(e){
            camera.far=e;
        });
        gui.add(controls,"rotationSpeed",0,0.3);
        gui.add(controls, 'addCube');
        
        for(var i=0;i<10;i++){
            controls.addCube();
        }
        
      
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            scene.traverse(function(e){
                if(e instanceof THREE.Mesh){
                    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.6 計算法向量顏色的材質------MeshNormalMaterial

    將該材質應用到幾何體對象的時候,幾何體對象的每一面的顏色都是從該面向外的法向量計算獲得的

    法向量決定了光反射的方向,在三維物體上映射材質時起輔助做用,還能夠在計算光照,陰影時提供信息,爲物體表面的像素上色

    法向量所指的方向決定每一個面從MeshNormalMaterial材質獲取的顏色

   //圓球每一個面的法向量都不一樣我能夠理解,可是法向量如何與顏色相聯繫在一塊兒,沒有搞明白

     下面的demo,設置transparent爲true,opacity爲0.5,咱們不只能夠看到計算法向顏色的材質,還能夠看到材質共有的屬性side的值front,back,both的效果

 

 

 

 

 

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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,10,100);
        camera.position.x=-50;
        camera.position.y=40;
        camera.position.z=50;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
         var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
        var sphereGeometry = new THREE.SphereGeometry(14, 20, 20);        
        var meshMaterial = new THREE.MeshNormalMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
         sphere.position.x = 0;
        sphere.position.y = 3;
        sphere.position.z = 2;
        for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) {
            var face = sphere.geometry.faces[f];
            f==0?console.log(face)&&console.log(sphere.geometry.vertices[face.a]):"";
            var centroid = new THREE.Vector3(0, 0, 0);
            centroid.add(sphere.geometry.vertices[face.a]);
            centroid.add(sphere.geometry.vertices[face.b]);
            centroid.add(sphere.geometry.vertices[face.c]);
            centroid.divideScalar(3);//這個函數沒有看明白是作什麼的

            var arrow = new THREE.ArrowHelper(
                    face.normal,//面的法向量
                    centroid,//該面的質心
                    2,
                    0x3333FF,//顏色
                    0.5,
                    0.5);
            sphere.add(arrow);
        }
        
        scene.add(sphere);
        
        
        //增長圖形控制界面
        var controls=new function(){
            this.opacity=1;
            this.transparent=false;
            this.rotationSpeed=0.02;
            this.side="front";
            
        };
        
        var gui=new dat.GUI();
        gui.add(controls,"opacity",0,1).onChange(function(e){
            meshMaterial.opacity=e;
        });
        gui.add(controls,"transparent").onChange(function (e) {
            meshMaterial.transparent = e
        });
        gui.add(controls,"rotationSpeed",0,0.3);
        gui.add(controls, 'side',["front","back","double"]).onChange(function(e){
            switch(e){
                case "front":
                    meshMaterial.side=THREE.FrontSide;
                break;
                case "back":
                    meshMaterial.side=THREE.BackSide;
                break;
                case "double":
                    meshMaterial.side=THREE.DoubleSide;
                break;
            }
            
        });
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致
        
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            scene.traverse(function(e){
                if(e instanceof THREE.Mesh){
                    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.7 爲幾何體的每一面都指定材質的材質----MeshFaceMaterial

    這種並非真正的材質,而更像一種材質容器,經過MeshFaceMaterial能夠爲幾何體的每個面都指定不一樣的材質

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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,10,100);
        camera.position.x=-50;
        camera.position.y=40;
        camera.position.z=50;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
         var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
        
        //生成一個有6個基礎材質的數組
        var materials=[]; materials.push(new THREE.MeshBasicMaterial({color:"red"})); materials.push(new THREE.MeshBasicMaterial({color:"blue"})); materials.push(new THREE.MeshBasicMaterial({color:"yellow"})); materials.push(new THREE.MeshBasicMaterial({color:"green"})); materials.push(new THREE.MeshBasicMaterial({color:"white"})); materials.push(new THREE.MeshBasicMaterial({color:"black"})); //這6個基礎材質的數組做爲參數傳遞給MeshFaceMaterial
        var faceMaterial=new THREE.MeshFaceMaterial(materials); //生成一個方塊應用faceMaterial,即爲每一個面指定一種材質
        var cubeGeom=new THREE.CubeGeometry(6,6,6);
        var cube=new THREE.Mesh(cubeGeom,faceMaterial);
        scene.add(cube);
        
        
        //增長圖形控制界面
        var controls=new function(){
            
            this.rotationSpeed=0.02;
            
        };
        
        var gui=new dat.GUI();
        
        gui.add(controls,"rotationSpeed",0,0.3);
        
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致
        
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            scene.traverse(function(e){
                if(e instanceof THREE.Mesh){
                    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>

 這裏的demo作了一個魔方

  1 一共須要生成27個方塊

  2 每一個方塊的每一個面都應用材質數組中材質,即每個小方塊的各個面顏色都不一樣

  3 方塊的長寬要比10小一些,留個空隙

  4 注意一下每一個方塊的position

  5 這些方塊追加到一個網格中,而後再將網格追加到場景中

  6 旋轉的時候,是這個網格在旋轉,而不是每一個單獨的旋轉

 

  

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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,10,100);
        camera.position.x=-50;
        camera.position.y=40;
        camera.position.z=50;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
         var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
        
        //生成一個有6個基礎材質的數組
        var materials=[],group=new THREE.Mesh();
        materials.push(new THREE.MeshBasicMaterial({color:"red"}));
        materials.push(new THREE.MeshBasicMaterial({color:"blue"}));
        materials.push(new THREE.MeshBasicMaterial({color:"yellow"}));
        materials.push(new THREE.MeshBasicMaterial({color:"green"}));
        materials.push(new THREE.MeshBasicMaterial({color:"white"}));
        materials.push(new THREE.MeshBasicMaterial({color:"black"}));
        //這6個基礎材質的數組做爲參數傳遞給MeshFaceMaterial
        var faceMaterial=new THREE.MeshFaceMaterial(materials);
        
        //生成27個方塊,每三個應用一種材質,即爲每一個面指定一種材質
        for(var x=0;x<3;x++){
            for(var y=0;y<3;y++){
                for(var z=0;z<3;z++){
                    var cubeGeom=new THREE.BoxGeometry(9,9,9,9);
                    var cube=new THREE.Mesh(cubeGeom,faceMaterial); cube.position.set(x*10-10,y*10,z*10-10); group.add(cube);
                }
            }
        }
        scene.add(group);
        
        
        //增長圖形控制界面
        var controls=new function(){
            
            this.rotationSpeed=0.02;
            
        };
        
        var gui=new dat.GUI();
        
        gui.add(controls,"rotationSpeed",0,0.3);
        
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致
        
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            group.rotation.x+=controls.rotationSpeed; group.rotation.y+=controls.rotationSpeed; group.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.8 高級材質

    1 MeshLambertMaterial:會對光源作出反應,能夠用來建立暗淡的材質

      MeshLambertMaterial材質的ambient(環境色)屬性:該材質的環境色,跟AmbientLight光源一塊兒使用,這個顏色會與AmbientLight光源的顏色相乘,該屬性的默認值是白色

      MeshLambertMaterial材質的emissive(發射色)屬性:該材質發射的顏色,它其實並非光源,而是一種純粹的,不受其餘光照影響的顏色,該屬性的默認值是黑色

 

<!DOCTYPE html>

<html>

<head>
    <title>1</title>
    <script type="text/javascript" src="three.js"></script>
    <script type="text/javascript" src="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 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,10,100);
        camera.position.x=-20;
        camera.position.y=30;
        camera.position.z=40;
        camera.lookAt(scene.position);
        scene.add(camera);
        
        var render;
        
        //生成一個webgl的渲染器
        var webGLrender=new THREE.WebGLRenderer();
        webGLrender.setClearColor(0xEEEEEE);
        webGLrender.setSize(window.innerWidth,window.innerHeight);
        webGLrender.shadowMapEnabled=true;
        //容許陰影映射,渲染陰影須要大量的資源,所以咱們須要告訴渲染器咱們須要陰影        
        render=webGLrender;
        
         var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
        var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 4, 4);
        var plane = new THREE.Mesh(planeGeometry, new THREE.MeshBasicMaterial({color: 0x555555}));
        plane.rotation.x=-Math.PI/2;
        plane.position.y=0;
        scene.add(plane);
        
        //生成一個有6個基礎材質的數組
        var cubeGeom=new THREE.BoxGeometry(10,10,10);
        var material=new THREE.MeshLambertMaterial({ color:0x7777ff }); var cube=new THREE.Mesh(cubeGeom,material);
        cube.position.x=0;
        cube.position.y=13;
        cube.position.z=2;
        scene.add(cube);
        
        //增長圖形控制界面
        var controls=new function(){
            this.ambient=material.ambient.getHex();
            this.emissive=material.emissive.getHex(); this.rotationSpeed=0.02;
            this.opacity=material.opacity;
            this.transparent=material.transparent;
            this.side="front";
            
        };
        
        var gui=new dat.GUI();
        
        gui.add(controls,"rotationSpeed",0,0.3);
        gui.add(controls,"opacity",0,1).onChange(function(e){
            material.opacity=e;
        });
        gui.add(controls,"transparent").onChange(function(e){
            material.transparent=e;
        });
        gui.add(controls,"side",["front","back","double"]).onChange(function(e){
            
            switch(e){
                case "front":
                    material.side=THREE.FrontSide;
                break;
                case "back":
                    material.side=THREE.BackSide;
                break;
                case "double":
                    material.side=THREE.DoubleSide;
                break;
            }
            material.needsUpdate=true;
        });
        //使用addColor方法,添加gui顏色選擇器
        gui.addColor(controls,"ambient").onChange(function(e){
            //顏色選擇器獲取到的是gbs,須要轉化THREE的color格式
 material.ambient=new THREE.Color(e);
        });
        gui.addColor(controls,"emissive").onChange(function(e){
            material.emissive=new THREE.Color(e);
        });
        
        //gui的一個參數是一個對象,該對象控制的屬性是add的函數的第二個參數
        //即controls的this.switchRender必須與下面的屬性一致
        
        document.getElementById("WebGL-output").append(render.domElement);
        
        
        
        
        function renderScene(){
            cube.rotation.x+=controls.rotationSpeed;
            cube.rotation.y+=controls.rotationSpeed;
            cube.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>

 

    2 MeshPhongMaterial:會對光源作出反應,能夠用來建立光亮的材質

名稱 描述
specular(鏡面)

該屬性指定該材質的光亮程度及其高光部分的顏色,

若是將它設置跟color的顏色相同,就會獲得一種相似於金屬的材質

若是設置成灰色,材質就會顯得更像塑料

shininess 該屬性指定高光部分的亮度,默認值是30

 

    

<!DOCTYPE html>

<html>

<head>
    <title>Example 04.06 - Mesh Lambert material</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/CanvasRenderer.js"></script>
    <script type="text/javascript" src="../libs/Projector.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();

        // 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;
        var webGLRenderer = new THREE.WebGLRenderer();
        webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        webGLRenderer.shadowMapEnabled = true;

        var canvasRenderer = new THREE.CanvasRenderer();
        canvasRenderer.setSize(window.innerWidth, window.innerHeight);
        renderer = webGLRenderer;

        var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4);
        var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({color: 0x555555}));
        groundMesh.rotation.x = -Math.PI / 2;
        groundMesh.position.y = -20;
        scene.add(groundMesh);

        var sphereGeometry = new THREE.SphereGeometry(14, 20, 20);
        var cubeGeometry = new THREE.BoxGeometry(15, 15, 15);
        var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4);


        var meshMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff});
        var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
        var cube = new THREE.Mesh(cubeGeometry, meshMaterial);
        var plane = new THREE.Mesh(planeGeometry, meshMaterial);

        // position the sphere
        sphere.position.x = 0;
        sphere.position.y = 3;
        sphere.position.z = 2;


        cube.position = sphere.position;
        plane.position = sphere.position;


        // add the sphere to the scene
        scene.add(cube);

        // position and point the camera to the center of the scene
        camera.position.x = -20;
        camera.position.y = 30;
        camera.position.z = 40;
        camera.lookAt(new THREE.Vector3(10, 0, 0));

        // add subtle ambient lighting
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-30, 60, 60);
        spotLight.castShadow = true;
        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;

        var controls = new function () {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;

            this.opacity = meshMaterial.opacity;
            this.transparent = meshMaterial.transparent;
            this.overdraw = meshMaterial.overdraw;
            this.visible = meshMaterial.visible;
            this.emissive = meshMaterial.emissive.getHex();
            this.ambient = meshMaterial.ambient.getHex();
            this.side = "front";

            this.color = meshMaterial.color.getStyle();
            this.wrapAround = false;
            this.wrapR = 1;
            this.wrapG = 1;
            this.wrapB = 1;

            this.selectedMesh = "cube";

        };

        var gui = new dat.GUI();


        var spGui = gui.addFolder("Mesh");
        spGui.add(controls, 'opacity', 0, 1).onChange(function (e) {
            meshMaterial.opacity = e
        });
        spGui.add(controls, 'transparent').onChange(function (e) {
            meshMaterial.transparent = e
        });
        spGui.add(controls, 'visible').onChange(function (e) {
            meshMaterial.visible = e
        });
        spGui.addColor(controls, 'ambient').onChange(function (e) {
            meshMaterial.ambient = new THREE.Color(e)
        });
        spGui.addColor(controls, 'emissive').onChange(function (e) {
            meshMaterial.emissive = new THREE.Color(e)
        });
        spGui.add(controls, 'side', ["front", "back", "double"]).onChange(function (e) {
            console.log(e);
            switch (e) {
                case "front":
                    meshMaterial.side = THREE.FrontSide;
                    break;
                case "back":
                    meshMaterial.side = THREE.BackSide;
                    break;
                case "double":
                    meshMaterial.side = THREE.DoubleSide;
                    break;
            }
            meshMaterial.needsUpdate = true;

        });
        spGui.addColor(controls, 'color').onChange(function (e) {
            meshMaterial.color.setStyle(e)
        });
        spGui.add(controls, 'selectedMesh', ["cube", "sphere", "plane"]).onChange(function (e) {

            scene.remove(plane);
            scene.remove(cube);
            scene.remove(sphere);

            switch (e) {
                case "cube":
                    scene.add(cube);
                    break;
                case "sphere":
                    scene.add(sphere);
                    break;
                case "plane":
                    scene.add(plane);
                    break;

            }


            scene.add(e);
        });

        spGui.add(controls, 'wrapAround').onChange(function (e) {

            meshMaterial.wrapAround = e;
            meshMaterial.needsUpdate = true;
        });

        spGui.add(controls, 'wrapR', 0, 1).step(0.01).onChange(function (e) {
            meshMaterial.wrapRGB.x = e;
        });

        spGui.add(controls, 'wrapG', 0, 1).step(0.01).onChange(function (e) {
            meshMaterial.wrapRGB.y = e;
        });

        spGui.add(controls, 'wrapB', 0, 1).step(0.01).onChange(function (e) {
            meshMaterial.wrapRGB.z = e;

        });

        render();

        function render() {
            stats.update();

            cube.rotation.y = step += 0.01;
            plane.rotation.y = step;
            sphere.rotation.y = step;

            // 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>

 

 

    3 ShaderMaterial:最通用也是最難用的材質,經過ShaderMaterial能夠建立本身的着色程序,直接在webgl環境中運行,

    着色器能夠將three.js中的js對象轉化爲屏幕上的像素,

    注意着色器不是js編寫的,而是相似於c的GLSL語言,因此下面這個demo只是一個例子,並不作過多的解釋

<!DOCTYPE html>

<html>

<head>
    <title>Example 04.08 - Shader material - http://glsl.heroku.com/</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>

<script id="vertex-shader" type="x-shader/x-vertex">
    uniform float time;
    varying vec2 vUv;


    void main()
    {
    vec3 posChanged = position;
    posChanged.x = posChanged.x*(abs(sin(time*1.0)));
    posChanged.y = posChanged.y*(abs(cos(time*1.0)));
    posChanged.z = posChanged.z*(abs(sin(time*1.0)));
    //gl_Position = projectionMatrix * modelViewMatrix * vec4(position*(abs(sin(time)/2.0)+0.5),1.0);
    gl_Position = projectionMatrix * modelViewMatrix * vec4(posChanged,1.0);
    }

</script>

<script id="fragment-shader-1" type="x-shader/x-fragment">
    precision highp float;
    uniform float time;
    uniform float alpha;
    uniform vec2 resolution;
    varying vec2 vUv;

    void main2(void)
    {
    vec2 position = vUv;
    float red = 1.0;
    float green = 0.25 + sin(time) * 0.25;
    float blue = 0.0;
    vec3 rgb = vec3(red, green, blue);
    vec4 color = vec4(rgb, alpha);
    gl_FragColor = color;
    }

    #define PI 3.14159
    #define TWO_PI (PI*2.0)
    #define N 68.5

    void main(void)
    {
    vec2 center = (gl_FragCoord.xy);
    center.x=-10.12*sin(time/200.0);
    center.y=-10.12*cos(time/200.0);

    vec2 v = (gl_FragCoord.xy - resolution/20.0) / min(resolution.y,resolution.x) * 15.0;
    v.x=v.x-10.0;
    v.y=v.y-200.0;
    float col = 0.0;

    for(float i = 0.0; i < N; i++)
    {
    float a = i * (TWO_PI/N) * 61.95;
    col += cos(TWO_PI*(v.y * cos(a) + v.x * sin(a) + sin(time*0.004)*100.0 ));
    }

    col /= 5.0;

    gl_FragColor = vec4(col*1.0, -col*1.0,-col*4.0, 1.0);
    }


</script>

<script id="fragment-shader-2" type="x-shader/x-fragment">
    // from http://glsl.heroku.com/e#7906.0


    uniform float time;
    uniform vec2 resolution;

    // 2013-03-30 by @hintz

    #define CGFloat float
    #define M_PI 3.14159265359

    vec3 hsvtorgb(float h, float s, float v)
    {
    float c = v * s;
    h = mod((h * 6.0), 6.0);
    float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
    vec3 color;

    if (0.0 <= h && h < 1.0)
    {
    color = vec3(c, x, 0.0);
    }
    else if (1.0 <= h && h < 2.0)
    {
    color = vec3(x, c, 0.0);
    }
    else if (2.0 <= h && h < 3.0)
    {
    color = vec3(0.0, c, x);
    }
    else if (3.0 <= h && h < 4.0)
    {
    color = vec3(0.0, x, c);
    }
    else if (4.0 <= h && h < 5.0)
    {
    color = vec3(x, 0.0, c);
    }
    else if (5.0 <= h && h < 6.0)
    {
    color = vec3(c, 0.0, x);
    }
    else
    {
    color = vec3(0.0);
    }

    color += v - c;

    return color;
    }

    void main(void)
    {

    vec2 position = (gl_FragCoord.xy - 0.5 * resolution) / resolution.y;
    float x = position.x;
    float y = position.y;

    CGFloat a = atan(x, y);

    CGFloat d = sqrt(x*x+y*y);
    CGFloat d0 = 0.5*(sin(d-time)+1.5)*d;
    CGFloat d1 = 5.0;

    CGFloat u = mod(a*d1+sin(d*10.0+time), M_PI*2.0)/M_PI*0.5 - 0.5;
    CGFloat v = mod(pow(d0*4.0, 0.75),1.0) - 0.5;

    CGFloat dd = sqrt(u*u+v*v);

    CGFloat aa = atan(u, v);

    CGFloat uu = mod(aa*3.0+3.0*cos(dd*30.0-time), M_PI*2.0)/M_PI*0.5 - 0.5;
    // CGFloat vv = mod(dd*4.0,1.0) - 0.5;

    CGFloat d2 = sqrt(uu*uu+v*v)*1.5;

    gl_FragColor = vec4( hsvtorgb(dd+time*0.5/d1, sin(dd*time), d2), 1.0 );
    }

</script>

<script id="fragment-shader-3" type="x-shader/x-fragment">
    uniform vec2 resolution;
    uniform float time;

    vec2 rand(vec2 pos)
    {
    return fract( 0.00005 * (pow(pos+2.0, pos.yx + 1.0) * 22222.0));
    }
    vec2 rand2(vec2 pos)
    {
    return rand(rand(pos));
    }

    float softnoise(vec2 pos, float scale)
    {
    vec2 smplpos = pos * scale;
    float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
    float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
    float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
    float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

    vec2 a = fract(smplpos);
    return mix(
    mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
    mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
    smoothstep(0.0, 1.0, a.y));
    }

    void main(void)
    {
    vec2 pos = gl_FragCoord.xy / resolution.y;
    pos.x += time * 0.1;
    float color = 0.0;
    float s = 1.0;
    for(int i = 0; i < 8; i++)
    {
    color += softnoise(pos+vec2(i)*0.02, s * 4.0) / s / 2.0;
    s *= 2.0;
    }
    gl_FragColor = vec4(color);
    }

</script>

<script id="fragment-shader-4" type="x-shader/x-fragment">


    uniform float time;
    uniform vec2 resolution;

    vec2 rand(vec2 pos)
    {
    return
    fract(
    (
    pow(
    pos+2.0,
    pos.yx+2.0
    )*555555.0
    )
    );
    }

    vec2 rand2(vec2 pos)
    {
    return rand(rand(pos));
    }

    float softnoise(vec2 pos, float scale) {
    vec2 smplpos = pos * scale;
    float c0 = rand2((floor(smplpos) + vec2(0.0, 0.0)) / scale).x;
    float c1 = rand2((floor(smplpos) + vec2(1.0, 0.0)) / scale).x;
    float c2 = rand2((floor(smplpos) + vec2(0.0, 1.0)) / scale).x;
    float c3 = rand2((floor(smplpos) + vec2(1.0, 1.0)) / scale).x;

    vec2 a = fract(smplpos);
    return mix(mix(c0, c1, smoothstep(0.0, 1.0, a.x)),
    mix(c2, c3, smoothstep(0.0, 1.0, a.x)),
    smoothstep(0.0, 1.0, a.x));
    }

    void main( void ) {
    vec2 pos = gl_FragCoord.xy / resolution.y - time * 0.4;

    float color = 0.0;
    float s = 1.0;
    for (int i = 0; i < 6; ++i) {
    color += softnoise(pos + vec2(0.01 * float(i)), s * 4.0) / s / 2.0;
    s *= 2.0;
    }
    gl_FragColor = vec4(color,mix(color,cos(color),sin(color)),color,1);
    }

</script>

<script id="fragment-shader-5" type="x-shader/x-fragment">

    uniform float time;
    uniform vec2 resolution;

    // tie nd die by Snoep Games.

    void main( void ) {

    vec3 color = vec3(1.0, 0., 0.);
    vec2 pos = (( 1.4 * gl_FragCoord.xy - resolution.xy) / resolution.xx)*1.5;
    float r=sqrt(pos.x*pos.x+pos.y*pos.y)/15.0;
    float size1=2.0*cos(time/60.0);
    float size2=2.5*sin(time/12.1);

    float rot1=13.00; //82.0+16.0*sin(time/4.0);
    float rot2=-50.00; //82.0+16.0*sin(time/8.0);
    float t=sin(time);
    float a = (60.0)*sin(rot1*atan(pos.x-size1*pos.y/r,pos.y+size1*pos.x/r)+time);
    a += 200.0*acos(pos.x*2.0+cos(time/2.0))+asin(pos.y*5.0+sin(time/2.0));
    a=a*(r/50.0);
    a=200.0*sin(a*5.0)*(r/30.0);
    if(a>5.0) a=a/200.0;
    if(a<0.5) a=a*22.5;
    gl_FragColor = vec4( cos(a/20.0),a*cos(a/200.0),sin(a/8.0), 1.0 );
    }


</script>

<script id="fragment-shader-6" type="x-shader/x-fragment">


    uniform float time;
    uniform vec2 resolution;


    void main( void )
    {

    vec2 uPos = ( gl_FragCoord.xy / resolution.xy );//normalize wrt y axis
    //suPos -= vec2((resolution.x/resolution.y)/2.0, 0.0);//shift origin to center

    uPos.x -= 1.0;
    uPos.y -= 0.5;

    vec3 color = vec3(0.0);
    float vertColor = 2.0;
    for( float i = 0.0; i < 15.0; ++i )
    {
    float t = time * (0.9);

    uPos.y += sin( uPos.x*i + t+i/2.0 ) * 0.1;
    float fTemp = abs(1.0 / uPos.y / 100.0);
    vertColor += fTemp;
    color += vec3( fTemp*(10.0-i)/10.0, fTemp*i/10.0, pow(fTemp,1.5)*1.5 );
    }

    vec4 color_final = vec4(color, 1.0);
    gl_FragColor = color_final;
    }

</script>

<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();

        // 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();
        renderer.setClearColor(new THREE.Color(0x000000, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;


        var cubeGeometry = new THREE.BoxGeometry(20, 20, 20);

        var meshMaterial1 = createMaterial("vertex-shader", "fragment-shader-1");
        var meshMaterial2 = createMaterial("vertex-shader", "fragment-shader-2");
        var meshMaterial3 = createMaterial("vertex-shader", "fragment-shader-3");
        var meshMaterial4 = createMaterial("vertex-shader", "fragment-shader-4");
        var meshMaterial5 = createMaterial("vertex-shader", "fragment-shader-5");
        var meshMaterial6 = createMaterial("vertex-shader", "fragment-shader-6");


        var material = new THREE.MeshFaceMaterial(
                [meshMaterial1,
                    meshMaterial2,
                    meshMaterial3,
                    meshMaterial4,
                    meshMaterial5,
                    meshMaterial6]);
//        var material = new THREE.MeshFaceMaterial([meshMaterial2, meshMaterial2, meshMaterial1, meshMaterial1, meshMaterial1, meshMaterial1]);

        var cube = new THREE.Mesh(cubeGeometry, material);


        // add the sphere to the scene
        scene.add(cube);

        // position and point the camera to the center of the scene
        camera.position.x = 30;
        camera.position.y = 30;
        camera.position.z = 30;
        camera.lookAt(new THREE.Vector3(0, 0, 0));

        // add subtle ambient lighting
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        // add spotlight for the shadows
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        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;
        var oldContext = null;

        var controls = new function () {
            this.rotationSpeed = 0.02;
            this.bouncingSpeed = 0.03;

            this.opacity = meshMaterial1.opacity;
            this.transparent = meshMaterial1.transparent;

            this.visible = meshMaterial1.visible;
            this.side = "front";

            this.wireframe = meshMaterial1.wireframe;
            this.wireframeLinewidth = meshMaterial1.wireframeLinewidth;

            this.selectedMesh = "cube";

            this.shadow = "flat";

        };


        render();

        function render() {
            stats.update();

            cube.rotation.y = step += 0.01;
            cube.rotation.x = step;
            cube.rotation.z = step;


            cube.material.materials.forEach(function (e) {
                e.uniforms.time.value += 0.01;
            });


            // 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;
        }

        function createMaterial(vertexShader, fragmentShader) {
            var vertShader = document.getElementById(vertexShader).innerHTML;
            var fragShader = document.getElementById(fragmentShader).innerHTML;

            var attributes = {};
            var uniforms = {
                time: {type: 'f', value: 0.2},
                scale: {type: 'f', value: 0.2},
                alpha: {type: 'f', value: 0.6},
                resolution: {type: "v2", value: new THREE.Vector2()}
            };

            uniforms.resolution.value.x = window.innerWidth;
            uniforms.resolution.value.y = window.innerHeight;

            var meshMaterial = new THREE.ShaderMaterial({
                uniforms: uniforms,
                attributes: attributes,
                vertexShader: vertShader,
                fragmentShader: fragShader,
                transparent: true

            });


            return meshMaterial;
        }


    }
    window.onload = init;
</script>
</body>
</html>

 

1.9 線段幾何體的材質

  下面這兩種材質只能應用於特定的幾何體:THREE.Line(線段)

  1.9.1 LineBaseMaterial:能夠設置線段的顏色,寬度,端點,鏈接點等屬性

  1.9.2 LineDashedMaterial:與上面的LineBaseMaterial屬性同樣,可是能夠經過指定短劃線和空格的長度,創造出來虛線的效果

  

<!DOCTYPE html>

<html>

<head>
    <title>Example 04.09 - Linematerial</title>
    <script type="text/javascript" src="../libs/three.js"></script>

    <script type="text/javascript" src="../libs/stats.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();

        // 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();

        renderer.setClearColor(new THREE.Color(0x000000, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;


        // position and point the camera to the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // 環境光 沒有特定的光源,該光源不會影響陰影的產生,使用該光源是爲了弱化陰影或者添加一些顏色
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        //聚光燈光源,最常使用的光源,錐形效果
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
        /*本處書中給出的例子是gosper曲線,涉及到數學曲線、,本人沒有看懂,因此使用了隨機生成的點,附帶上Gosper函數,
        能看懂的朋友,能夠留言給我,謝謝了!
        function gosper(a, b) {

            var turtle = [0, 0, 0];
            var points = [];
            var count = 0;

            rg(a, b, turtle);


            return points;
            
            //右走
            function rt(x) {
                turtle[2] += x;
            }
            
            //左走
            function lt(x) {
                turtle[2] -= x;
            }

            function fd(dist) {
//                ctx.beginPath();
                points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
//                ctx.moveTo(turtle[0], turtle[1]);

                var dir = turtle[2] * (Math.PI / 180);
                turtle[0] += Math.cos(dir) * dist;
                turtle[1] += Math.sin(dir) * dist;

                points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
//                ctx.lineTo(turtle[0], turtle[1]);
//                ctx.stroke();

            }

            function rg(st, ln, turtle) {

                st--;
                ln = ln / 2.6457;
                if (st > 0) {
//                    ctx.strokeStyle = '#111';
                    rg(st, ln, turtle);
                    rt(60);
                    gl(st, ln, turtle);
                    rt(120);
                    gl(st, ln, turtle);
                    lt(60);
                    rg(st, ln, turtle);
                    lt(120);
                    rg(st, ln, turtle);
                    rg(st, ln, turtle);
                    lt(60);
                    gl(st, ln, turtle);
                    rt(60);
                }
                if (st == 0) {
                    fd(ln);
                    rt(60);
                    fd(ln);
                    rt(120);
                    fd(ln);
                    lt(60);
                    fd(ln);
                    lt(120);
                    fd(ln);
                    fd(ln);
                    lt(60);
                    fd(ln);
                    rt(60)
                }
            }

            function gl(st, ln, turtle) {
                st--;
                ln = ln / 2.6457;
                if (st > 0) {
//                    ctx.strokeStyle = '#555';
                    lt(60);
                    rg(st, ln, turtle);
                    rt(60);
                    gl(st, ln, turtle);
                    gl(st, ln, turtle);
                    rt(120);
                    gl(st, ln, turtle);
                    rt(60);
                    rg(st, ln, turtle);
                    lt(120);
                    rg(st, ln, turtle);
                    lt(60);
                    gl(st, ln, turtle);
                }
                if (st == 0) {
                    lt(60);
                    fd(ln);
                    rt(60);
                    fd(ln);
                    fd(ln);
                    rt(120);
                    fd(ln);
                    rt(60);
                    fd(ln);
                    lt(120);
                    fd(ln);
                    lt(60);
                    fd(ln);
                }
            }
        }
        
        
        */
        var points=[];
        function getPoints(){
            var rmd_x=Math.random()*50;
            var rmd_y=Math.random()*50;
            var rmd_z=Math.random()*50;
            points.push({x:rmd_x, y: rmd_y, z: rmd_z});
        }
        
        for(var j=0;j<100;j++){
            getPoints();
        }

        //生成一個幾何體
        var lines = new THREE.Geometry();
        var colors = [];
        var i = 0;
        //該幾何體的頂點由getPoint函數生成的點組成
        points.forEach(function (e) {
            lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y));
            colors[i] = new THREE.Color(0xffffff);
            colors[i].setHSL(e.x / 100 + 0.5, (  e.y * 20 ) / 300, 0.8);
            //色調,飽和度,亮度
            i++;
        });
        
        //該幾何體的顏色就是上面獲得的顏色
        lines.colors = colors;
        /*這裏有幾個點不是很理解,linewidth是設置線段的寬度的,可是這裏即便設置到50,也沒有任何反應,不知道是哪裏寫錯了
        有能找到問題的歡迎留言給我,另外透明度的opacity屬性也不起做用            
        */
        
        
        var material = new THREE.LineBasicMaterial({
            opacity: 1.0,
            linewidth: 4,
            vertexColors: THREE.VertexColors
        });

        var line = new THREE.Line(lines, material);
        line.position.set(25, -30, -60);
        scene.add(line);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        var step = 0;
        render();

        function render() {
            //stats.update();
            line.rotation.z = step += 0.01;

            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }
    };

    window.onload = init;


</script>
</body>
</html>

LineDashedMaterial與LineBasicMaterial類似,多了幾個屬性,dashSize:短劃線的長度,gapSize間隔的長度

<!DOCTYPE html>

<html>

<head>
    <title>Example 04.09 - Linematerial</title>
    <script type="text/javascript" src="../libs/three.js"></script>

    <script type="text/javascript" src="../libs/stats.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();

        // 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();

        renderer.setClearColor(new THREE.Color(0x000000, 1.0));
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.shadowMapEnabled = true;


        // position and point the camera to the center of the scene
        camera.position.x = -30;
        camera.position.y = 40;
        camera.position.z = 30;
        camera.lookAt(scene.position);

        // 環境光 沒有特定的光源,該光源不會影響陰影的產生,使用該光源是爲了弱化陰影或者添加一些顏色
        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        //聚光燈光源,最常使用的光源,錐形效果
        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);
        
       
        var points=[];
        function getPoints(){
            var rmd_x=Math.random()*50;
            var rmd_y=Math.random()*50;
            var rmd_z=Math.random()*50;
            points.push({x:rmd_x, y: rmd_y, z: rmd_z});
        }
        
        for(var j=0;j<100;j++){
            getPoints();
        }

        //生成一個幾何體
        var lines = new THREE.Geometry();
        var colors = [];
        var i = 0;
        //該幾何體的頂點由getPoint函數生成的點組成
        points.forEach(function (e) {
            lines.vertices.push(new THREE.Vector3(e.x, e.z, e.y));
            colors[i] = new THREE.Color(0xffffff);
            colors[i].setHSL(e.x / 100 + 0.5, (  e.y * 20 ) / 300, 0.8);
            //色調,飽和度,亮度
            i++;
        });
        
        //該幾何體的顏色就是上面獲得的顏色
        lines.colors = colors;
        
        //必須調用該方法,若是不調用,間隔就不能顯示出來
 lines.computeLineDistances(); var material = new THREE.LineDashedMaterial({
            dashSize:10,//短劃線的長度
 gapSize:1,//間隔的長度
            scale: 0.4,//縮放的比例
            vertexColors:THREE.VertexColors//爲每一個頂點指定一個顏色
        });

        var line = new THREE.Line(lines, material);
        line.position.set(25, -30, -60);
        scene.add(line);

        // add the output of the renderer to the html element
        document.getElementById("WebGL-output").appendChild(renderer.domElement);

        // call the render function
        var step = 0;
        render();

        function render() {
            //stats.update();
            line.rotation.z = step += 0.01;

            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }
    };

    window.onload = init;


</script>
</body>
</html>
相關文章
相關標籤/搜索