
植被圖集這件事在材質(zhì)圈里一直是個分水嶺。剛?cè)胄心菚何乙詾樽鰳淙~就是找張好看的葉子照片摳出來往模型上一貼就完事。結(jié)果第一次把成品丟進引擎美術(shù)總監(jiān)看了一眼就問我你這樹葉怎么像紙片糊上去的風一吹是不是還得嘩嘩響那一刻我才意識到植被圖集遠不是貼圖兩個字能概括的它牽扯到Alpha通道的精度、法線的朝向、粗糙度的層次、以及整個圖集在引擎里的采樣效率。Substance Designer之所以成為這個環(huán)節(jié)的主力工具核心就在于它能把隨機性和可控性這兩件看似矛盾的事捏到一起——你既要有自然植被那種不規(guī)則的生長感又得保證每一片葉子在UV里規(guī)規(guī)矩矩、不越界、不糊邊。這篇內(nèi)容我打算把整套植被圖集的制作鏈路從頭到尾捋一遍從圖集規(guī)劃、葉片單體生成、法線與粗糙度推導(dǎo)到最終打包導(dǎo)出和引擎驗證。適合已經(jīng)摸過Substance Designer基礎(chǔ)節(jié)點、但一做植被就翻車的朋友也適合想從拼照片轉(zhuǎn)向程序化生成的材質(zhì)從業(yè)者。我不會只給你一串節(jié)點連線而是把每一步為什么這么做講清楚包括我自己踩過的那些坑——比如Alpha邊緣發(fā)灰、法線接縫、圖集打包后采樣模糊這些老問題都會給出具體的排查思路和參數(shù)區(qū)間。1. 植被圖集到底在解決什么問題1.1 從一張葉子一張圖到一張圖集打天下很多人剛開始做植被習(xí)慣一片葉子導(dǎo)出一張貼圖覺得這樣清晰、好管理。但真到了場景里一棵樹幾百片葉子如果每片都獨立貼圖Draw Call會直接爆炸顯存也會被大量重復(fù)的小圖撐滿。植被圖集的核心思路就是把多種葉片、多種朝向、多種破損狀態(tài)全部塞進一張或少數(shù)幾張大圖里讓引擎用同一份材質(zhì)實例去渲染成百上千個面片。這背后的邏輯其實和游戲里的UI圖集、角色裝備圖集是一回事合并采樣源降低狀態(tài)切換開銷。但植被比UI麻煩的地方在于葉片有大量透明區(qū)域Alpha通道的處理直接決定了邊緣質(zhì)量和性能。圖集里如果Alpha分布不合理要么邊緣鋸齒嚴重要么透明區(qū)域浪費了大量像素填充率。我一般會把一張圖集控制在2048×2048或4096×4096具體看項目目標平臺。移動端傾向2048PC和主機可以上4096。圖集內(nèi)部按網(wǎng)格切分比如8×8的格子每格256×256一片葉子占一格或兩格。這樣在UV映射時每片葉子的UV都落在固定區(qū)間內(nèi)方便程序化擺放和LOD切換。1.2 圖集規(guī)劃里最容易被忽略的三個約束第一個約束是Alpha的膨脹邊界。葉片貼圖在采樣時如果UV剛好落在葉片邊緣GPU的雙線性插值會把透明區(qū)域的RGB也混進來導(dǎo)致邊緣發(fā)灰或發(fā)黑。解決辦法是在葉片周圍留出2到4像素的出血區(qū)把葉片的顏色向外膨脹Dilate出去。Substance Designer里有專門的Dilate節(jié)點但很多人忘了在圖集打包之后再做一次全局膨脹。第二個約束是法線的切線空間一致性。圖集里每片葉子的法線都必須是切線空間法線而且朝向要統(tǒng)一。如果你從不同來源拼葉子有的法線是物體空間、有的Y軸朝上有的朝下進引擎后光照會亂成一團。我的做法是在Designer里統(tǒng)一用Normal節(jié)點從高度圖生成保證所有葉片的法線基準一致。第三個約束是Mipmap的衰減。圖集在遠處會觸發(fā)Mipmap如果葉片之間間距太近低級別Mip會把相鄰葉片的顏色混進來出現(xiàn)鬼影。所以圖集里每片葉子之間要留足空隙通常至少8像素重要葉片可以留16像素。1.3 一張合格植被圖集的驗收標準我給自己定的驗收標準有這么幾條Alpha邊緣在放大到400%時不出現(xiàn)明顯灰邊法線在引擎里打光時葉片正反面過渡自然沒有硬接縫粗糙度能區(qū)分出葉面蠟質(zhì)感和葉背的啞光感整張圖集在Mipmap第3級時仍然能辨認出葉片輪廓。這幾條聽起來簡單但真做起來每一條都能卡住不少人。提示驗收時一定要把圖集放進實際引擎場景里看不要只在Designer的2D視圖里判斷。Designer的預(yù)覽和引擎的采樣、光照、Mip策略都有差異很多問題只有進引擎才暴露。2. 葉片單體的程序化生成思路2.1 用形狀節(jié)點搭出葉片的骨架做葉片單體我不建議一上來就畫。程序化的好處是可復(fù)用、可批量變體。我的常規(guī)做法是先用Polygon或Shape節(jié)點搭出葉片的基礎(chǔ)輪廓再用Warp、Directional Warp做邊緣的起伏。葉片的形狀本質(zhì)上是一條主脈加若干側(cè)脈驅(qū)動的所以我會先畫一條從葉柄到葉尖的漸變作為主脈的權(quán)重然后用這個權(quán)重去驅(qū)動邊緣的彎曲。具體節(jié)點鏈路上我通常用Linear Gradient 1做縱向漸變配合Radial Gradient做葉尖的收窄兩者用Blend疊加得到基礎(chǔ)葉形。接著用Directional Warp配合一張噪聲讓邊緣產(chǎn)生自然的鋸齒和波浪。這里噪聲的強度要控制好太強葉子會像被蟲啃過太弱又顯得太塑料。我一般把噪聲強度放在0.05到0.12之間頻率中等偏高。葉柄部分單獨用一條細長的形狀疊加注意葉柄和葉片的連接處要平滑過渡不能有硬邊。我見過不少人葉柄和葉片是兩塊分開的圖形結(jié)果Alpha一合并就出現(xiàn)斷裂。2.2 葉脈的層次感靠高度圖而不是顏色新手常犯的錯誤是把葉脈直接畫在顏色圖上結(jié)果葉片看起來扁平。正確的做法是葉脈主要靠高度圖表達顏色圖只做輕微的明暗輔助。主脈的高度要比葉面高出一點側(cè)脈再低一些形成三級層次主脈 側(cè)脈 葉面。在Designer里我會用幾條不同粗細、不同方向的Gradient Line組合出葉脈網(wǎng)絡(luò)。主脈用一條較粗的線側(cè)脈用多條細線按角度分布。這里可以用Tile Sampler或者Mirror節(jié)點來批量生成對稱的側(cè)脈效率比手動畫高得多。側(cè)脈的角度和間距要有隨機變化完全對稱會顯得假。高度圖的灰度值我一般這樣分配葉面基準0.5側(cè)脈0.6主脈0.75葉柄0.65。這樣從高度圖生成法線后葉脈的立體感剛好不會過于夸張。2.3 顏色變化要模擬真實葉片的不完美真實葉片沒有一片是純色的。向陽面和背陰面、老葉和嫩葉、健康區(qū)域和枯萎邊緣顏色都不一樣。我在顏色階段會疊三層基礎(chǔ)色、漸變變化、局部斑駁?;A(chǔ)色用一張低頻噪聲調(diào)出黃綠到深綠的過渡。漸變變化用縱向漸變模擬葉尖偏黃、葉基偏深。局部斑駁用高頻噪聲配合Levels做出一些枯黃的小斑點。這三層用不同的混合模式疊加基礎(chǔ)色用Normal漸變用Multiply斑駁用Overlay或Soft Light。這里有個經(jīng)驗葉片的顏色飽和度不要拉滿。很多人做出來的葉子綠得發(fā)亮像塑料。真實葉片的飽和度其實偏低尤其是背光面。我通常會把最終顏色的飽和度壓到70%左右再在引擎里靠光照補回來。2.4 用HSL和漸變映射做批量變體一片葉子做完了怎么快速生成幾十種變體我的做法是用HSL節(jié)點配合漸變映射。把基礎(chǔ)葉形和高度圖固定只對顏色層做HSL偏移色相偏移±15度飽和度±20%明度±10%就能得到一批看起來同種但不同株的葉片。再配合漸變映射把綠色映射到秋天的黃橙色系就能快速產(chǎn)出一套秋季變體。這種批量變體的思路在項目里非常實用尤其是需要做季節(jié)變化或者不同生態(tài)環(huán)境的時候。你不需要重新做形狀只需要調(diào)整顏色參數(shù)效率能提升好幾倍。3. 從高度圖推導(dǎo)法線與粗糙度的關(guān)鍵細節(jié)3.1 法線生成不是點一下Normal節(jié)點就完事Substance Designer里從高度圖生成法線用的是Normal節(jié)點但參數(shù)設(shè)置有講究。默認的強度Intensity往往偏大生成的葉脈法線過于銳利進引擎后高光會炸。我一般把強度調(diào)到0.5到0.8之間具體看高度圖的對比度。如果高度圖本身對比就很強強度還要再降。另一個關(guān)鍵是法線的采樣精度。Normal節(jié)點內(nèi)部會對高度圖做差分計算如果高度圖的分辨率不夠或者有噪點法線會出現(xiàn)麻點。解決辦法是在生成法線之前先對高度圖做一次輕微的模糊Blur把高頻噪點壓掉但注意不要模糊過頭否則葉脈細節(jié)就沒了。我通常用Blur HQ Grayscale半徑1到2像素。還有一點法線生成后要檢查接縫問題。如果葉片是左右對稱的法線在對稱軸上可能出現(xiàn)一條硬線。這是因為差分計算在邊界處不連續(xù)。解決辦法是在生成法線前把高度圖做一次Mirror讓邊界連續(xù)生成法線后再裁回來。3.2 粗糙度要區(qū)分葉面和葉背葉片的粗糙度不是均勻的。葉面通常有一層蠟質(zhì)粗糙度偏低大約0.3到0.4葉背的絨毛多粗糙度偏高0.6到0.8。如果整片葉子用同一個粗糙度光照會顯得很平。我的做法是用一張遮罩區(qū)分葉面和葉背。這個遮罩可以從高度圖或者法線的朝向推導(dǎo)出來——葉背通常對應(yīng)法線朝下的區(qū)域。用Normal節(jié)點的輸出做點積或者直接用高度圖的梯度方向判斷。得到遮罩后用兩個不同的灰度值分別填充葉面和葉背再疊加一點噪聲做微觀變化。粗糙度圖里還可以加入一些破損信息比如蟲蛀區(qū)域粗糙度偏高枯萎邊緣粗糙度也偏高。這些細節(jié)雖然小但在近景特寫時能明顯提升真實感。3.3 環(huán)境光遮蔽AO在葉片上的特殊處理葉片的AO和普通物體不一樣。普通物體的AO是凹處暗、凸處亮但葉片很薄正反面的AO會互相影響。如果直接用常規(guī)AO生成葉片會顯得很臟。我的處理方式是AO只做葉脈和葉柄的局部遮蔽葉面大面積保持接近白色。葉脈的凹槽處稍微壓暗葉柄和葉片的連接處壓暗其余區(qū)域不動。這樣進引擎后葉片整體明亮只有細節(jié)處有自然的陰影層次。具體參數(shù)上AO的強度我一般控制在0.15到0.25之間不要超過0.3。超過0.3葉片就會顯得灰蒙蒙的失去通透感。3.4 高度圖、法線、AO三者的先后順序這三者的生成順序不能亂。正確的鏈路是先做高度圖再從高度圖生成法線和AO。因為法線和AO都依賴高度信息如果先做法線再改高度法線就白做了。我見過有人先畫顏色再從顏色反推高度結(jié)果葉脈的立體感完全不對。顏色是表面反射的結(jié)果高度是幾何結(jié)構(gòu)兩者不能互相替代。一定要先把幾何結(jié)構(gòu)高度定下來顏色和粗糙度都是在這個結(jié)構(gòu)上涂上去的。4. 圖集打包與UV布局的實操要點4.1 用Tile Sampler和Transformation 2D做批量擺放圖集打包的核心是把多個葉片單體按網(wǎng)格擺放到一張大圖上。Substance Designer里可以用Tile Sampler配合Transformation 2D來實現(xiàn)。Tile Sampler負責按行列復(fù)制Transformation 2D負責每個實例的旋轉(zhuǎn)、縮放、偏移。我的常規(guī)參數(shù)是8×8網(wǎng)格每個格子256×256葉片在格子內(nèi)居中縮放控制在格子的80%到90%留出邊緣空隙。旋轉(zhuǎn)角度我一般給±15度的隨機范圍讓葉片朝向有變化但不要完全隨機否則UV映射時會很麻煩。這里有個坑Tile Sampler的隨機種子要固定。如果種子是隨機的每次重新生成圖集葉片的位置都會變之前調(diào)好的UV映射就全廢了。所以一旦布局確定立刻把種子鎖死后續(xù)只改葉片內(nèi)容不改布局。4.2 Alpha通道的膨脹與邊緣處理圖集打包完成后Alpha的邊緣處理是最后一道關(guān)。前面提到過葉片周圍要留出血區(qū)但光留還不夠還要做膨脹。Designer里的Dilate節(jié)點可以對RGB做膨脹但Alpha本身也需要處理。我的做法是先把所有葉片的Alpha合并成一張遮罩然后用Dilate節(jié)點對整張圖集的RGB做膨脹膨脹半徑2到4像素。膨脹之后再用這張遮罩去裁剪RGB保證膨脹只發(fā)生在葉片邊緣外側(cè)不會污染葉片內(nèi)部。膨脹的顏色來源要選對。如果膨脹用的是葉片邊緣的顏色效果最好如果用整張圖的平均色邊緣會出現(xiàn)色差。Designer的Dilate節(jié)點有Color Source選項選Nearest或者Average要看具體情況我一般用Nearest邊緣過渡更自然。4.3 UV布局與引擎采樣的對應(yīng)關(guān)系圖集做完最終是要在引擎里用的。UV布局必須和引擎的采樣方式對應(yīng)上。如果引擎用的是標準的UV采樣那圖集里每片葉子的UV區(qū)間要明確標注出來方便美術(shù)在建模時對齊。我通常會在圖集旁邊附一張UV索引圖標出每片葉子對應(yīng)的UV范圍比如第3行第5列對應(yīng)UV 0.25-0.375, 0.5-0.625。這張索引圖不導(dǎo)出到引擎只是內(nèi)部協(xié)作用。有了它建模的人就知道該把哪片葉子的UV對到哪個區(qū)間不會貼錯。另外圖集的邊緣要留至少4像素的空白因為引擎在采樣時可能會因為Mipmap或者各向異性過濾而溢出到圖集邊界外。如果葉片緊貼圖集邊緣采樣時會出現(xiàn)邊緣拉伸或者黑邊。4.4 導(dǎo)出格式與壓縮策略導(dǎo)出的時候顏色圖用sRGB法線和粗糙度用Linear。格式上PC項目我一般用TGA或者PNG做中間格式最終進引擎前再轉(zhuǎn)成平臺支持的壓縮格式。移動端用ASTCPC用BC7主機看具體平臺。Alpha通道的壓縮要特別注意。很多壓縮格式對Alpha的支持不好會導(dǎo)致邊緣質(zhì)量下降。如果項目對邊緣要求高可以考慮把Alpha單獨存一張圖用更高的壓縮質(zhì)量。或者用Alpha Test而不是Alpha Blend這樣對壓縮的容忍度更高。注意導(dǎo)出前一定要在Designer里把圖集的色彩空間設(shè)置檢查一遍。顏色圖如果誤設(shè)成Linear進引擎后會偏暗法線如果誤設(shè)成sRGB光照會完全錯亂。這個錯誤非常常見而且排查起來很費時間。5. 進引擎后的驗證與常見翻車現(xiàn)場5.1 邊緣發(fā)灰、發(fā)黑的排查鏈路邊緣發(fā)灰是植被圖集最經(jīng)典的問題。排查的時候按這個順序走先看Alpha邊緣有沒有膨脹再看Mipmap設(shè)置最后看材質(zhì)的混合模式。如果Alpha沒膨脹邊緣采樣時會把透明區(qū)域的黑色混進來導(dǎo)致發(fā)黑。如果膨脹了還發(fā)灰那可能是Mipmap的問題——低級別Mip把葉片和背景混在一起了。解決辦法是給Alpha通道單獨設(shè)置Mipmap偏移或者用Alpha Test配合較高的Cutoff值。還有一種情況是材質(zhì)的混合模式設(shè)成了Alpha Blend但圖集的Alpha是硬邊0或1這樣邊緣會有半透明的過渡帶看起來發(fā)灰。這種情況要么改用Alpha Test要么把Alpha的邊緣做成漸變。5.2 法線接縫與光照異常的定位法線接縫通常出現(xiàn)在葉片的對稱軸或者圖集的格子邊界。如果接縫在葉片內(nèi)部多半是高度圖在對稱軸處不連續(xù)導(dǎo)致的。如果接縫在圖集格子邊界那是相鄰葉片的法線互相干擾了。定位方法是在引擎里把法線圖單獨顯示出來放大看接縫位置。如果是高度圖的問題回Designer重新生成法線生成前做Mirror。如果是格子邊界的問題檢查圖集里葉片之間的間距加大到16像素以上。光照異常還有一種可能是切線空間不匹配。如果模型導(dǎo)入引擎時切線空間設(shè)置和Designer生成法線時的假設(shè)不一致光照會整體偏斜。這種情況要檢查模型的切線導(dǎo)入設(shè)置確保和法線的切線空間對齊。5.3 遠處Mipmap導(dǎo)致的鬼影與模糊遠處葉片模糊、出現(xiàn)鬼影是Mipmap的典型癥狀。圖集里葉片之間如果間距不夠低級別Mip會把相鄰葉片的顏色混進來形成鬼影。解決辦法有兩個一是加大葉片間距二是給圖集設(shè)置合適的Mipmap生成策略。我一般會在引擎里給植被圖集的Mipmap做一點銳化或者用Sharpen過濾。有些引擎支持Mipmap Bias可以稍微偏移一下讓遠處葉片更清晰。但注意不要偏移太多否則會出現(xiàn)閃爍。另外如果項目支持可以用Virtual Texture或者Streaming Texture來管理植被圖集這樣遠處葉片可以加載更低分辨率的版本既省顯存又減少鬼影。5.4 性能與畫質(zhì)的平衡取舍植被圖集最終是要跑在實時的場景里的性能和畫質(zhì)必須平衡。我的經(jīng)驗是近景葉片用高分辨率圖集遠景用低分辨率或者簡化的圖集??梢詼蕚鋬商讏D集一套2048給近景一套512給遠景引擎根據(jù)距離切換。Alpha Test的Cutoff值也要調(diào)。Cutoff太低邊緣保留太多透明區(qū)域的Overdraw嚴重Cutoff太高葉片邊緣會被裁掉顯得稀疏。我一般把Cutoff設(shè)在0.3到0.5之間具體看葉片的Alpha分布。還有一點如果場景里葉片數(shù)量極大可以考慮用Billboard或者Impostor技術(shù)把遠處的整棵樹渲染成一張面向相機的貼圖。這樣能大幅降低面數(shù)和Draw Call代價是旋轉(zhuǎn)視角時會有輕微的紙片感。6. 我踩過的幾個典型坑與應(yīng)對經(jīng)驗6.1 圖集打包后顏色變臟的問題有一次我做完圖集在Designer里看顏色很正常導(dǎo)出進引擎后整體偏暗、偏臟。排查了半天發(fā)現(xiàn)是圖集的色彩空間在導(dǎo)出時被改了。Designer默認的工作空間是Linear但顏色圖需要sRGB。導(dǎo)出時如果沒勾選正確的色彩空間轉(zhuǎn)換顏色就會偏。后來我養(yǎng)成了一個習(xí)慣在Designer里給顏色圖單獨加一個Color Space節(jié)點明確標記為sRGB導(dǎo)出時就不會錯。法線和粗糙度則保持Linear不加轉(zhuǎn)換。6.2 葉片朝向不一致導(dǎo)致的光照錯亂早期做圖集我從不同項目里拼了幾片葉子結(jié)果進引擎后有的葉子亮、有的葉子暗打光完全不對。原因是這些葉子的法線朝向不一致有的Y軸朝上有的朝下。解決辦法是統(tǒng)一法線基準。所有葉片的高度圖都按同一個方向生成法線Y軸統(tǒng)一朝上。如果某片葉子需要反向不要翻轉(zhuǎn)法線而是翻轉(zhuǎn)UV或者旋轉(zhuǎn)模型。這樣能保證圖集里所有葉片的法線在同一個切線空間里。6.3 Alpha膨脹過度導(dǎo)致的邊緣發(fā)胖膨脹是個雙刃劍。膨脹不夠邊緣發(fā)灰膨脹過度葉片邊緣會發(fā)胖看起來比實際大一圈。我一開始為了保險把膨脹半徑設(shè)得很大結(jié)果葉片邊緣多了一圈半透明的光暈。后來我把膨脹半徑控制在2到3像素并且膨脹后立刻用原始Alpha做一次裁剪把膨脹超出葉片輪廓的部分切掉。這樣既保證了邊緣顏色又不會讓葉片變形。6.4 圖集分辨率與顯存的權(quán)衡4096的圖集確實清晰但顯存占用也大。一張4096的RGBA圖集未壓縮時是64MB壓縮后也有16MB左右。如果項目里有多套植被圖集顯存很快就吃緊了。我的做法是按植被類型分圖集而不是把所有植被塞進一張。比如闊葉樹一套、針葉樹一套、灌木一套、草一套。每套圖集控制在2048這樣顯存壓力小而且不同植被可以用不同的材質(zhì)參數(shù)靈活性更高。6.5 從Designer到引擎的迭代效率問題最后說一個流程上的經(jīng)驗。很多人做植被圖集是在Designer里做完導(dǎo)出進引擎看效果不滿意再回Designer改再導(dǎo)出再進引擎。這個循環(huán)很慢一天改不了幾次。我的優(yōu)化方式是在Designer里把關(guān)鍵參數(shù)暴露成參數(shù)節(jié)點Parameter比如顏色偏移、粗糙度范圍、膨脹半徑。這樣在引擎里如果發(fā)現(xiàn)小問題可以先通過材質(zhì)參數(shù)微調(diào)不用回Designer重新導(dǎo)出。只有結(jié)構(gòu)性的改動才回Designer。這個習(xí)慣能省下大量時間尤其是項目后期頻繁調(diào)優(yōu)的階段。植被圖集這個活兒說到底是在自然感和工程約束之間找平衡。程序化生成給了你批量產(chǎn)出的能力但真正決定質(zhì)量的還是你對葉片結(jié)構(gòu)的理解和對引擎采樣行為的預(yù)判。我做了這么多年每次做新圖集還是會有新的小坑冒出來但只要把高度、法線、Alpha這三條線守住大部分問題都能在排查鏈路里找到答案。