聊聊如何正確向Compute Shader傳遞數組
來自專欄 Runtime
22 人贊了文章
0x00 前言
因為前一段時間去英國出差,所以有日子沒有更新專欄了。只好利用中秋假期來補交作業,順便祝大家中秋節快樂。
在這篇文章中,我選擇了過去幾周Unity官方社區交流群以及UUG社區群中比較有代表性的幾個問題,總結在這裡和大家進行分享。主要涵蓋了UGUI、Lighting、Profiler、Shader Graph、SRP、Compute Shader、GLES等領域。
同時,也歡迎大家加入我們這個討論乾貨的官方技術群,交流看法分享經驗。
Unity官方社區交流群:629212643
0x01 UGUI
Q1:陳老師。我發現個問題。Unity 2018.2.3以後的幾乎所有版本的inputfield沒辦法輸入部分中文字元,比如「我」,我今天試了好多好多版本。2017是確定沒有這個問題的。但是2018我從高到低裝了好多。2018.1.9不存在這個問題。
A:Hi,這是一個已知的2018.2的Bug。Bug的原因是由於2018.2中將16bit的C# char截成了8bit的C++ char。我們會在2018.3中修復該問題,並且之後會Backport回2018.2的版本。
Q2:有一個UGUI做的prefab,每次apply之後第一個slider總是會錯位,有遇到的嗎?Unity版本2017.3.0f3。
0x02 Lighting
Q1: 最近場景要做烘焙陰影動態載入,嘗試了下mixed燈光下烘焙出來的shadowmask貼圖添加到lightmapping中沒辦法正常顯示出來。看結構已經和取數值出來的時候是一模一樣了。網上看到有人說,shadowmask需要保留光源在場景中,否則會顯示失敗。想了解是不是真的需要保留燈光。或者有其他做法可以動態載入shadowmask。
A: shadowmask是mixed光照模式的一種,並且它保存的是mask信息,而不是真實的光照產生的陰影效果。在mixed-shadowmask光照模式下,需要light來提供直接光,再利用陰影mask來生產陰影。
如果想要關閉光照,可以考慮使用mixed-subtractive模式或者bake模式。將直接光照結果預先烘焙到貼圖上。
Q2:我有兩個場景。第一個場景烘焙ok,第二個場景複製的第一個場景,然後加了點新的傢具,再烘焙就都是黑的。而且場景內對象的light probes選項也不能勾選。LightMap沒有丟失,就是烘焙出來都是黑的。
A:不能勾選light probe是因為你的物體設置了Lightmap static的flag,所以它的lighting信息會烘焙到Lightmap上,而不是從Light Probe中獲取。
當然,如果是針對LOD Group的烘焙,在勾選了Lightmap static後,還是可以在模型上勾選light probe的,這是因為LOD需要light probe來提供間接光。
烘焙後模型變黑的問題,首先要確認是否為模型設置了UV2數據。這是因為烘焙時需要UV2數據。其次,可以檢查一下模型的Shader中是否包含Meta Pass。
可以參考:Material properties and the GI system
同時,還需要檢查一下場景中的Light是否開啟,並正確的設定了屬性。以及Lighting Window中的間接光Indirect Intensity不為0。
Q3:場景進行光照烘焙時存在速度較慢的問題,是否有一些設置上的改進或最佳實踐?
A:在lighting設置窗口中,主要是由於Indirect Resolution的設置會影響烘焙的速度。
事實上,利用Lightmap Parameter機制可以對場景中不同的區域設置不同的烘焙參數,例如光照變化較為低頻的部分可以創建一個解析度較低的Lightmap Parameter,以節約烘焙時間。參考文檔:
Fine tuning with Lightmap Parameters - Unity
0x03 Profiler
Q:請問一下性能指標裡面的SetPassCalls和Draw Calls、Batches這些有什區別,具體指什麼呢?網上有人說是一樣的東西,但是我發現有時候值不一樣。
A:SetPass Call指的是切換渲染狀態(render state)的次數,比如你的shader中如果有多個pass,或者是場景中有不同的material,都會造成渲染狀態切換。
Drawcall的話,以gles為例,就是調用draw的實際次數,例如drawarray、drawelement,調用一次都會增加。
Batch則是會在第一次調用draw行為的時候加1,如果之後渲染狀態沒有改變,則batch的數量不再增加,但是一次batch內可能會有多次drawcall調用,只是渲染狀態沒有改變。
0x04 Shader Graph
Q:有朋友在用Shader Graph嗎?請問它可以將節點轉成shader供Unity 2017使用嗎?
A:右鍵點擊節點有一個copy code的選項,可以複製代碼。針對根結點,則可以copy生成的全部代碼。
但是不建議在Unity 2017中使用,因為Shader Graph主要是和SRP配合使用的,SRP Shader library和UnityCG.cginc中有比較多的區別。
0x05 SRP
Q:在Unity2018中,使用Lightweight Render Pipeline的時候,有一些Asset Store上的插件的顯示結果不正確。
A: 傳統渲染流水線的Built-in的Shader以及自定義的光照 Shader目前不能在新的Lightweight Render Pipeline中使用。LWRP有其自己的Shader。
如果是傳統的Built-in Shader,則可以通過菜單選擇直接升級到LWRP的Shader。
但是自己寫的lit shader會比較麻煩,目前需要手動來修改。這是因為SRP Shader library和UnityCG.cginc中有比較多的區別。因此這個問題只能向插件作者反饋了,或者你仍然使用傳統的渲染流水線。
0x06 Compute Shader
Q:話說Unity的Compute Shader傳float數組一直有bug。比如傳float[5],C#里寫ComputeShader.SetFloats是無法成功的,只有第一個float可以設置成功,這個bug官方已知嗎?
A: 這個不是bug。而是根據HLSL的規則,應該對數據進行對齊,以避免為計算偏移所導致的ALU開銷。
HLSL的相關文檔可以參考:
Packing Rules for Constant Variables
「Arrays are not packed in HLSL by default. To avoid forcing the shader to take on ALU overhead for offset computations, every element in an array is stored in a four-component vector.」
因此調用帶有float []參數的SetFloats應根據HLSL規則進行對齊,即float []應按每個數據16位元組,也就是float4的形式傳遞。
例如如下格式:
//Setup Float Array _floatArray = new float[4*4]; _floatArray[0] = 0.25f; _floatArray[4] = 0.50f; _floatArray[8] = 0.75f; _floatArray[12] = 1.00f;
傳遞的結果就是,(0.25, 0.5, 0.75,1)。
而Unity的文檔中,其實也有提到這個問題。具體內容可以查看文檔。
ComputeShader.SetFloats
This function can be used to set float vector, float array or float vector array values. For example, float4 myArray[4] in the compute shader can be filled by passing 16 floats.
0x07 GLES
Q:我們現在需要一個非壓縮單通道格式的紋理,作為palatte使用。用Alpha8在某些mali gpu手機上有問題,會變成rgba32位格式,內存增加4倍。請問是為什麼?另外R8的這個在哪裡可以設置?
A:第一個問題,在某些mali gpu手機上有問題,這是由於Alpha8 texture format在OpenGL ES 3 及以上版本中被移除了,因此我們使用了GL_EXT_texture_swizzle拓展來實現類似的功能,但是GL_EXT_texture_swizzle拓展在某些mali gpu的手機上的實現存在問題,導致該功能不能正常工作。
如果要使用R8格式,可以將Texture Type設置為Single Channel,選擇Red即可。
0x08 後記
好了,以上就是想和大家分享的幾個在群里討論的小問題。
再次,歡迎大家加入我們這個討論乾貨的官方技術群,交流分享呀。Unity官方社區交流群:629212643http://qm.qq.com/cgi-bin/qm/qr?k=iezKNTDbilddKmeoHOdq1Q2M_bbCJ9Ls (二維碼自動識別)
-EOF-
最後打個廣告,歡迎支持我的書
《Unity 3D腳本編程:使用C#語言開發跨平台遊戲》(陳嘉棟)【摘要 書評 試讀】- 京東圖書
推薦閱讀: