材質就像物體的皮膚,決定了幾何體的外表,例如是否像草地/金屬,是否透明,是否顯示線框等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>