最近項目中需要優化模型的顯示效果,所以就忙着編寫合用效果的 shader 了,然後就遇到了各種各樣的小問題,其中有個只在 pc 平臺會報錯,但是在 android 平臺下沒毛病的小 bug 卡了我一下,後來才發現又叫 unity 給坑了。
ps:這裏不得不吐槽一下 unity 提供的這些內部着色器方法,雖然是極大的方便了 shader 的編寫,但是這個文檔呀。。。它有好多在內部寫死了的實現,死到甚至要求我們的頂點,片段輸入輸出結構體中的語義
變量都必須是死名,2333,這你妹的沒有文檔可是叫人看死了。。。
我遇到的就是這個宏的問題TRANSFER_VERTEX_TO_FRAGMENT
,它定義在AutoLight.cginc
文件中,它會與宏LIGHTING_COORDS
協同工作,它會根據該pass處理的光源類型( spot 或 point 或 directional )來計算光源座標的具體值,以及進行和 shadow 相關的計算等。
在pc平臺的時候,它會去調用一個在UnityCG.cginc
文件中的ComputeScreenPos
方法,有問題的就是它了。
假如我們的頂點輸出結構是這麼定義的:
struct v2f
{
half4 vertex : SV_POSITION;
half2 uv : TEXCOORD0;
half3 normal : TEXCOORD1;
half3 viewDir : TEXCOORD2;
half3 lightDir : TEXCOORD3;
LIGHTING_COORDS(4, 5)
};
看着沒有什麼問題哈,但是在pc平臺下就會報錯,錯誤爲:
現在讓我們看看正確的寫法是什麼樣的:
struct v2f
{
half4 pos : SV_POSITION;
half2 uv : TEXCOORD0;
half3 normal : TEXCOORD1;
half3 viewDir : TEXCOORD2;
half3 lightDir : TEXCOORD3;
LIGHTING_COORDS(4, 5)
};
現在,聰明的你看出來了吧,區別就在SV_POSITION
語義的變量名上,之前我們取的是vertex
,後來改成了pos
,那這是爲什麼呢?
然後我在unity的內置方法裏一通搜,這裏推薦一下 vscode 這個編輯器,真的是腳本開發的利器,可以以文件夾爲單位打開代碼,然後在裏面全局搜索你要找的內容,特別的適合進行這種調用過程不明確,目標也不明確情況下的代碼搜索。
結果在這裏:
看到了沒,上面我們提到過的TRANSFER_VERTEX_TO_FRAGMENT
會輔助我們進行陰影相關的計算,然後這裏它在進行陰影座標計算的時候,傳入了一個a.pos
,所以這也就是爲什麼我們的頂點輸出結構裏,必須將變量定義爲pos
的原因了,然鵝並沒有文檔來說明這個宏的正確使用方法,2333。。。。。。