創作內容

0 GP

Unity Shader 可控制 Transform 的 DrawmeshinstancedIndirect

作者:Funcy│2018-03-25 17:35:26│巴幣:0│人氣:948
研究Unity Shader一段時間了
終於稍微開竅後,便開始著手整理去年一直有在構想的優化神器:
GPU Instancing DrawmeshinstancedIndirect 的方式新增數千個物件
並可用控制每個 Instancing 物件的Transform
官方資料:

官方只有提供簡易的SurfaceShader VertexFragmentShaderInstancing示例
且只能控制物件的position
因此我將官方的Standard Shader 整理成了可編譯VertexFragment Shader的版本
並附加上了可以支援 DrawmeshinstancedIndirect 、控制 Transform 的功能。

Demo:

因為程式碼的量很多 所以我只針對我認為的關鍵點進行說明
流程:

Shader:
1.整理 StandardShader 成至可以客製化 VertexShader的形式
2.賦予 StandardShader Instancing 功能
3.宣告float4x4儲存C#帶進來的Transform轉換矩陣,並宣告頂點的BufferCount
4.指認Shader每個產生的VertexBuffer 對應的轉換矩陣

C# : 這邊比較單純只要把每個 Transform position 代進 positionBuffer
再把每個TransformlocalToWorldMatrix 代進 Shaderfloat4x4陣列中就可以了
因為腳本衍伸自官方的C#文件,所以會穿插在以下的Shader說明。

Shader部分:

1.整理 StandardShader 成至可以客製化 VertexShader的形式
請參考我之前的文章:


2.賦予 StandardShader Instancing 功能

看過官方的文件後,我發現賦予 Shader Instancing 功能其實非常簡單,
只需要在頂點著色器階段新增一個 instanceID,並宣告一個positionBuffer
儲存C#代進來的物件座標

一般的Shader 在頂點著色階段時,是把頂點轉成MVP空間,一般都會看到
o.pos = mul(UNITY_MATRIX_MVP , v.vertex) 或是 o.pos = UnityObjectToClipPos(v.vertex)
兩者意思是一樣的,都是把由顯卡輸出的頂點座標,由物件空間轉換成MVP空間(ModelViewProjector)
///
但在instancing Shader就比較特別了,它的座標轉換空間是這樣寫的
先宣告一個四維座標data紀錄C#代進來的座標資訊

再宣告localPositionworldPosition 來截取Instancing出的Model頂點座標
這兩行依我弱弱的理解,應該是把逐頂點的座標,乘以一個經神秘處理的w
會說它神秘是因為它在C#代近來時都是1,經Buffer階段後就可以把每個vertex位移到模型給個頂點所在的位置;然後在把喬好的逐頂點,加上代進來的3維座標,就是新生成的模型位置

最後把頂點作標轉換到MVP空間;
這邊就不是用UnityObjectToClipPos(v.vertex)了,而是把世界空間轉成MVP空間,因為輸入端是世界空間。


加上這幾行後,一個Instancing Shader 就完成了! 對,沒看錯,真的就改這幾行而已。

3.宣告float4x4儲存C#帶進來的Transform轉換矩陣,並宣告頂點的BufferCount +
4.指認Shader每個產生的VertexBuffer 對應的轉換矩陣

這邊我在Shader宣告了一個 float4x4 陣列與 一個整數vertexBufferCount分別儲存
每個Transform代進來的 Matrix4x4 mesh的頂點 Buffer 數量


C#端我是這樣代的


positionBuffer 官方文件就有了,我就不再贅述
為了讓Instancing後的模型,有正確的旋轉與縮放,我代入了vertexBufferCount與每個Transform localToWorldMatrix。大家可能會很疑惑 while (matrixlist.Count < 512) 這個迴圈是作什麼用的?
會加這行是因為經測試,不把 transformMatrix[512] 這個陣列填滿,會跳出警告訊息,而這個警告訊息會導致ShaderCompiled時卡住不動,在卡住時就不會繼續Instancing了,故加上此。

再來就是指認每個Instancing Model的矩陣了,這邊就是關鍵點了,經反覆思考、測試後得出來只有這樣寫,才能正確的指認每個Instancing ModelTransform

上下兩行在前面就有提到了,我在這兩行中間插入了座標空間的轉換
指認正確的轉換矩陣,要先知到在逐頂點執行時,instanceID代表的數字是什麼?
經測試後我發現它對應的是vertexBufferIndex,所以我才會把vertexBufferCount代近來,
確保我的每個Transform 矩陣確實代進每個Instancing Model


這邊有兩個我想聊一下的問題:
1.依我的寫法,一個材質球最多只能Instancing  512個 Model,雖然可以靠新增材質球的方式解決,但這並不治本

2.官方的 Instancing  vertexShader 示例,有限制 Shader target 必須是4.5以上,但經測試後,我發現只需要target 3.0以上就可以跑Instancing  Shader 了(2017.1.0 版例外);
會發現這個純粹是因為我發現我的GTX1060竟然不支援 target4.5 的 Shader 有人有遇過一樣的情況嗎?

以上,謝謝你耐心看完

2018/03/28
更新自答問題2
看了一下官方的說明後,我發現這個問題,只有在把Build Setting 切換到mobile系列才會發生,並且所有版本在Android底下 均不能運行target 4.5
但是只有2017.x.x系列不能夠在target 3.0的情況下運行GPU Instancing,5.6.x 卻可以,跟顯卡沒有關係。
2018/03/28
再次更新 需要target 4.5的API 是C#中的ComputeBuffer
DrawmeshinstancedIndirect 必須使用一個argsBuffer 如果要支持Android 可能要另尋方案了
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3932531
All rights reserved. 版權所有,保留一切權利

相關創作

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

喜歡★w96396355557 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:Unity 5 可客製化...

追蹤私訊切換新版閱覽

作品資料夾

face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】