最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Unity烘焙:光照貼圖分場(chǎng)景烘焙與綜合加載

2023-03-19 22:43 作者:叁拾柒渡伍  | 我要投稿

前言

???????文章的內(nèi)容在于分享在Unity中如何對(duì)一整套模型分批烘焙,最后再綜合加載的,以及加載后存在的問(wèn)題。不會(huì)詳細(xì)的講解烘焙參數(shù)以及方法相關(guān)的知識(shí),對(duì)這方面知識(shí)有需求的小伙伴可以自行查看其他資料。

???????最后再補(bǔ)充一點(diǎn),這里只是分享分場(chǎng)景烘焙與綜合加載的方法,至于在實(shí)際項(xiàng)目中是否實(shí)際可行,就需要小伙伴根據(jù)自己項(xiàng)目自行考慮啦。

? ? 如果我分享的內(nèi)容存在問(wèn)題也請(qǐng)大伙指正,我會(huì)及時(shí)修改,好了讓我們開(kāi)始正文吧。

? ?部分借鑒:https://blog.csdn.net/Tel17610887670/article/details/113181709

????該文章部分代碼并未涉及,完全照做達(dá)不到最后的效果,部分內(nèi)容據(jù)說(shuō)需要下載示例工程。至少我木得積分,并沒(méi)有下載。

正文

????????首先介紹一下我的環(huán)境以及使用的素材給大伙一個(gè)參考:

????????????1、Unity 3D版本: 2020.3.30f1c1

????????????2、模型素材:Asset Store中的"Medieval Tavern Pack"(免費(fèi)

????????準(zhǔn)備工作就已經(jīng)結(jié)束了。

? ??????先來(lái)看一眼原始場(chǎng)景、整體烘焙后場(chǎng)景和分場(chǎng)景烘焙綜合加載效果。文章的核心在于分享方案,所以請(qǐng)自動(dòng)忽略這個(gè)效果不好的問(wèn)題.....【實(shí)在是能力有限】

未烘焙
整體烘焙

分場(chǎng)景烘焙綜合加載(截完才發(fā)現(xiàn)這不是Game視口但是不影響)

????????烘焙的相關(guān)知識(shí)這里不會(huì)展開(kāi)講解,因?yàn)檫@是一個(gè)比較大的內(nèi)容,如果有需要可以單獨(dú)開(kāi)一篇來(lái)進(jìn)行講解。所以下面只會(huì)對(duì)關(guān)鍵面板進(jìn)行截圖展示并告訴大家修改某些參數(shù),至于具體功能和其他參數(shù)這里不做過(guò)多贅述。

????????這里稍微說(shuō)一下烘焙的方式,有基礎(chǔ)小伙伴可以跳過(guò)。這里不對(duì)燈光和烘焙參數(shù)做過(guò)多的設(shè)置。

????????首先我們找到自己的模型文件,將所有用到的模型的“Generate Lightmap UVs”勾選,點(diǎn)擊“Apply”為我們的模型生成光照UV,如果不做這一步,能會(huì)造成烘焙效果不正確,當(dāng)然省略這一步會(huì)不會(huì)影響我們后續(xù)的操作,但是為了效果還是建議勾選。

“Generate Lightmap UVs”設(shè)置

????????將場(chǎng)景中所有模型勾選“Static”,否則烘焙后無(wú)法得到想要的數(shù)據(jù)。

勾選“Static”

????? ? 將燈光的模式改為“Baked”,稍微調(diào)高光強(qiáng)和間接光強(qiáng)。

燈光模式,光強(qiáng)和間接光強(qiáng)


?????????Lighting面板可以在頂部菜單欄"Window->Rendering->Lighting"打開(kāi)。

????????然后在Lighting面板新生成一個(gè)“Lighting Settings”,勾選“Mixed Lighting”下的“Baked Global illumination”選項(xiàng),并將“Lighting Mode”設(shè)置為“Shadowmask”.


