threejs太陽光與陰影效果實例代碼
前言
這篇文章實現(xiàn)智慧城市中模擬太陽光隨時間變化產(chǎn)生對應(yīng)場景效果。為了場景能夠更逼真,我們一般會通過對接天氣以及陽光等各種環(huán)境因素同步到場景中,使得場景能夠更貼近現(xiàn)實。比如一些常見的天氣系統(tǒng),下雨、下雪、陰天、霧霾等,我之后會獨立一篇文章中提現(xiàn)。這邊文章主要介紹一系列燈光,主要是平行光對于太陽的模仿,以及一些材質(zhì)的問題~
燈光與材質(zhì)基礎(chǔ)篇
常見的燈光:
- 點光源 (點光源可以理解為一個同時向四面八方散發(fā)光線,我們通常用來模擬燈泡,可以產(chǎn)生陰影)
- 平行光 (平行光可以想象成一個從無限遠(yuǎn)照射來的光束,通常用來模擬太陽光,可以產(chǎn)生陰影)
- 聚光燈 (聚光燈字面意思就是類似舞臺燈光一樣,照射突出特定圓弧形范圍,可以產(chǎn)生陰影)
- 環(huán)境光 (一般用于改變整體場景的亮度,也是最常用的光源之一)
這里提一嘴材質(zhì):(僅僅列舉常用的)
- 網(wǎng)格基礎(chǔ)材質(zhì)(MeshBasicMaterial,不支持陰影)
- FBR材質(zhì)
- 物理標(biāo)準(zhǔn)材質(zhì)(MeshStandardMaterial)
- MeshPhysicalMaterial
- 以上兩者FBR材質(zhì)相對于高光網(wǎng)格材質(zhì)效果更好
- MeshPhongMaterial(高光網(wǎng)格材質(zhì),高亮表面、鏡面反射)
- MeshLambertMaterial(網(wǎng)格Lambert材質(zhì),暗淡,漫反射)
這里簡單做一下介紹,不懂的同學(xué)可以具體去了解某個材質(zhì)
太陽光
添加平行光-----從東至西調(diào)整位置-----調(diào)整亮度以及顏色-----添加過渡模擬太陽光
接下來介紹本文的重點,如何模擬太陽光照的變化。其實原理非常簡單,就是添加平行光,調(diào)整場景模型的陰影關(guān)系,根據(jù)時間實時變化平行光的位置以及光照強度以及顏色即可模擬~
整體調(diào)用代碼
由于是一個demo,所以注重效果,一切從簡實現(xiàn)功能
sun() { //兩秒變化一次平行光
let i=0
setInterval(()=>{
this.initSun(i)
i++
},2000)
}簡單實現(xiàn)通過定時器以及提前寫好對應(yīng)位置光照的信息。主要是思想,酌情根據(jù)自己的需求可以改變~
這里這么寫主要是實現(xiàn)效果,真實的應(yīng)該根據(jù)系統(tǒng)時間將太陽光做出調(diào)整,包括根據(jù)天氣原因,換湯不換藥,主要還是
手動調(diào)整并存儲為json通過傳入時間以及天氣去做出轉(zhuǎn)化~
Viewer.prototype.initSun = function (type) {
let position = {}
let color = '#ffffff'
let intensity = 1
switch (type) {
case 0:
position = {
x: 270,
y: 150,
z: 0
}
intensity = 5
break
case 1:
position = {
x: 258,
y: 170,
z: 0
}
intensity = 7
color = '#fcffc9'
break
case 2:
position = {
x: 245,
y: 180,
z: 0
}
intensity = 10
color = '#ffe69f'
break
case 3:
position = {
x: 0,
y: 100,
z: 0
}
intensity = 15
color = '#ffe69f'
break
case 4:
position = {
x: -245,
y: 180,
z: 0
}
intensity = 10
color = '#e3894d'
break
case 5:
position = {
x: -258,
y: 160,
z: 0
}
intensity = 10
color = '#ff8400'
break
default :
position = {
x: -270,
y: 150,
z: 0
}
intensity = 8
color = '#ff8400'
break
}
if (this.directionalLight) {
this.directionalLight.setSun(position,color,intensity)
} else {
this.directionalLight = new zhdSun()
this.directionalLight.renderFn(this.renderFunction)
this.directionalLight.init({
position,
color,
intensity,
scene: this.scene,
currentlayers: this.currentlayers
})
}
}太陽光類
這里主要對太陽光類的拆解與分析,封裝的比較粗糙,酌情個人可以優(yōu)化
import TWEEN from '@tweenjs/tween.js'
import {zhdObject} from './zhdObject'
export class zhdSun extends zhdObject {
constructor() {
super()
this.light = null
}
}
//由于添加了TWEEN動畫庫,記得在animate中實時更新TWEEN
TWEEN.update()初始化
這里做的是向場景中添加平行光,設(shè)置其陰影的范圍以及距離等屬性,因為我這邊涉及層級,所以設(shè)置了平行光的層級
平行光可謂是所有燈光中陰影調(diào)整最麻煩的,想要平行光能夠產(chǎn)生對的陰影效果,模型的產(chǎn)生陰影以及接收陰影要調(diào)整好,并且平行光的照射范圍也要調(diào)整好。我效果圖中不知大家有沒有發(fā)現(xiàn),在正午時刻的時候太陽光照射地面產(chǎn)生了一個長方形的范圍陰影,這里是特地錄制一個相對不那么完美的版本。
產(chǎn)生原因:平行光范圍太小,但是一旦你調(diào)整平行光范圍過大,由于地面是通過多個瓦片加載的,就會出現(xiàn)條紋狀的陰影
如下圖
解決方法:調(diào)整平行光陰影的bias屬性,有助于減少陰影中的偽影

