本章主要做了下面的工作
1 生成一個簡單的場景,該場景的物體只有平面和坐標軸
2 在第一個demo的基礎上添加光源和方塊物體,並生成陰影
3 在第二個demo的基礎上,增加動畫,使得方塊進行旋轉
4 在第三個demo的基礎上,增加圖形操作界面,改變方塊旋轉的速度
5 在第四個demo的基礎上,我們使用ascII效果(這個沒有做出來,不知道為什么asciieffect沒有定義)
在下面的demo中,
1 生成了場景,相機,渲染器,幾何體(平面),材質(幾何體和材質進行組合,組成物體),坐標軸,
2 將相機,渲染器,物體都添加到場景中,
3 然后再對場景和相機進行渲染
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.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"> function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); //生成一個坐標軸,輔助線,坐標軸的參數 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//注意參數 //生成一個材質,設置材質的顏色,同時顯示線框 var planeMaterial=new THREE.MeshBasicMaterial({color:0xcccccc,wireframe:true}); //生成一個網格,將平面和材質放在一個網格中,組合在一起,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI; plane.position.x=15; plane.position.y=0; plane.position.z=0; //將相機,渲染器,坐標軸,平面都追加到場景中,然后對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); render.render(scene,camera); document.getElementById("WebGL-output").append(render.domElement); }; window.onload = init; </script> </body> </html>
在下面的demo中,我們添加光源和設置物體陰影
1 three.js中有兩種材質可以對光源產生反應,MeshLambertMaterial和MeshPhongMaterial,所以我們將上面demo中的MeshBasicMaterial替換為另外一個材質MeshLambertMaterial
2 我們設置點光源SpotLight
3 由於陰影需要大量的計算資源,所以three.js默認是不生成陰影的,需要進行設置
首先是渲染器,render.shadowMapEnabled=true
其次是允許物體投射陰影,cube.castShadow=true;
再其次是允許某些物體接受陰影,plane.receiveShadow=true
最后是光源也要投射陰影,spot.castShadow=true
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.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"> function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//允許陰影映射,渲染陰影需要大量的資源,因此我們需要告訴渲染器我們需要陰影 //生成一個坐標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一起,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//需要陰影,方塊進行投射陰影 var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(-40,60,-10); spotLight.castShadow=true; //將相機,渲染器,坐標軸,平面都追加到場景中,然后對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); scene.add(cube); scene.add(spotLight); render.render(scene,camera); document.getElementById("WebGL-output").append(render.domElement); }; window.onload = init; </script> </body> </html>
在下面demo中,我們引入動畫
讓場景每隔一段時間進行一次渲染,setInterval方法會指定時間進行一次函數調用,
但是該方法並不考慮瀏覽器發生的事情,即使你正在瀏覽其他頁面,該方法仍然會每隔固定的時間進行一次調用,
另外該方法並沒有跟顯示器的重新繪制同步,這將導致較高的cpu使用率
現在的瀏覽器有了requestAnimationFrame方法
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.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"> function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//允許陰影映射,渲染陰影需要大量的資源,因此我們需要告訴渲染器我們需要陰影 //生成一個坐標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一起,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//需要陰影,方塊進行投射陰影 var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(-40,60,-10); spotLight.castShadow=true; //將相機,渲染器,坐標軸,平面都追加到場景中,然后對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); scene.add(cube); scene.add(spotLight); document.getElementById("WebGL-output").append(render.domElement); renderScene(); function renderScene(){ cube.rotation.x+=0.02; cube.rotation.y+=0.02; cube.rotation.z+=0.02; requestAnimationFrame(renderScene); render.render(scene,camera); } } window.onload = init; </script> </body> </html>
我們使用google創建的dat.GUI庫創建一個簡單的界面,來控制方塊旋轉的速度
1 首先引入google的dat.gui.js文件
2 生成一個gui對象
3 定義一個js對象controls,然后再將controls對象傳遞給dat.gui對象
<!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"> function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//允許陰影映射,渲染陰影需要大量的資源,因此我們需要告訴渲染器我們需要陰影 //生成一個坐標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一起,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//需要陰影,方塊進行投射陰影 var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(-40,60,-10); spotLight.castShadow=true; //將相機,渲染器,坐標軸,平面都追加到場景中,然后對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); scene.add(cube); scene.add(spotLight); document.getElementById("WebGL-output").append(render.domElement); renderScene(); function renderScene(){ cube.rotation.x+=controls.rotationSpeed; cube.rotation.y+=controls.rotationSpeed; cube.rotation.z+=controls.rotationSpeed; requestAnimationFrame(renderScene); render.render(scene,camera); } } var controls=new function(){ this.rotationSpeed=0.02; }; var gui=new dat.GUI(); gui.add(controls,"rotationSpeed",0,0.5); window.onload = init; </script> </body> </html>
ASCII效果
1 引入AsciiEffect.js
2 生成一個ascii效果
3 頁面追加的domElement由渲染器的domElement改成ascii效果的domelement
4 render的話就使用effect的render進行渲染
<!DOCTYPE html> <html> <head> <title>1</title> <script type="text/javascript" src="three.js"></script> <script type="text/javascript" src="dat.gui.js"></script> <script type="text/javascript" src="AsciiEffect.js"></script> <style> body { /* set margin to 0 and overflow to hidden, to go fullscreen */ margin: 0; overflow: hidden; } </style> </head> <body> <!-- Div which will hold the Output --> <div id="WebGL-output"> </div> <!-- Javascript code that runs our Three.js examples --> <script type="text/javascript"> function init() { var scene=new THREE.Scene();//生成一個場景 //生成一個相機 var camera=new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);//視場,長寬比,近面,遠面 camera.position.x=-20; camera.position.y=40; camera.position.z=30; camera.lookAt(scene.position); //生成一個渲染器 var render=new THREE.WebGLRenderer(); render.setClearColorHex(0xEEEEEE); render.setSize(window.innerWidth,window.innerHeight); render.shadowMapEnabled=true;//允許陰影映射,渲染陰影需要大量的資源,因此我們需要告訴渲染器我們需要陰影 //生成一個坐標軸,輔助線 var axes=new THREE.AxisHelper(20); //生成一個平面 var planeGeometry=new THREE.PlaneGeometry(60,20,10,10);//平面 //生成一個材質 var planeMaterial=new THREE.MeshLambertMaterial({color:0xffffff}); //生成一個網格,將平面和材質放在一個網格中,組合在一起,組成一個物體 var plane=new THREE.Mesh(planeGeometry,planeMaterial); plane.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 plane.position.x=0; plane.position.y=0; plane.position.z=0; plane.receiveShadow=true;//平面進行接受陰影 var cubeGeometry=new THREE.CubeGeometry(10,10,10); var planeMaterial1=new THREE.MeshLambertMaterial({color:0xff0000}); var cube=new THREE.Mesh(cubeGeometry,planeMaterial1); //plane1.rotation.x=-0.5*Math.PI;//將平面沿着x軸進行旋轉 cube.position.x=-4; cube.position.y=3; cube.position.z=0; cube.castShadow=true;//需要陰影,方塊進行投射陰影 var spotLight=new THREE.SpotLight(0xffffff); spotLight.position.set(-40,60,-10); spotLight.castShadow=true; //將相機,渲染器,坐標軸,平面都追加到場景中,然后對場景和相機進行渲染 scene.add(camera); scene.add(render); scene.add(axes); scene.add(plane); scene.add(cube); scene.add(spotLight); var effect=new THREE.AsciiEffect(render); effect.setSize(window.innerWidth,window.innerHeight); document.getElementById("WebGL-output").append(effect.domElement); renderScene(); function renderScene(){ cube.rotation.x+=controls.rotationSpeed; cube.rotation.y+=controls.rotationSpeed; cube.rotation.z+=controls.rotationSpeed; requestAnimationFrame(renderScene); effect.render(scene,camera); } } var controls=new function(){ this.rotationSpeed=0.02; }; var gui=new dat.GUI(); gui.add(controls,"rotationSpeed",0,0.5); window.onload = init; </script> </body> </html>