日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

由浅到浅入门批量渲染(三)

發(fā)布時(shí)間:2024/9/3 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 由浅到浅入门批量渲染(三) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上回簡(jiǎn)單總結(jié)了一下動(dòng)態(tài)合批,這次我們繼續(xù)說(shuō)說(shuō)實(shí)例化渲染

| 實(shí)例化渲染

當(dāng)我們想要呈現(xiàn)這樣的場(chǎng)景:一片茂密的森林、廣闊的草原或崎嶇的山路時(shí),會(huì)發(fā)現(xiàn)在這些場(chǎng)景中存在大量重復(fù)性元素:樹(shù)木、草和巖石。

仙境怕是也不過(guò)如此吧

它們都使用了相同的模型,或者模型的種類(lèi)很少,比如:樹(shù)可能只有幾種;但為了做出差異化,它們的顏色略有不同,高低參差不齊,當(dāng)然位置也各不相同。

使用靜態(tài)合批來(lái)處理它們(假設(shè)它們都沒(méi)有動(dòng)畫(huà)),是不合適的。因?yàn)?strong>數(shù)量太多(林子大了,多少樹(shù)都有),所以合并后的網(wǎng)格體積可能非常大,這會(huì)引起內(nèi)存的增加;而且,這個(gè)合并后的網(wǎng)格還是由大量重復(fù)網(wǎng)格組成的,不劃算。

使用動(dòng)態(tài)合批來(lái)處理他們,雖然不會(huì)“合并”網(wǎng)格,但是仍然需要在渲染前遍歷所有頂點(diǎn),進(jìn)行空間變換的操作;雖然單顆樹(shù)、石頭的頂點(diǎn)數(shù)量可能不多,但由于數(shù)量很多,所以也會(huì)在一定程度上增加CPU性能的開(kāi)銷(xiāo),沒(méi)必要。

那么,對(duì)于場(chǎng)景中這些模型重復(fù)數(shù)量多的渲染需求,有沒(méi)有適合的批處理策略呢?有吧,實(shí)例化渲染就是為了解決這樣的問(wèn)題。

| 簡(jiǎn)述工作原理

實(shí)例化渲染,是通過(guò)調(diào)用“特殊”的渲染接口,由GPU完成的“批處理”。

它與傳統(tǒng)的渲染方式相比,最大的差別在于:調(diào)用渲染命令時(shí)需要告知GPU這次渲染的次數(shù)(繪制N個(gè))。當(dāng)GPU接到這個(gè)命令時(shí),就會(huì)連續(xù)繪制N個(gè)物體到我們的屏幕上,其效率遠(yuǎn)高于連續(xù)調(diào)用N次傳統(tǒng)渲染命令的和(一次繪制一個(gè))。

舉個(gè)例子,假設(shè)希望在屏幕上繪制出兩個(gè)顏色、位置均不同的箱子。如果使用傳統(tǒng)的渲染,則需要調(diào)用兩次渲染命令(DrawCall = 2),分別為:畫(huà)一個(gè)紅箱子 和 畫(huà)一個(gè)綠箱子。

兩個(gè)顏色、位置各異的箱子

如果使用實(shí)例化渲染,則只需要調(diào)用一次渲染命令(DrawCall = 1),并且附帶一個(gè)參數(shù)2(表示繪制兩個(gè))即可。

當(dāng)然,如果只是這樣,那GPU就會(huì)把兩個(gè)箱子畫(huà)在相同的位置上。所以我們還需要告訴GPU兩個(gè)箱子各自的位置(其實(shí)是轉(zhuǎn)換矩陣)以及顏色

這個(gè)位置和顏色我們會(huì)按照數(shù)組的方式傳遞給GPU,大概這個(gè)樣子吧:

分別傳遞保存位置和顏色的數(shù)組

那接下來(lái)GPU在進(jìn)行渲染時(shí),就會(huì)在渲染每一個(gè)箱子的時(shí)候,根據(jù)當(dāng)前箱子的索引(第幾個(gè)),拿到正確的屬性(位置、顏色)來(lái)進(jìn)行繪制了。

一個(gè)簡(jiǎn)單的實(shí)例化渲染流程


?

| Unity是如何處理實(shí)例化的

我們通過(guò)一個(gè)簡(jiǎn)單的場(chǎng)景,來(lái)看一下Unity為實(shí)例化渲染做了什么。

實(shí)例化渲染兩個(gè)彩色箱子

顏色屬性通過(guò)MaterialPropertyBlock傳入

通過(guò)GPA觀察Unity做了什么。

GPA中的VertexBuffer和IndexBuffer中的信息

注:Unity默認(rèn)Cube網(wǎng)格,包含24個(gè)頂點(diǎn)和36個(gè)索引。

  • 頂點(diǎn)緩沖區(qū)Size = (Position(float3) + Normal(float3) + Tangent(float4) + TexCoord(float2) + TexCoord1(float2)) x 24 = 1344Byte
  • 索引緩沖區(qū)Size = Index(ushort) x 36 = 72Byte

可見(jiàn),頂點(diǎn)、索引緩沖區(qū)內(nèi),確實(shí)只有一個(gè)網(wǎng)格的數(shù)據(jù)。

那么GPU如何判斷每個(gè)Cube的繪制位置,及其顏色呢?

結(jié)合引擎為Dx平臺(tái)生成的shader(我的測(cè)試環(huán)境使用的是Pc),可以很容易找到對(duì)應(yīng)的數(shù)據(jù)。

轉(zhuǎn)換矩陣及顏色被分別填入Constant Buffer中

Constant Buffer中的矩陣(Dx為行向量)

Constant Buffer中的屬性(顏色)

可見(jiàn),渲染時(shí)GPU可以通過(guò)當(dāng)前實(shí)例化單位的索引,二手手游賬號(hào)轉(zhuǎn)讓平臺(tái)從Buffer中獲取到對(duì)應(yīng)的屬性,完成正確的繪制。

| Unity中啟用實(shí)例化渲染

當(dāng)然,相比于上述無(wú)用的知識(shí)點(diǎn),如何在Unity中使用實(shí)例化渲染可能更為重要。

在Unity中可以通過(guò)自動(dòng)或手動(dòng)的方式,啟用實(shí)例化渲染。

自動(dòng)啟用實(shí)例化渲染

使用支持實(shí)例化渲染的Shader,并勾選材質(zhì)球上的啟用開(kāi)關(guān),Unity便會(huì)對(duì)滿(mǎn)足條件的物體,自動(dòng)開(kāi)啟實(shí)例化渲染。

有這個(gè)選項(xiàng)即表示該Shader支持實(shí)例化渲染

自定義Shader

如果你希望自己的Shader也支持實(shí)例化渲染,應(yīng)重點(diǎn)注意以下內(nèi)容:
?

#pragma multi_compile_instancing

啟用實(shí)例化渲染(材質(zhì)球上將出現(xiàn)啟用實(shí)例化的勾選框);

UNITY_VERTEX_INPUT_INSTANCE_ID

在a2v及v2f的結(jié)構(gòu)中定義實(shí)例化索引下標(biāo)(SV_InstanceID?),也就是當(dāng)前渲染單位的索引,用于從Constant?Buffer中提取正確的屬性(做顯示差異化用);

UNITY_INSTANCING_BUFFER_START ~ END

在這個(gè)起止區(qū)域內(nèi)定義屬性,才能在著色器中正確的根據(jù)索引提取出當(dāng)前渲染單位所對(duì)應(yīng)的屬性;

UNITY_SETUP_INSTANCE_ID

定義在著色器的起始位置,使頂點(diǎn)著色器(或片段著色器)可以正確的訪(fǎng)問(wèn)到實(shí)例化單位的索引;

UNITY_ACCESS_INSTANCED_PROP

根據(jù)索引訪(fǎng)問(wèn)到這個(gè)單位對(duì)應(yīng)的屬性,如上面例子中每個(gè)箱子的顏色屬性。

這里只是簡(jiǎn)述一些相對(duì)重要的內(nèi)容(湊些字?jǐn)?shù)),官方文檔中有更詳細(xì)內(nèi)容,建議優(yōu)先了解。

手動(dòng)實(shí)例化渲染

使用??Graphics.DrawMeshInstanced?和?Graphics.DrawMeshInstancedIndirect?來(lái)手動(dòng)執(zhí)行 GPU 實(shí)例化,詳見(jiàn)官方文檔中的解釋,這里就不再贅述了。

| 實(shí)例化渲染的使用要求

并非所有設(shè)備都可以使用實(shí)例化渲染。

在Unity官方文檔中,列舉了各平臺(tái)支持實(shí)例化渲染的最低要求。

官方文檔中對(duì)實(shí)例化渲染的最低API支持要求