????????這個(gè)地方建議大家選用較小的模型來(lái)測(cè)試,模型的大小直接決定我們的烘焙速度。將"Lightmapper" 改為“Progressive GPU(Preview)”可以增加速度(我的電腦能快5-10倍),如果場(chǎng)景不大,其他的選項(xiàng)可以不改。

????最后點(diǎn)擊“Generate Lighting”開(kāi)始烘焙。順便提一下,關(guān)閉“Auto Generate”。

????這些數(shù)值不重要,可以照著填,也可以不改。

烘焙

????????接下來(lái),讓我們看看場(chǎng)景烘焙完以后會(huì)的得到些什么。我這里是把場(chǎng)景分成了3份,3個(gè)場(chǎng)景分別烘焙的。所以會(huì)有3個(gè)文件夾。如果你沒(méi)有分,就只會(huì)得到1個(gè)。這個(gè)地方解釋一下,希望不要給讀者造成困擾。

烘焙得到的內(nèi)容

????????烘焙完成后,會(huì)在場(chǎng)景同級(jí)目錄中生成一個(gè)同名文件夾,用來(lái)存放場(chǎng)景的烘焙數(shù)據(jù)類似光照貼圖等。光照貼圖會(huì)被加載到"Lighting"-“Baked Lightmaps”下。

????????再來(lái)看一下場(chǎng)景中的模型是如何利用這些光照貼圖的??梢钥吹剑姹汉蟮摹癕esh Renderer”組件下的“Lightmapping”多了一個(gè)“Baked Lightmap”,并且他還記錄著光照貼圖序號(hào)(Lightmap Index)和Tilling/Offset等,這就是我們想要的東西。

烘焙前


烘焙后:使用第1張

烘焙后:使用第2張

????????

所有光照貼圖展示

????????到這里相信已經(jīng)有許多小伙伴已經(jīng)知道我們最后應(yīng)該怎么實(shí)現(xiàn)了,一定想迫不及待的自己試一下。

????????沒(méi)錯(cuò)!就是你想的那個(gè)樣子?。。?/span>

????????下面進(jìn)入我們的代碼環(huán)節(jié),為了讓小伙伴們方便的復(fù)現(xiàn),所有的代碼我都會(huì)完整的貼出來(lái)并且寫(xiě)好注釋,爭(zhēng)取讓大伙都看的明白我每一步想要干什么,至于代碼的優(yōu)化問(wèn)題,我相信小伙伴們都可以完成的,這里就以易讀為主了。


? 代碼部分

?????實(shí)現(xiàn)思路

????????1、? 獲取對(duì)象的? “Mesh Renderer”,并且保存“Lightmap Index”,“l(fā)ightmapScaleOffset”(“Tilling”與“Offset”)。

????????2、往“綜合場(chǎng)景”按照一定的順序加載所有的光照貼圖。

????????3、將第一步記錄的數(shù)據(jù)在“綜合場(chǎng)景”還原。

????實(shí)現(xiàn)與詳解

????首先我們需要分割場(chǎng)景,并將分割后的模型分辨放入不同的場(chǎng)景,但是要保證各場(chǎng)景的燈光數(shù)值相同。

????然后分別點(diǎn)擊烘焙,得到三個(gè)上邊講過(guò)的烘焙數(shù)據(jù)文件夾。

????先將場(chǎng)景的模型放到統(tǒng)一父物體下,并且做成預(yù)制體,放到Resources目錄下,這很重要,否則后續(xù)的操作大概率會(huì)失敗。

“LightMapData”存儲(chǔ)每個(gè)對(duì)象的數(shù)據(jù),會(huì)統(tǒng)一存入“SubSceneLightMapData”

[Serializable]

public class LightMapData

{

? ? //Mesh Renderer組件

? ? public MeshRenderer meshRenderer;

? ? //引用的光照貼圖在本場(chǎng)景的下標(biāo)( MeshRenderer.lightmapIndex)

? ? public int lightmapIndex;

? ? //“Tilling”與“Offset”他們合并成一個(gè)Vector4返回(MeshRenderer.lightmapScaleOffset)

? ? public Vector4 lightmapScaleOffset;


? ?public LightMapData(MeshRenderer meshRenderer)

? ? {

? ? ? ? this.meshRenderer = meshRenderer;//略? ? ? ?

? ? ? ? lightmapIndex = meshRenderer.lightmapIndex;//略

? ? ? ? lightmapScaleOffset = meshRenderer.lightmapScaleOffset;//略

? ? }

}