init({position, color, intensity , currentlayers, scene}) {
const directionalLight = new THREE.DirectionalLight(color, intensity) // 新建一個平行光源,顏色未白色,強度為1
this.light = directionalLight
directionalLight.position.set(position.x, position.y, position.z) // 將此平行光源調(diào)整到一個合適的位置
directionalLight.castShadow = true // 將此平行光源產(chǎn)生陰影的屬性打開
// 設(shè)置平行光的的陰影屬性,即一個長方體的長寬高,在設(shè)定值的范圍內(nèi)的物體才會產(chǎn)生陰影
const d =100 //陰影范圍
directionalLight.shadow.camera.left = -d
directionalLight.shadow.camera.right = d
directionalLight.shadow.camera.top = d
directionalLight.shadow.camera.bottom = -d
directionalLight.shadow.camera.near = 20
directionalLight.shadow.camera.far = 8000
directionalLight.shadow.mapSize.x = 2048 // 定義陰影貼圖的寬度和高度,必須為2的整數(shù)此冪
directionalLight.shadow.mapSize.y = 2048 // 較高的值會以計算時間為代價提供更好的陰影質(zhì)量
directionalLight.shadow.bias = -0.0005 //解決條紋陰影的出現(xiàn)
this.setlayers(directionalLight, currentlayers)
scene.add(directionalLight) // 將此平行光源加入場景中,我們才可以看到這個光源
return directionalLight
}設(shè)置平行光信息
設(shè)置平行光的信息:包括位置、顏色、強度
setSun(position, color, intensity) {
this.setTweens(this.light.position, position, 2000)
this.light.color = new THREE.Color( color )
this.light.intensity = intensity
}Tween
這里簡單介紹TWEEN不懂的可以去看我之前的文章,主要是一個動畫庫,這里做簡單的封裝
setTweens(obj, newObj, duration = 1500) {
var ro = new TWEEN.Tween(obj)
ro.to(newObj, duration) // 變化后的位置以及動畫時間
ro.easing(TWEEN.Easing.Sinusoidal.InOut)
ro.onUpdate(function () {
})
ro.start()
}總結(jié)
到此這篇關(guān)于threejs太陽光與陰影效果的文章就介紹到這了,更多相關(guān)threejs太陽光與陰影內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js中console在一行內(nèi)打印字符串和對象的方法
這篇文章主要介紹了js中console在一行內(nèi)打印字符串和對象的方法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09
JS數(shù)組去重常用方法實例小結(jié)【4種方法】
這篇文章主要介紹了JS數(shù)組去重常用方法,結(jié)合實例形式總結(jié)分析了4種常用的數(shù)據(jù)去重實現(xiàn)方法,涉及javascript數(shù)組的遍歷、判斷、追加等相關(guān)操作技巧,需要的朋友可以參考下2018-05-05
js的math中缺少的數(shù)學(xué)方法小結(jié)
JavaScript?Math對象包含一些真正有用且強大的數(shù)學(xué)運算,但它缺乏大多數(shù)其他語言提供的許多重要運算,例如求和,乘積,奇數(shù)和偶數(shù)等等,本文就來介紹一下2023-08-08
UEditor 自定義圖片視頻尺寸校驗功能的實現(xiàn)代碼
UEditor支持單圖、多圖以及視頻上傳,編輯器配置項支持文件格式、文件大小校驗,對于文件寬高尺寸校驗暫不支持。本文給大家介紹UEditor 自定義圖片視頻尺寸校驗功能的實現(xiàn)代碼,感興趣的朋友一起看看吧2020-10-10
JS實現(xiàn)瀏覽器狀態(tài)欄文字閃爍效果的方法
這篇文章主要介紹了JS實現(xiàn)瀏覽器狀態(tài)欄文字閃爍效果的方法,通過時間函數(shù)定時觸發(fā)遞歸調(diào)用實現(xiàn)狀態(tài)欄文字閃爍效果,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10