當(dāng)然,我們也可以通過(guò)引擎中SystemInfo.supportsInstancing屬性來(lái)判斷環(huán)境是否支持實(shí)例化渲染。

那支持實(shí)例化渲染的機(jī)器占比大概是多少呢?由于國(guó)內(nèi)大多數(shù)游戲公司都是以手游項(xiàng)目糊口。所以開(kāi)發(fā)者可能會(huì)更多關(guān)注其在安卓平臺(tái)上的情況。

根據(jù)Android開(kāi)發(fā)者的官方數(shù)據(jù)顯示,截至2020年8月30日,約88%的活躍安卓設(shè)備,都已經(jīng)支持實(shí)例化渲染,所以基本上可以放心使用。

android開(kāi)發(fā)者官網(wǎng)發(fā)布的活躍設(shè)備OpenGL ES版本占比信息

| 與靜、動(dòng)態(tài)合批的差異

靜、動(dòng)態(tài)合批實(shí)質(zhì)上是將可以合批的對(duì)象真正的合并成一個(gè)大物體后,再通知GPU進(jìn)行渲染,也就是其頂點(diǎn)索引緩沖區(qū)中必須包含全部參與合批對(duì)象的頂點(diǎn)信息;因此,可以認(rèn)為是CPU完成的批處理。
?

實(shí)例化渲染是對(duì)網(wǎng)格信息的重復(fù)利用,無(wú)論最終要渲染出幾個(gè)單位,其頂點(diǎn)和索引緩沖區(qū)內(nèi)都只有一份數(shù)據(jù),可以認(rèn)為是GPU完成的批處理。


其實(shí)這么總結(jié)也有點(diǎn)問(wèn)題,本質(zhì)上講:動(dòng)、靜態(tài)合批解決的是合批問(wèn)題,也就是先有大量存在的單位,再通過(guò)一些手段合并成為批次;而實(shí)例化渲染其實(shí)是個(gè)復(fù)制的事兒,是從少量復(fù)制為大量,只是利用了它“可以通過(guò)傳入屬性實(shí)現(xiàn)差異化”的特點(diǎn),在某些條件下達(dá)到了與合批相同的效果。

| 簡(jiǎn)單總結(jié)靜、動(dòng)態(tài)合批及實(shí)例化渲染

無(wú)論是靜態(tài)合批、動(dòng)態(tài)合批或?qū)嵗秩?#xff0c;本質(zhì)上并無(wú)孰優(yōu)孰劣,它們都只是提高渲染效率的解決方案,也都有自己適合的場(chǎng)景或擅長(zhǎng)解決的問(wèn)題。

個(gè)人以為:

如果你的場(chǎng)景中存在多數(shù)靜止的、使用了不同網(wǎng)格、相同材質(zhì)的物體,特別是當(dāng)你的相機(jī)通常只能照到一部分物體時(shí)(如第一視角),可以?xún)?yōu)先嘗試下靜態(tài)合批,通過(guò)犧牲一些內(nèi)存來(lái)提升渲染效率;

針對(duì)那些運(yùn)動(dòng)的、網(wǎng)格頂點(diǎn)數(shù)很少、材質(zhì)相同的物體,比如飛行的各種箭矢、炮彈等,使用動(dòng)態(tài)合批,通過(guò)增加一些CPU處理頂點(diǎn)的性能開(kāi)銷(xiāo),來(lái)提升渲染效率,也許是不錯(cuò)的選擇;

如果有大量模型相同、材質(zhì)相同、或盡管表現(xiàn)上有一些不同,但仍然可以通過(guò)屬性來(lái)實(shí)現(xiàn)這些差異化的物體時(shí),啟用實(shí)例化渲染通常可以在很大程度上提升渲染效率。

| 寫(xiě)在最后

按計(jì)劃下次更新的內(nèi)容應(yīng)該是“優(yōu)化骨骼蒙皮動(dòng)畫(huà),以及兩種常用的批量渲染方式”,但覺(jué)得內(nèi)容有點(diǎn)多,所以將其分為兩個(gè)部分;因此,下次更新的內(nèi)容變?yōu)椤皟?yōu)化骨骼蒙皮動(dòng)畫(huà)”,而“兩種常用的骨骼蒙皮動(dòng)畫(huà)單位的批量渲染方式”,將作為本系列的最后一次更新內(nèi)容。

總結(jié)

以上是生活随笔為你收集整理的由浅到浅入门批量渲染(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。