unity3d內建著色器原始碼解析(四)

2021-10-17 18:38:42 字數 3413 閱讀 4037

假如需要繪製有很多模型的場景,而大部分模型都是使用的同乙個模型,即他們使用同一組頂點資料,在渲染時指定不同的世界座標,繪製在不同的位置上。例如成千上萬的小草,每顆小草都需要呼叫一次drawcall,此時效能瓶頸在cpu往gpu傳送資料次數過多,因為這些操作都是在相對緩慢的cpu到gpu匯流排上進行的。

如果能夠一次性將資料傳送到gpu,然後使用乙個繪製函式讓渲染流水線利用這些資料繪製多個相同的物體將大大提公升效能,這種技術就是gpu多例化(gpu instancing)技術。directx和opengl等渲染流水線已經實現了這個功能。unity3d引擎在此基礎上進行包裝,使得在每個平台上都能使用同一套**使用gpu多例化技術。以direct3d 11平台為例,當準備好頂點資料、設定好頂點緩衝區後,接下來進入輸入組裝階段(input assemble stage)。輸入組裝階段時使用硬體實現的。此階段根據使用者輸入的頂點緩衝區資訊、圖元拓撲(primitive topology)結構資訊和描述頂點布局(vertice layout)格式資訊,把頂點組裝成圖元,然後傳送給頂點緩衝區。

gpu多例化的思想,就是把每個例項的不同資訊儲存在緩衝區(可能是頂點緩衝區,也可能是儲存著著色器uniform變數的常量緩衝區)中,然後直接操作緩衝區的資料來設定。而不用多例化技術,每次呼叫都是很相似的,除了在設定世界矩陣時,無非就是更新著色器常量緩衝區的某個uniform變數,這裡又是一次cpu到gpu的資料傳遞操作。既然可以在定義頂點資訊結構體時指定每個頂點的法線、切線和紋理對映座標資訊,那完全也可以為每個頂點增加乙個描述世界矩陣的屬性,無非就是在頂點資訊結構體中多加乙個float4x4型別的屬性變數而已。

假設需要渲染100個相同的模型,每個模型有256個三角形,那麼需要兩個緩衝區。乙個用來描述頂點的模型資訊,因為帶渲染的模型是相同的,所以這個緩衝區只儲存了256個三角形(如果不用任何的優化組織方式,則有768個頂點);另乙個就是用來描述模型在世界座標系下的位置資訊,如果不考慮旋轉和縮放,100個模型即占用100個float3型別的儲存空間。

要在unity3d中啟用多例化技術,首先應在材質檔案的inspector面板中選中enable instancing核取方塊。

必須要注意的是,只有材質檔案使用的著色器檔案中宣告了支援gpu多例化技術,材質檔案的inspector面板中才會出現enable instacing核取方塊。引擎提供的standard著色器、standardspecular著色器及所有的外觀著色器都支援gpu多例化技術。下圖展示了使用與未使用gpu多例化技術的效果和效能比較,可見使用了gpu多例化技術後效能大幅提公升。

每一次多例化繪製呼叫(instanced draw call)時,預設地,unity3d僅對使用了同一網格材質,但是有著不同的位置變換資訊的遊戲物件進行批次化。為了讓gpu多例化技術不僅應用在只有不同位置變換資訊的遊戲物件,如材質顏色不同,也可以使用gpu多例化技術。可以在自定義著色器**中新增逐多例(per-instance)屬性。如下**所示。在外觀著色器中給材質顏色變數增加gpu多例化支援的**。

shader "custom/instancedcolorsu***ceshader" 

_glossiness ("smoothness", range(0,1)) = 0.5

_metallic ("metallic", range(0,1)) = 0.0

} subshader

lod 200

cgprogram

// physically based standard lighting model, and enable shadows on all light types

#pragma su***ce surf standard fullforwardshadows

// use shader model 3.0 target, to get nicer looking lighting

#pragma target 3.0

sampler2d _maintex;

struct input ;

half _glossiness;

half _metallic;

// add instancing support for this shader. you need to check 'enable instancing' on materials that use the shader.

// see for more information about instancing.

// #pragma instancing_options assumeuniformscaling

unity_instancing_cbuffer_start(props)

// put more per-instance properties here

unity_define_instanced_prop(fixed4, _color);

unity_instancing_cbuffer_end

void surf (input in, inout su***ceoutputstandard o)

endcg

} fallback "diffuse"

}

上面**使用unity_instancing_buffer_start巨集開始宣告要使用gpu多例化技術的變數,使用unity_define_instanced_prop巨集宣告_color是逐例項變數,使用unity_instancing_buffer_end巨集結束使用技術的宣告。

在c#層設定game object中的多例化材質顏色屬性(逐例項屬性)

materialpropertyblock props = new materialpropertyblock();

meshrenderer renderer;

foreach (gameobject obj in objects)

前文提到預設地外觀著色器是開啟了多例化技術支援的,對於普通的頂點著色器和片元著色器也可以使用此技術,但是要在**中新增關鍵語句。

shader "unlit/******instancedshader"

subshader

lod 100

pass

; struct v2f

;//step4. 宣告多例化屬性變數

//cbuffer unityinstancingprops

unity_instancing_cbuffer_start(props)

unity_define_instanced_prop(fixed4, _color)

unity_instancing_cbuffer_end

fixed4 frag (v2f i) : sv_target

endcg

} }}

Unity3D內建著色器

unity內部提供了一些可以直接使用的著色器,這些內建著色器包括以下6個方面 1 performance of unity shaders specular 高光,強度和camera的觀察角度有關,main tex的alpha通道可以用來做specular map 反射貼圖,也稱gloss map ...

著色器 unity3d教程

unity3d教程手冊 如下圖所示,在project面板中新建乙個new material.這樣子就準備好了乙個空白的著色器。它能支援的型別也就在shader中全部顯示出來。不得不說,很好很強大。所有這些pixel 畫素 著色器,預設的diffuse算是資源開銷較小的渲染選擇。隨後那些帶有凹凸貼圖的...

Unity3D著色器Shader程式設計入門

自學unity3d也有大半年了,對shader一直不敢入坑,最近看了些資料,以及通過自己的實踐,對shader還是有一點了解了,分享下僅作入門參考。狗刨學習網 因shader是對影象影象渲染的,學習前可以去了解下圖形影象學及gpu程式設計相關的知識。強烈推薦 gpu 程式設計與cg 語言之陽春白雪下...