ThreeJS快速入門
- ThreeJS開發
-
- 學習準備
- 安裝
- 基本使用
-
- 效果圖
- 控制器
- 物體移動
-
- 效果圖
- 物體縮放與旋轉
- Clock跟蹤時間
- Gsap動畫
- 自适應
- Gui
-
- 效果圖
- BufferGeometry(設定頂點)
-
- 設定頂點建立矩形
- 實作三角形
- 材質與紋理
- 标準網格材質
-
- 效果圖
- 環境貼圖
-
- 效果圖
- 燈光與陰影
-
- 效果圖
- 平行光的陰影屬性
- 聚光燈
-
- 效果圖
- 點光源
-
- 效果圖
ThreeJS開發
該教程由本人學習記錄下來的筆記供大家學習
- 初識ThreeJS它是一個web端3D開發的好幫手
- 本人對3D的熱愛探索便前往學習了解了一番
- 特此整理以下筆記供大家參閱
學習準備
這裡我使用vue腳手架去建立的項目
目錄結構:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL3YjZzcTZhRWYmJTZmljMiNzMlRTOxcjM0ITOkRDN1gzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
安裝
這裡可以單獨安裝依賴,我這裡安裝好了,大家隻需要在package.json中放入以下代碼塊
"dependencies": {
"dat.gui": "^0.7.9",
"gsap": "^3.11.0",
"three": "^0.143.0",
"vue": "^3.0.4"
},
- three肯定是必不可少的
- 其次dat.gui是three提供的一款gui界面調試的工具
- gsap是一款動畫庫,用于實作動畫
- vue則是腳手架建立項目時自動安裝好的
放入以上代碼後則使用以下指令進行安裝依賴
npm i
基本使用
這裡簡單使用three實作一個平面圖形
在index.html中編寫代碼并且下方js檔案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Three開發---碰磕</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="./src/3D/threeBasic.js"></script>
</body>
</html>
threeBasic.js
1.引入three.js
2.建立一個場景
3.建立一個相機
設定相機位置x,y,z并放入場景中
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
4.添加物體
這裡建立一個平面圖形
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
5.初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
6.将渲染的内容添加到dom節點中
7、使用渲染器,通過相機将場景渲染進來
以上代碼即可實作簡單的效果
npm run dev
運作看看效果圖吧!!!
效果圖
現在開始一步一步系統學習吧!
控制器
使用控制器檢視3d物體
這裡我就直接貼代碼了,代碼中都給了注釋,index.html中别忘了引入該js
/**
* 使用控制器檢視3d物體
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//編寫渲染函數
function render(){
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
以上代碼即可實作3D效果了,可拉近拉遠,可旋轉
物體移動
實作3d物體移動
/**
* 實作3d物體移動
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
cube.position.x+=0.01;
if(cube.position.x>5){
cube.position.x=0
}
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
- 通過new $Three.AxesHelper(5)建立了坐标軸,使得物體移動看着更清晰
- 再通過控制position去修改它的位置
效果圖
效果圖如下:它是一直在動的哈
物體縮放與旋轉
實作3d物體縮放
/**
* 實作3d物體縮放
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
cube.position.x+=0.01;
cube.scale.x+=0.01;//縮放scale
cube.rotation.x+=0.01//旋轉rotation
if(cube.position.x>5){
cube.position.x=0
cube.scale.x=1
cube.rotation.x=0
}
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
- 旋轉通過控制rotation屬性
- 縮放通過控制scale屬性
以上代碼即可看到該圖形邊變長邊旋轉…
Clock跟蹤時間
/**
* Clock跟蹤時間
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//設定時鐘
const clock=new $Three.Clock();
//編寫渲染函數
function render(){
//擷取時鐘運作的總時長
let time=clock.getElapsedTime();
let deltaTime=clock.getDelta();
// console.log("時鐘運作總時長:",time);
// console.log("兩次擷取時間的間隔::",deltaTime);
let t=time%5;
cube.position.x =t*1;
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
- 以上代碼主要是運用一下Three中的Clock()時鐘
Gsap動畫
gsap設定各種動畫效果
官網:https://github.com/greensock/GSAP
如果沒安裝該依賴則手動安裝一下,跟着教程的話一開始即安裝好了,沒有安裝請安裝
npm install gsap
開始使用:
/**
* gsap設定各種動畫效果
* npm install gsap
* 官網:https://github.com/greensock/GSAP
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//導入動畫庫
import gsap from 'gsap'
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//修改幾何體的位置
// cube.position.set(5,0,0)
// cube.position.x=3;
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//設定時鐘
// const clock=new $Three.Clock();
//設定動畫to(物體的屬性,{需要執行的操作..},ease執行方式,repeat:重複的次數(死循環設定-1),yoyo:往返移動,delay:延遲移動,onComplete:()=>完成執行的回調函數,onStart:()=>動畫開始執行)
var maveposition=gsap.to(cube.position,{x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
console.log("移動完成")
},
onStart:()=>{
console.log("動畫開始")
}
});
window.addEventListener('click',()=>{
//isActive()表示是否在運作移動
if(maveposition.isActive()){
maveposition.pause();//動畫暫停
}else{
maveposition.resume();//動畫繼續
}
})
gsap.to(cube.rotation,{x:2*Math.PI,duration:6,ease: "power1.inOut"})
//編寫渲染函數
function render(){
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
- 如何使用代碼中都進行了注釋,自行看看咯
自适應
以上代碼均沒有做一個自适應處理
- 當你放大縮小頁面時,頁面内容還是保持不變,是以我們要解決這個問題!!!
- 通過監聽畫面變化,更新畫面
/**
* 頁面自适應
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//導入動畫庫
import gsap from 'gsap'
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
//修改幾何體的位置
// cube.position.set(5,0,0)
// cube.position.x=3;
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//設定動畫to(物體的屬性,{需要執行的操作..},ease執行方式,repeat:重複的次數(死循環設定-1),yoyo:往返移動,delay:延遲移動,onComplete:()=>完成執行的回調函數,onStart:()=>動畫開始執行)
var maveposition=gsap.to(cube.position,{x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
console.log("移動完成")
},
onStart:()=>{
console.log("動畫開始")
}
});
window.addEventListener('click',()=>{
//isActive()表示是否在運作移動
if(maveposition.isActive()){
maveposition.pause();//動畫暫停
}else{
maveposition.resume();//動畫繼續
}
})
gsap.to(cube.rotation,{x:2*Math.PI,duration:6,ease: "power1.inOut"})
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
})
- resize表示頁面大小被改變時觸發的事件
Gui
通過gui界面更改參數
沒安裝的話請安裝
npm install --save dat.gui
使用:
/**
* gui界面更改參數
* npm install --save dat.gui
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//導入動畫庫
import gsap from 'gsap'
//導入gui
import * as dat from 'dat.gui'
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BoxGeometry();
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const cube=new $Three.Mesh(cubeGeometry,cubeMaterial);
scene.add(cube)//将幾何體添加到場景中
const gui=new dat.GUI()
gui.add(cube.position,"x").min(0).max(5).step(0.02).name("正方體x坐标").onChange((val)=>{
console.log("你修改了x=",val)
}).onFinishChange((val)=>{
console.log("完全停下來..",val)
})
//修改物體顔色
let params={
color:'#ffff00',
fn:()=>{
gsap.to(cube.rotation,{x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut"})
},
}
gui.addColor(params,'color').onChange((val)=>cube.material.color.set(val));
//設定頁籤
gui.add(cube,'visible').name("是否顯示");
var folder=gui.addFolder("設定立方體");
folder.add(cube.material,"wireframe");
//設定按鈕點選觸發某個事件
gui.add(params,"fn").name("立方體運動")
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//設定時鐘
// const clock=new $Three.Clock();
//設定動畫to(物體的屬性,{需要執行的操作..},ease執行方式,repeat:重複的次數(死循環設定-1),yoyo:往返移動,delay:延遲移動,onComplete:()=>完成執行的回調函數,onStart:()=>動畫開始執行)
var maveposition=gsap.to(cube.position,{x: 5,duration:5,repeat:2,yoyo:true,delay:1,ease: "power1.inOut",
onComplete:()=>{
console.log("移動完成")
},
onStart:()=>{
console.log("動畫開始")
}
});
window.addEventListener('click',()=>{
//isActive()表示是否在運作移動
if(maveposition.isActive()){
maveposition.pause();//動畫暫停
}else{
maveposition.resume();//動畫繼續
}
})
gsap.to(cube.rotation,{x:2*Math.PI,duration:6,ease: "power1.inOut"})
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
效果圖
BufferGeometry(設定頂點)
設定頂點建立矩形
BufferGeometry設定頂點建立矩形
/**
* BufferGeometry設定頂點建立矩形
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//導入動畫庫
import gsap from 'gsap'
//導入gui
import * as dat from 'dat.gui'
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
const cubeGeometry=new $Three.BufferGeometry();
const vertices=new Float32Array([
-1.0,-1.0,1.0,1.0,-1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,-1.0,1.0,1.0,-1.0,-1.0,1.0
]);
cubeGeometry.setAttribute("position",new $Three.BufferAttribute(vertices,3));
const cubeMaterial=new $Three.MeshBasicMaterial({color: 0x00ff00});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const mesh=new $Three.Mesh(cubeGeometry,cubeMaterial)
scene.add(mesh)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
實作三角形
通過循環建立多個角度不同的三角形,要的就是雜亂無章的感覺
/**
* 使用BufferGeometry實作酷炫三角形
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//導入動畫庫
import gsap from 'gsap'
//導入gui
import * as dat from 'dat.gui'
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//3、添加物體
//建立幾何體
for(let i=0;i<50;i++){
const cubeGeometry=new $Three.BufferGeometry();
const positionArr=new Float32Array(9);
//3個頂點(每個頂點3個值)
for(let j=0;j<9;j++){
positionArr[j]=Math.random()*5-1;
}
cubeGeometry.setAttribute("position",new $Three.BufferAttribute(positionArr,3));
let color=new $Three.Color(Math.random(),Math.random(),Math.random());//随機顔色
const cubeMaterial=new $Three.MeshBasicMaterial({color: color,transparent:true,opacity:0.5});//使用基礎材質并設定顔色
//根據幾何體和材質建立物體
const mesh=new $Three.Mesh(cubeGeometry,cubeMaterial)
scene.add(mesh)
}
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
材質與紋理
- 通過enableDamping設定阻尼讓物體有重量感
- 代碼中示範了紋理的一些常用屬性
/**
* 材質與紋理
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//導入紋理
const textureloader=new $Three.TextureLoader();
const myTextloader=textureloader.load('../chunyu02.jpg')//加載本地圖檔
/**
* 紋理常用的屬性
*/
myTextloader.offset.set(0.1,0)//偏移
myTextloader.center.set(0.5,0.5)//旋轉的原點
myTextloader.rotation=Math.PI/4//旋轉45deg
myTextloader.repeat.set(2,3);//重複
myTextloader.wrapS=$Three.RepeatWrapping;//設定重複模式(該值表示無限重複)
//添加物體
const geometry=new $Three.BoxBufferGeometry(1,1,1);
//材質
const basicMaterial=new $Three.MeshBasicMaterial({
color:"#ffff00",
map:myTextloader
})
const cube=new $Three.Mesh(geometry,basicMaterial);
scene.add(cube)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
以上代碼主要是對材質與紋理的一個了解使用
标準網格材質
通過MeshStandardMaterial建立标準網格材質
/**
* 标準網格材質
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
let event={}
//單張紋理圖的加載
event.onLoad=function(){
console.log("加載完成...")
}
event.onProgress=function(e,sum,total){
console.log("正在加載的路徑",e)
console.log("加載進度",sum)
console.log("需要加載的總進度:",total)
console.log("加載進度百分比:",((sum/total)*100).toFixed(2)+'%');
}
event.onError=function(){
console.log("加載失敗")
}
//設定加載管理器
const loadingManager=new $Three.LoadingManager(
event.onLoad,
event.onProgress,
event.onError
);
//導入紋理
const textureloader=new $Three.TextureLoader(loadingManager);
const myTextloader=textureloader.load('../chunyu02.jpg')//event.onLoad,event.onProgress,event.onError加載本地圖檔
/**
* 紋理常用的屬性
*/
myTextloader.offset.set(0.1,0)//偏移
myTextloader.center.set(0.5,0.5)//旋轉的原點
myTextloader.rotation=Math.PI/4//旋轉45deg
myTextloader.repeat.set(2,3);//重複
myTextloader.wrapS=$Three.RepeatWrapping;//設定重複模式(該值表示無限重複)
//添加物體
const geometry=new $Three.BoxBufferGeometry(1,1,1);
//材質
const material=new $Three.MeshStandardMaterial({
color:"#ffff00",
map:myTextloader,
roughness:0,//粗糙度
metalness:0,//金屬度
})
//燈光
const light1=new $Three.AmbientLight(0xffffff,0.5);//環境光
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.position.set(10,10,10)//設定平行光照的位置
scene.add(light2)
const cube=new $Three.Mesh(geometry,material);
scene.add(cube)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
效果圖
環境貼圖
這裡我要推薦一個素材網:[Textures - Poliigon](https://www.poliigon.com/textures)
自行去下載下傳hdr圖檔,這裡再推薦個圖檔格式轉換:
[Convertio — 檔案轉換器](https://www.poliigon.com/textures)
/**
* 環境貼圖
*/
import * as $Three from 'three'
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//加載hdr環境圖
const rgbeLoader=new RGBELoader();
rgbeLoader.loadAsync('./public/HdrOutdoorBeachBlueHourCloudy002_HDR_4K.hdr').then(res=>{
res.mapping=$Three.EquirectangularReflectionMapping;//設定映射
scene.background=res;
scene.environment=res;
})
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
//設定cube紋理加載器
const cubeTextureloader=new $Three.CubeTextureLoader()
// const envMapTexture=cubeTextureloader.load([
// "/public/bg1.jpg",
// "/public/chunyu02.jpg",
// "/public/bg2.jpg",
// "/public/chunyu02.jpg",
// "/public/chunyu02.jpg",
// "/public/chunyu02.jpg",
// ]);
const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const textureloader=new $Three.TextureLoader();
const myTextloader=textureloader.load('./public/HdrOutdoorBeachBlueHourCloudy002_JPG_4K.jpg')
const material=new $Three.MeshStandardMaterial({
metalness: 0.7,
roughness: 0.1,
// envMap:rgbeLoader
map:myTextloader
})
const sphere=new $Three.Mesh(sphereGeo,material);
scene.add(sphere)
//設定環境背景
// scene.background=envMapTexture;
//設定預設環境背景
// scene.environment=envMapTexture;
//燈光
const light1=new $Three.AmbientLight(0xffffff,0.5);//環境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.position.set(10,10,10)//設定平行光照的位置
scene.add(light2)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
- 通過loadAsync異步加載hdr環境圖
- 以上代碼即可實作身臨其境般的感覺
效果圖
還可以360°旋轉呢
燈光與陰影
建立一個平面與一個球實作對燈光以及陰影的使用
/**
* 燈光與陰影
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//設定球投射陰影
scene.add(sphere)
//建立平面
const planeGeo=new $Three.PlaneBufferGeometry(10,10);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;
plane.receiveShadow=true//接收陰影
scene.add(plane)
//燈光
const light1=new $Three.AmbientLight(0xffffff,0.5);//環境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//設定光線投射陰影
light2.position.set(10,10,10)//設定平行光照的位置
scene.add(light2)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//開啟陰影計算
renderer.shadowMap.enabled=true;
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
- castShadow投射陰影
- receiveShadow接收陰影
- renderer.shadowMap.enabled=true;開啟陰影計算
- AmbientLight環境光
- DirectionalLight平行光
效果圖
平行光的陰影屬性
舉例一些常見的
/**
* 平行光陰影屬性
*/
light2.shadow.radius=20;//陰影模糊度
light2.shadow.mapSize.set(1080,1080);//陰影貼圖分辨率(預設512*512)
//設定平行光投影相機的屬性(近端、遠端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
scene.add(light2)
聚光燈
通過SpotLight去建立聚光燈
/**
* 聚光燈
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//設定球投射陰影
scene.add(sphere)
//建立平面
const planeGeo=new $Three.PlaneBufferGeometry(20,20);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;
plane.receiveShadow=true//接收陰影
scene.add(plane)
//燈光
const light1=new $Three.AmbientLight(0xffffff,0.5);//環境光
scene.add(light1)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//設定光線投射陰影
light2.position.set(10,10,10)//設定平行光照的位置
/**
* 平行光陰影屬性
*/
light2.shadow.radius=20;//陰影模糊度
light2.shadow.mapSize.set(1080,1080);//陰影貼圖分辨率(預設512*512)
//設定平行光投影相機的屬性(近端、遠端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
// scene.add(light2)
/**
* 聚光燈
*/
const light3=new $Three.SpotLight(0xffffff,1);
//調節亮度
light3.intensity=3
light3.position.set(5,5,5);
light3.castShadow=true;
light3.shadow.mapSize.set(1080,1080);
light3.target=sphere;//聚光燈照明目标(設定為球)
sphere.position.x=2//球移動聚光燈追随
light3.angle=Math.PI/6;//聚光燈角度(預設180deg/3)
light3.distance=15;//光的衰減效果
light3.penumbra=0;//伴影的衰減效果
light3.decay=0.1;//沿着光照距離的衰減(需要給渲染器設定)
scene.add(light3)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//開啟陰影計算
renderer.shadowMap.enabled=true;
renderer.physicallyCorrectLights=true;//使用實體上正确的光照模式
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//6、使用渲染器,通過相機将場景渲染進來
// renderer.render(scene,camera);
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//編寫渲染函數
function render(){
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
- 以上代碼并且示範了聚光燈的一些屬性
效果圖
點光源
通過PointLight建立
/**
* 點光源
*/
import * as $Three from 'three'
//導入軌道控制器
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls';
//1、建立一個場景
const scene= new $Three.Scene();
//2、建立一個相機
const camera=new $Three.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
//設定相機位置 x,y,z
camera.position.set(0,0,10);
scene.add(camera);//相機放入場景中
const sphereGeo=new $Three.SphereBufferGeometry(1,20,20);
const material=new $Three.MeshStandardMaterial()
const sphere=new $Three.Mesh(sphereGeo,material);
sphere.castShadow=true;//設定球投射陰影
scene.add(sphere)
//建立平面
const planeGeo=new $Three.PlaneBufferGeometry(20,20);
const plane=new $Three.Mesh(planeGeo,material);
plane.position.set(0,-1,0);
plane.rotation.x=-Math.PI/2;
plane.receiveShadow=true//接收陰影
scene.add(plane)
//燈光
const light1=new $Three.AmbientLight(0xffffff,0.5);//環境光
scene.add(light1)
/**
* 添加小球
*/
const smallBall=new $Three.Mesh(
new $Three.SphereBufferGeometry(0.1,20,20),
new $Three.MeshBasicMaterial({color: 0xff0000})
)
smallBall.position.set(2,2,2)
scene.add(smallBall)
const light2=new $Three.DirectionalLight(0xffffff,1)//平行光
light2.castShadow=true;//設定光線投射陰影
light2.position.set(10,10,10)//設定平行光照的位置
/**
* 平行光陰影屬性
*/
light2.shadow.radius=20;//陰影模糊度
light2.shadow.mapSize.set(1080,1080);//陰影貼圖分辨率(預設512*512)
//設定平行光投影相機的屬性(近端、遠端、上、下、左、右)
light2.shadow.camera.near=0.5;
light2.shadow.camera.far=500;
light2.shadow.camera.top=5;
light2.shadow.camera.bottom=-5;
light2.shadow.camera.left=5;
light2.shadow.camera.right=-5;
// scene.add(light2)
/**
* 點光源
*/
const light4=new $Three.PointLight(0xfff00f,1);
light4.intensity=2;
scene.add(light4)
//4、初始化渲染器
const renderer=new $Three.WebGLRenderer();
//設定渲染大小
renderer.setSize(window.innerWidth,window.innerHeight);//寬、高
//開啟陰影計算
renderer.shadowMap.enabled=true;
renderer.physicallyCorrectLights=true;//使用實體上正确的光照模式
//5、将渲染的内容添加到dom節點中
document.body.appendChild(renderer.domElement)
//建立軌道控制器
const controls=new OrbitControls(camera,renderer.domElement);
//設定控制器阻尼,更有重量感,然後必須在動畫循環調用update()
controls.enableDamping=true;
//建立坐标軸
const xy=new $Three.AxesHelper(5);
scene.add(xy);
//設定時鐘
const clock=new $Three.Clock();
//編寫渲染函數
function render(){
let time=clock.getElapsedTime()
smallBall.position.x=Math.sin(time)*3;
smallBall.position.z=Math.cos(time)*3;
smallBall.position.y=2+Math.sin(time*10);
controls.update();//調用update實作阻尼
renderer.render(scene,camera);//每一幀就進行一次渲染...
requestAnimationFrame(render);//浏覽器自帶方法請求幀
}
render();//調用渲染函數
//監聽畫面變化,更新畫面
window.addEventListener('resize',()=>{
//更新攝像頭
camera.aspect=window.innerWidth/window.innerHeight;
//更新攝像頭投影矩陣
camera.updateProjectionMatrix();
//更新渲染器
renderer.setSize(window.innerWidth,window.innerHeight);
//設定渲染像素比
renderer.setPixelRatio(window.devicePixelRatio);
});
- 實作了小球圍繞大球轉
效果圖
一直轉着呢…
了解這些就差不多了,可以去實作一些案例了