three.js开发指南(第四章)

Three.js开发指南---使用three.js的材质(第四章)

Posted on  2017-01-29 16:41  Amy-lover 阅读( 1312) 评论( 0编辑  收藏

 

材质就像物体的皮肤,决定了几何体的外表,例如是否像草地/金属,是否透明,是否显示线框等

一 材质

  THREE.js的材质分为多种,Three.js提供了一个材质基类THREE.Material,

  该基类拥有three.js所有材质的公有属性,分为三类:基础属性,融合属性,高级属性

  基础属性:ID,name,透明度,是否可见,是否需要刷新等

  融合属性:决定了物体如何与背景融合

  高级属性:可以控制WEBGL上下文渲染物体的方法,大多数情况下,是不会用这些属性,我们这里不再讨论

   1.1 基础属性

属性描述
ID(描述符)用来标识材质,在创建时赋值
name(名称)通过该属性克赋予该材质名称
opacity(透明度)定义物体有多透明,与transparent属性一起使用
transparent(是否透明)设置为true时,会根据opacity的值来设置透明度,设置为false时,则只着色
overdraw(过度描绘)当使用THREE.CanvasRenderer画布渲染器绘制对象的时候,物体之间可能会有空隙,这时设置该值为true,多边形会被渲染的稍微大一点,
visible(是否可见)定义该材质是否可见
side(侧面)

决定了几何体的哪一面应用该材质,

THREE.FrontSide应用到几何体的前(外)面;

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>
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目录(共14章) 前言 本书内容 阅读之前的准备 读者对象 致谢 第1章 用Three.js创建你的第一个三维场景 1.1 使用Three.js的前提条件 1.2 获取源代码 1.3 创建HTML页面框架 1.4 渲染并展示三维对象 1.5 添加材质、灯光和阴影 1.6 用动画扩展你的首个场景 1.7 使用dat.GUI库简化试验 1.8 使用ASCII效果 1.9 总结 第2章 使用构建Three.js场景的基本组件 2.1 创建场景 2.2 使用几何和网格对象 2.3 选择合适的相机 2.4 总结 第3章 使用Three.js里的各种光源 3.1 探索Three.js库提供的光源 3.2 学习基础光源 3.3 总结 第4章 使用Three.js的材质 4.1 理解共有属性 4.2 从简单的网格材质(基础、深度和面)开始 4.3 学习高级材质 4.4 线段几何体的材质 4.5 总结 第5章 学习使用几何体 5.1 Three.js提供的基础几何体 5.2 总结 第6章 使用高级几何体和二元操作 6.1 ConvexGeometry 6.2 LatheGeometry 6.3 通过拉伸创建几何体 6.4 创建三维文本 6.5 使用二元操作组合网格 6.6 总结 第7章 粒子和粒子系统 7.1 理解粒子 7.2 粒子、粒子系统和BasicParticleMaterial 7.3 使用HTML5画布格式化粒子 7.4 使用纹理格式化粒子 7.5 从高级几何体中创建粒子系统 7.6 总结 第8章 创建、加载高级网格和几何体 8.1 几何体组合和合并 8.2 从外部资源中加载几何体 8.3 以Three.js的JSON格式保存和加载 8.4 使用Blender 8.5 导入三维格式文件 8.6 总结 第9章 创建动画和移动相机 9.1 基础动画 9.2 使用相机 9.3 变形动画和骨骼动画 9.4 使用外部模型创建动画 9.5 总结 第10章 加载和使用纹理 10.1 在材质中使用纹理 10.2 纹理的高级用途 10.3 总结 第11章 定制着色器和渲染后期处理 11.1 设置后期处理 11.2 后期处理通道 11.3 创建自定义的后期处理着色器 11.4 总结 第12章 用Physijs在场景中添加物理效果 12.1 创建可用Physijs的基本Three.js场景 12.2 材质属性 12.3 基础图形 12.4 使用约束限制对象移动 12.5 总结

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值