“SubSceneLightMapData”記錄場(chǎng)景中所有的光照貼圖和各個(gè)物體的信息

public class SubSceneLightMapData : MonoBehaviour

{

? ? //起始下標(biāo)。假如當(dāng)前是第二個(gè)場(chǎng)景,第一個(gè)場(chǎng)景加載了5張光照,那么起始下標(biāo)就是5。在綜合加載時(shí)使用

? ? public int startIndex;

? ? //本場(chǎng)景的所需要的光照貼圖集合

? ? public List<Texture2D> subLightMaps = new List<Texture2D>();

? ? //本場(chǎng)景所有的模型對(duì)象以及光照信息

? ? public List<LightMapData> lightMaps = new List<LightMapData>();

????//在組件的菜單中增加一個(gè)選項(xiàng),不理解的可以直接抄

? ? [ContextMenu("執(zhí)行函數(shù)")]

? ? public void ExecuteAction()

? ? {

? ? ? ? LoadSubSceneLightMap();

? ? ? ? GetLightMapData(transform);

? ?//代碼自動(dòng)保存預(yù)制體,如果感覺(jué)波浪線不好看,可以不寫(xiě)手動(dòng)保存

? ? ? ? if (PrefabUtility.GetPrefabParent(gameObject) != null)

? ? ? ? {

? ? ? ? ? ? PrefabUtility.ReplacePrefab(gameObject, PrefabUtility.GetPrefabParent(gameObject), ReplacePrefabOptions.ConnectToPrefab);

? ? ? ? }

? ? }

? ? //加載本場(chǎng)景的光照貼圖

? ? void LoadSubSceneLightMap()

? ? {

? ? ? ? foreach (var item in LightmapSettings.lightmaps)

? ? ? ? {

? ? ? ? ? ? subLightMaps.Add(item.lightmapColor);

? ? ? ? }

? ? }

? ? //判斷節(jié)點(diǎn)是否具有Mesh Renderer,保存相關(guān)數(shù)據(jù),并判斷當(dāng)前節(jié)點(diǎn)是否具有子節(jié)點(diǎn),如果有那么遞歸操作。

? ? private void GetLightMapData(Transform node)

? ? {

? ? ? ? if (node.gameObject.isStatic)

? ? ? ? {

? ? ? ? ? ? var render = node.GetComponent<MeshRenderer>();

? ? ? ? ? ? if (render != null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? lightMaps.Add(new LightMapData(render));

? ? ? ? ? ? }

? ? ? ? ? ? for (int i = 0; i < node.childCount; i++)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? GetLightMapData(node.GetChild(i));

? ? ? ? ? ? }

? ? ? ? }

? ? }

? ? //綜合加載時(shí),將對(duì)應(yīng)的光照貼圖數(shù)據(jù)再還原回去

? ? public void SetAllLightmapData()

? ? {

? ? ? ? if (lightMaps == null) return;

? ? ? ? for (int i = 0; i < lightMaps.Count; i++)

? ? ? ? {

? ? ? ? ? ? //綜合加載時(shí),光照貼圖的順序要隨著加載順序發(fā)生變化

? ? ? ? ? ? lightMaps[i].meshRenderer.lightmapIndex = lightMaps[i].lightmapIndex + startIndex;

? ? ? ? ? ? lightMaps[i].meshRenderer.lightmapScaleOffset = lightMaps[i].lightmapScaleOffset;

? ? ? ? }

? ? }

}

掛載到最頂級(jí)對(duì)象上,執(zhí)行函數(shù)。

執(zhí)行前
執(zhí)行后

一定記得保存預(yù)制體!雖然代碼里有自動(dòng)保存,但還是再說(shuō)一遍!

