[Unity3D]降低向Shader中傳值的開銷


Unity3D中提供了很多API用於向shader傳值,這篇文章對比測試了兩類不同的使用方法的性能。

正文

Unity3D中,通過C#代碼向shader傳值有兩種方式。 
一種是面向具體的material,另一種是面向所有的material。 
以上兩種方式分別對應下面兩類API:

  • Material.SetXXX();
  • Shader.SetGlobalXXX();

例如,現在的需求是,需要每幀向shader傳遞一個offset、一個scale、和一個alpha。

普通的做法是:

在shader中添加:

    float _Offset; float _Scale; float _Alpha;

在C#中通過以下方式進行傳值:

    Shader.SetGlobalFloat("_Offset", offset); Shader.SetGlobalFloat("_Scale", scale); Shader.SetGlobalFloat("_Alpha", alpha);

以上寫法可以正常工作,但是更好的方法是下面這種:

Shader中:

    float4 _Parameter;

C#中:

    Vector4 parameter = new Vector4(offset, scale, alpha, 0); Shader.SetGlobalVector("_Parameter", parameter );

第二種方法在GPU寄存器的使用方面會優於第一種方法,因為不論是SetFloat還是SetVector,都會占用一個寄存器。CPU和GPU通信次數越少性能開銷也就越少。 
用下面的方法做一下測試,可以發現兩種方式在CPU方面開銷變化很明顯,在我的電腦上,萬次循環一幀大約可以節省2ms左右。

void Update() { for (int i = 0; i < 10000; i++) { if (_switcher) { Shader.SetGlobalVector("_Parameter", new Vector4(1, 0, 0, 1)); } else { Shader.SetGlobalFloat("_R", 0); Shader.SetGlobalFloat("_G", 1); Shader.SetGlobalFloat("_B", 1); Shader.SetGlobalFloat("_A", 1); } } }

最后

其實這個技巧也不僅僅局限於Unity3d,在dx和gl中也應該是這樣,思想是通用的,如果誰能分享一些不是非常難的結合代碼的GPU和CPU通信的學習資料大普通將be very appreciate。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM