上篇文章?前端開發(fā)者掌握3d技術不再是夢,初識threejs 作為three.js入門篇講解了許多內容但是沒有深入了解其原理以及實現方法,僅僅只是展示了實現的內容及代碼,本篇文章將深入講解實現效果其背后用到的知識與原理。
目錄
使用相機控件軌道控制器
理解光源影響
環(huán)境光
點光源
聚光燈光源
平行光
燈光與陰影的關系設置
使用相機控件軌道控制器
平時開發(fā)調試代碼或者展示模型的時候,可以通過相機控件 OrbitControls 實現旋轉縮放預覽效果
旋轉:拖動鼠標左鍵、縮放:滾動鼠標中鍵、平移:拖動鼠標右鍵。使用控件步驟如下:
引入第三方控件js文件,如下:
// 導入軌道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
使用OrbitControls,可以參考一下官方文檔對這方面的知識進行的講解,如下:
創(chuàng)建軌道控制器之后,創(chuàng)設置好的照相機和要觀察的物體對象作為參數傳入,并每次經過渲染函數的調用還實現查看物體方向的作用:
// 創(chuàng)建軌道控制器
new OrbitControls(camera,renderer.domElement)
export function render(){
// 使用渲染器,通過相機將場景渲染出來
renderer.render(scene,camera)
// 接下來渲染下一幀的時候就會調用render函數
requestAnimationFrame(render)
}
// 先開始就渲染一下
render()
理解光源影響
實際生活中物體表面的明暗效果是會受到光照的影響,threejs中同樣也要模擬光照Light對網絡模型Mesh表面的影響,threejs提供的網格材質,有的受光照影響,有的不受光照影響,其用到的網絡材質如下:
如果你設置的是不受光照影響的網格材質,做不做光源都沒有影響,物體表面顏色基本沒啥區(qū)別,但是你一旦設置了受光照影響的網格材質,就必須做光源,否則物體是不顯示的,這很容易理解啊,在黑夜中你是看不見物體的,只有有了光源你才能看到物體,這是一個道理。
Three.js提供了多種模擬生活中光源的API,在官方文檔中搜索關鍵詞 light 就可以看到,如下:
環(huán)境光
環(huán)境光 AmbientLight 沒有特定的方向,只是整體改變場景的光照明暗。按我個人的理解就是,環(huán)境光就相當于太陽光,雖然不能有很強的光照強度,但是其能照亮每一處地方,如下:
點光源
點光源顧名思義,就是一個點向各個方向發(fā)散光源,其相關函數設置可參考官方文檔。
可以看到下圖的樣式,我將點光源的位置設置在y坐標軸上,被點光源照射的地方呈現物體原本的顏色,而沒有被照射的地方則呈現出黑色,如下:
雖然大家可能知道事是這么回事,但是不知道事的人是真不知道這事是怎么回事,為了讓不知道事的人知道這是怎么回事,我們可以這么會事,通過點光源輔助觀察對象 PointLightHelper 來可視化光源,如下:
搭配環(huán)境光的話,效果更明顯,如下:
聚光燈光源
聚光燈光源就是一個點沿著一個方向射出,隨著光線照射的變遠,光線圓錐體的尺寸也逐漸變大
// 聚光燈光源
const spotLight = new THREE.SpotLight(0xffffff,0.5)
spotLight.position.set(10,5,5)
spotLight.castShadow = true
// 從聚光燈的位置以弧度表示聚光燈的最大范圍
spotLight.angle = Math.PI / 6
// 設置光源隨著距離的衰減程度
spotLight.distance = 100
// 設置聚光錐的半影衰減百分比
spotLight.penumbra = 0
// 設置沿著光照距離的衰減量
spotLight.decay = 0
scene.add(spotLight)
平行光
平行光 DirectionalLight 就是沿著特定方向發(fā)射,如下:
平行光與Mesh表面光線是存在反射規(guī)律的,平行光照射到網格模型Mesh表面,光線和模型表面構成一個入射角度,入射角度的不同,對光照的反射能力不同,光線照射到漫反射網絡材質對應Mesh表面,Mesh表面對光線反射程度取決于入射角度,如下:
燈光與陰影的關系設置
在進行3d建模的時候,我們也可以給物體設置一個陰影,這樣讓3d立體的效果更加明顯,我在第一篇文章也講解到了關于陰影的設置,接下來我將詳細講解一下添加陰影的步驟。注意:添加陰影一定不要使用環(huán)境光作為光源,因為環(huán)境光是沒有方向的;當然也不要使用基礎網格材質,因為這種材質是不受光照影響的。如果要做到燈光與影響需要做到以下步驟:
1)材質要滿足能夠對光照有反應,光源不選擇環(huán)境光
2)設置渲染器開啟陰影的計算:renderer.shadowMap.enabled = true
3)設置光照投射投影:directionalLight.castShadow = true
4)設置物體投射陰影:sphere.castShadow = true
5)設置物體接收陰影:plane.receiveShadow = true
陰影屬性:我們除了能設置陰影以外,我們還可以給陰影添加一些屬性,讓陰影的呈現更具有靈活性,如下:
radius:將此值設置大于1的值將模糊陰影的邊緣。
mapSize:定義陰影貼圖的寬度和高度。
當然我們也可以設置投射相機的屬性來改變陰影的效果,后面文章講解的gui庫可以結合這個動態(tài)的改變值的大小,這樣的效果更加明顯。
// 設置投射相機的屬性
pointLight.shadow.camera.near = 0.5
pointLight.shadow.camera.far = 500
pointLight.shadow.camera.top = 5
pointLight.shadow.camera.bottom = -5
pointLight.shadow.camera.left = -5
pointLight.shadow.camera.right = 5
當然每次修改相關值之后,必須調用更新攝像機投影矩陣。
文章來源:http://www.zghlxwxcb.cn/news/detail-437558.html
仔細對比一下光源對物體的影響。給出本文完整代碼,如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-437558.html
import * as THREE from 'three';
// 導入軌道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
// 1.創(chuàng)建場景
const scene = new THREE.Scene();
// 2.創(chuàng)建相機
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.添加物體,創(chuàng)建幾何體
const cubeGeometry = new THREE.BoxGeometry(1,1,1) // 設置幾何體大小
const cubeMaterial = new THREE.MeshLambertMaterial({color:0xff0000}) // 設置幾何體材質
// 根據幾何體和材質創(chuàng)建物體
const cube = new THREE.Mesh(cubeGeometry,cubeMaterial)
// 修改物體的位置
cube.position.y = 1.5
cube.rotation.set(Math.PI / 4,0,0,"XYZ")
// 物體投射投影
cube.castShadow = true
// 將幾何體添加到場景之中
scene.add(cube)
// 4.初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 設置渲染的尺寸大小
renderer.setSize(window.innerWidth,window.innerHeight)
// 開啟場景中的陰影貼圖
renderer.shadowMap.enabled = true
// 將webgl渲染的canvas內容添加到body上
document.body.appendChild(renderer.domElement)
// 創(chuàng)建地面網格參照
const planeGeometry = new THREE.PlaneGeometry(30,30) // 平面幾何的寬高
const PlaneMateial = new THREE.MeshStandardMaterial({color:0xF8F8FF}) // 幾何平面的顏色
const plane = new THREE.Mesh(planeGeometry,PlaneMateial)
plane.rotation.x = -0.5*Math.PI
plane.position.set(0,0,0)
// 平面接收投影
plane.receiveShadow = true
scene.add(plane)
// 添加一個環(huán)境光
const ambient = new THREE.AmbientLight(0xffffff,0.2)
scene.add(ambient)
// 創(chuàng)建一個點光源
const pointLight = new THREE.PointLight(0xffffff,1.0)
// 設置點光源位置
pointLight.position.set(0,5,0)
// 設置光照投影
pointLight.castShadow = true
// 設置陰影貼圖模糊度
pointLight.shadow.radius = 20
// 設置陰影貼圖的分辨率
pointLight.shadow.mapSize.set(4096,4096)
// 設置點光源投射相機的屬性
pointLight.shadow.camera.near = 0.5
pointLight.shadow.camera.far = 500
pointLight.shadow.camera.top = 5
pointLight.shadow.camera.bottom = -5
pointLight.shadow.camera.left = -5
pointLight.shadow.camera.right = 5
scene.add(pointLight)
// 可視化點光源
const pointLightHelper = new THREE.PointLightHelper( pointLight, 0.1 );
scene.add(pointLightHelper)
// // 聚光燈光源
// const spotLight = new THREE.SpotLight(0xffffff,0.5)
// spotLight.position.set(10,5,5)
// spotLight.castShadow = true
// // 從聚光燈的位置以弧度表示聚光燈的最大范圍
// spotLight.angle = Math.PI / 6
// // 設置光源隨著距離的衰減程度
// spotLight.distance = 100
// // 設置聚光錐的半影衰減百分比
// spotLight.penumbra = 0
// // 設置沿著光照距離的衰減量
// spotLight.decay = 0
// scene.add(spotLight)
// // 添加一個平行光
// const directionalLight = new THREE.DirectionalLight(0xffffff,1)
// // 設置光源方向
// directionalLight.position.set(8,10,5)
// // 方向光指向對象網格模型Mesh,即照射的對象,可以不設置,默認的位置是0,0,0
// directionalLight.target = cube
// scene.add(directionalLight)
// // 可視化平行光
// const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight,5,0xff0000)
// scene.add(dirLightHelper)
// 添加坐標軸輔助器
const axesHelper = new THREE.AxesHelper(5) // 數值代表線的長度
scene.add(axesHelper) // 添加到場景之中
// 創(chuàng)建軌道控制器
new OrbitControls(camera,renderer.domElement)
export function render(){
cube.position.x +=0.01
cube.rotation.x +=0.01
if(cube.position.x>5){
cube.position.x = 0
}
// 使用渲染器,通過相機將場景渲染出來
renderer.render(scene,camera)
// 接下來渲染下一幀的時候就會調用render函數
requestAnimationFrame(render)
}
// 先開始就渲染一下
render()
到了這里,關于Three.js--》理解光源對物體產生影響的重要性的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!