簡介?
Three.js是用JavaScript編寫的第三方庫,用于實現3D功能,基于WebGL進行封裝。
一個3D模型的建立主要由以下幾個部分組成(基本版):
?* ? ?創建場景scene--相機camera--渲染器renderer--(燈光light);
?* ? ?創建模型(geometry+material+mesh)或導入模型gltf/glb;
?* ? ?添加相機控件controls--動畫渲染循環animate;?*? ? 其他動畫操作,可學習gasp動畫庫。
一、引入threeJS
// 引入three.js---npm install three@0.157.0 -S
import * as THREE from "three";
?二、場景、相機、渲染器
1、創建3D場景對象Scene
const scene = new THREE.Scene();
2、創建透視投影相機對象
// const camera = new THREE.PerspectiveCamera(); //正投影相機是OrthographicCamera // 定義threejs輸出Canvas畫布的尺寸(單位:像素px) const width = window.innerWidth; //寬度 const height = window.innerHeight; //高度 // (fov,aspect,near,far),30:視場角度, width / height:Canvas畫布, 1:近裁截面, 3000:遠裁截面 const camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000); //相機在Three.js三維坐標系中的位置---根據需要設置相機位置具體值 camera.position.set(292, 223, 185); //相機觀察目標指向Threejs 3D空間中某個位置 camera.lookAt(0, 0, 0); //坐標原點---camera.lookAt(mesh.position);指向mesh對應的位置
3、創建webGL渲染器對象
//屬性:antialias是否抗鋸齒 const renderer = new THREE.WebGLRenderer(); //設置three.js渲染區域的尺寸(像素px) renderer.setSize(width, height); //WebGLRenderer執行渲染方法生成canvas畫布,并把相機拍照的場景在畫布上呈現 renderer.render(scene, camera); // console.log("threeJS", THREE.Scene); //測試場景 // 獲得生成的canvas畫布(domElement就是生成的那張照片==canvas畫布==html元素) document.body.appendChild(renderer.domElement); // 將Canvas畫布插入到任意HTML元素中 // document.getElementById('app').appendChild(renderer.domElement);
?三、燈光及陰影
燈光:
1、PointLight:點光源,類似于燈泡,向四周發射光線的發光點。
2、SpotLight:聚光源,沿著特定方向逐漸發散,照射范圍在三維空間中構成一個圓錐體。
3、DirectionalLight:平行光,沿著特定方向發射。
4、AmbientLight:環境光,沒有特定方向,只是整體改變場景的光照明暗,無法投射陰影,均勻照射對物體明暗對比無法呈現。
5、HemisphereLight:半球光,可以很好地表現天空和地面顏色照射到物體上時的效果,不能投射陰影,對物體明暗對比比較明顯。
以點光源舉例:
const pointLight = new THREE.PointLight(0xffffff, 1.0); pointLight.intensity = 1.0; //光照強度 // 設置光源衰減,默認2.0 pointLight.decay = 0.0; //設置光源不隨距離衰減 //點光源位置 pointLight.position.set(400, 0, 0); //點光源放在x軸上 scene.add(pointLight); //點光源添加到場景中// 點光源輔助觀察--創建一個虛擬的球形網 Mesh的輔助對象來可視化模擬光線 const pointLightHelper = new THREE.PointLightHelper(pointLight, 50); scene.add(pointLightHelper);
陰影:
陰影的開啟需要全方位的開啟,渲染器及光源開啟陰影,模型要接受陰影,模型需開啟陰影,地面接收陰影。
// 首先渲染器開啟陰影 renderer.shadowMap.enabled = true; renderer.shadowMapEnabled = true;// 光源開啟陰影 directionalLight.castShadow = true; directionalLight.shadow.mapSize = new Vector2(1024, 1024);// 地板接受陰影開啟 floor.receiveShadow = true;// 模型Mesh開啟陰影 // 物體需要開啟“引起陰影”和“接收陰影”: gltf.scene.traverse(obj => {if(obj.isMesh) {obj.castShadow = true;obj.receiveShadow = true;} })
四、模型
一個3d模型是由物體形狀及材質組成的網格模型。
通常模型可進行自己搭建及導入模型兩個途徑:
1、模型搭建
①?Geometry 形狀
????????Geometry 通過存儲模型用到的點集和點間關系(哪些點構成一個三角形)來描述物體形狀。
② Material 材質
????????Material 其實是物體表面除了形狀以外所有可視屬性的集合,例如色彩、紋理、光滑度、透明度、反射率、折射率、發光度。③?Mesh 模型
????????Mesh 用三角形組成的網格來描述三維模型,隨著三角形數量的增加,它的表面越來越平滑/準確。
Geometry在threejs中有提供諸如 長方體、圓柱、圓錐等基礎形狀,更為復雜的形狀需自行構建,通常可用以下形狀組成:
④ Point 點
????????Point 在三維空間中的某一個點可以用一個坐標點來表示,點的集合,可以由一組頂點坐標組成。
⑤ Line 線
????????Line 既可以直接定義線條材質,也可以通過定義兩個坐標點,來構造一條線。
⑥ Curve 曲線
????????Curve 平滑的路徑或形狀,可用來創建諸如圓弧、橢圓等形狀。
//創建一個長方體幾何對象Geometry const geometry = new THREE.BoxGeometry(100, 100, 100); //創建一個材質對象Material---MeshBasicMaterial不受光照影響,MeshLambertMaterial受光照影響 const material = new THREE.MeshBasicMaterial({collor: 0xff0000, //0xff0000設置材質顏色為紅色transparent: true, //開啟透明opacity: 0.5, //設置透明度 }); // 兩個參數分別為幾何體geometry、材質material const mesh = new THREE.Mesh(geometry, material); //網格模型對象Mesh //設置網格模型在三維空間中的位置坐標,默認是坐標原點 mesh.position.set(0, 10, 0); // 將網格模型添加到三維場景 scene.add(mesh);/點、線、曲線創建舉例 const point1 = new THREE.Vector3(4,8,9); const line = new THREE.Line( geometry, material, THREE.LinePieces ); const curve= new THREE.EllipseCurve(0, 0, 100, 50); //橢圓中心坐標以及x和y方向半徑
2、模型導入
通常是使用gltf或glb格式的模型文件,可參考3D模型庫:https://sketchfab.com。
//創建GLTFLoader實例 const loader = new GLTFLoader(); //加載gltf、glb模型 loader.load("bydSA3/scene.gltf", (gltf) => {//模型加載成功后的回調函數scene.add(gltf.scene); //將模型添加到場景中},(xhr) => {//加載過程中的回調函數console.log((xhr.loaded / xhr.total)*100+"% loaded");},(error) => {//加載出錯的回調函數console.error("An error happened", error);} );
五、相機控件
相機控件可實現鼠標的左鍵旋轉,滑動鍵縮放,右鍵平移
也可利用相機控件實現模型自轉:
//定義旋轉縮放平移相機控件 const controls = new OrbitControls(camera, renderer.domElement); controls.autoRotate = false; //在animate方法中更新OrbitControls controls.update();controls.autoRotate = true; //模型自轉
六、動畫渲染
動畫渲染需要對場景進行繪制的循環,而其他很多操作都是使用動畫庫tween.js,gasp庫等
// 動畫循環 const animate = () => {//對場景進行繪制的循環requestAnimationFrame(animate);……renderer.render(scene, camera); }; animate();
動畫庫使用舉例:
import TweenLite from "gsap"; // 參數:動畫目標、動作時間、起始狀態(已省略)、終點狀態 TweenLite.to(component1.position, 1.5, {y: 1.5,ease: Power4.easeOut, });
X、資源教程
1、Three.js中文網教程:http://www.webgl3d.cn/
2、Three.js教j程(api文檔):https://threejs.org/docs/
3、web GL中文網:http://www.hewebgl.com/