最后一個(gè)腳本“SceneLightMapControl”,加載所有的預(yù)制體,光照截圖,為每個(gè)子場(chǎng)景的預(yù)制體設(shè)置一個(gè)正確的順序。

public class SceneLightMapControl : MonoBehaviour

{

? ? //已經(jīng)加載的光照貼圖的數(shù)量,一會(huì)要賦值給SubSceneLightMapData使用

? ? public int lightmapCount = 0;

? ? //光照貼圖總集合

? ? public List<Texture2D> Templightmaps=new List<Texture2D>();

? ? private void Start()

? ? {

? ? ? ? LoadSubPrefab();

? ? }

? ? public void LoadSubPrefab()

? ? {

? ? ? ? LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional;

? ? ? ? //為了方便加載我將預(yù)制體存放在Resources根目錄下,分成了三份。

? ? ? ? for (int i = 0; i < 3; i++)

? ? ? ? {

? ? ? ? ? ? GameObject go = Instantiate(Resources.Load<GameObject>("Part" + i));

? ? ? ? ? ? go.GetComponent<SubSceneLightMapData>().startIndex = lightmapCount;

? ? ? ? ? ? //獲取子場(chǎng)景所有的光照貼圖

? ? ? ? ? ? foreach (var item in go.GetComponent<SubSceneLightMapData>().subLightMaps)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? Templightmaps.Add(item);

? ? ? ? ? ? }

? ? ? ? ? ? go.GetComponent<SubSceneLightMapData>().SetAllLightmapData();

? ? ? ? ? ? //更新起始下標(biāo)

? ? ? ? ? ? lightmapCount = Templightmaps.Count;

? ? ? ? }

? ? ? ? List<LightmapData> lightMapArray = new List<LightmapData>();

? ? ? ? for (int i = 0; i < Templightmaps.Count; i++)

? ? ? ? {

? ? ? ? ? ? LightmapData lm = new LightmapData();

? ? ? ? ? ? lm.lightmapColor = Templightmaps[i];

? ? ? ? ? ? lightMapArray.Add(lm);

? ? ? ? }

? ? ? ? //將光照貼圖重新賦值

? ? ? ? LightmapSettings.lightmaps = lightMapArray.ToArray();

? ? }

}

OK,下載將“SceneLightMapControl?”掛到場(chǎng)景中運(yùn)行就可以看到效果了

運(yùn)行前
運(yùn)行后

現(xiàn)在我們的功能就已經(jīng)全部實(shí)現(xiàn)了。


后話

????如果最后加載出來(lái)的場(chǎng)景光影不正常如下圖所示,請(qǐng)檢查加載的貼圖順序是否正常。

全部只使用第一張和第二張

另外這種分場(chǎng)景烘焙的方案存在一定的缺陷,比如連續(xù)的陰影存在缺陷

問(wèn)題1
問(wèn)題2

對(duì)于這種情況,只能請(qǐng)美術(shù)大佬想想辦法給我們找補(bǔ)一下了。?

但是更建議我們?cè)诓鸱种熬瓦x擇不產(chǎn)生陰影的地方做分割或者不易被發(fā)現(xiàn)的地方分割。


好了今天的內(nèi)容就到這里,有問(wèn)題或者文章有錯(cuò)誤請(qǐng)?jiān)谠u(píng)論區(qū)內(nèi)留言,我會(huì)及時(shí)改正的!

我們下期再見(jiàn)!

Unity烘焙:光照貼圖分場(chǎng)景烘焙與綜合加載的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
启东市| 宜宾县| 白朗县| 武宁县| 资中县| 吴堡县| 娱乐| 姚安县| 新兴县| 桂平市| 高唐县| 兖州市| 南陵县| 滦南县| 商洛市| 磴口县| 赤水市| 昆山市| 郧西县| 太谷县| 大邑县| 辉南县| 达孜县| 灌云县| 建宁县| 冕宁县| 葫芦岛市| 鄯善县| 卢氏县| 邮箱| 菏泽市| 永靖县| 常州市| 东源县| 历史| 长丰县| 英山县| 岐山县| 永清县| 鸡西市| 大理市|