GLSL/HLSL易犯錯誤和注意點


GLSL/HLSL易犯錯誤和注意點

我的blog里有許多此類筆記,主要是記錄寫程序時犯下的錯誤.有相當多的錯誤,我都是一犯再犯,而且每次都因這種小錯耽誤時間而罵自己是豬,所以很有必要記錄下來,以備查找.作程序的要懂得積累經驗,並書面化,抽象化. 渲染API容易出錯,根源於其本質是個狀態機,作一個渲染時,幾十上百個狀態都必須設置正確,才能得到正確的圖像,這就很容易出點小差錯. 1.GLSL的vec4有3種分量形式xyzw/rgba/stpq, 注意到的r分量是指顏色r分量, 習慣上的紋理坐標分量strq的r由於和顏色r沖突,改作p. 2.Global Amibient也要乘以材質Material. 3.HLSL沒有shadow2DProj函數, GLSL的shadow2DProj返回的是深度比較的結果1.0或0.0的4元組,不是深度值!且要記住,shadow2DProj受到固定流水中紋理GL_TEXTURE_COMPARE_MODE/GL_TEXTURE_COMPARE_FUNC的影響,要使用shadow2DProj必須打開深度紋理比較模式. 4.HLSL允許如vec4向下強轉為vec3這種隱式轉換. GLSL語法上不允許,但實踐上N卡出warning仍可以編譯運行,A卡直接報錯無法運行. 5.DirectX的shader調試狀態和硬件實際運行狀態的結果有很大區別,不能全信. 6.設置   glEnable(GL_COLOR_MATERIAL);               glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); 在shader中, A卡的glFrontMaterial.diffuse不會跟蹤設置為當前頂點色,而N卡正確. 7.GLSL: N卡可以使用vec3 temp = { 1.0, 0.0, 1.0}; 這種形式的構造, A卡報錯.     HLSL: 都可以使用float3 temp = { 1.0, 0.0, 1.0};形式. 8.HLSL的mul接受mul(vec, matrix)或mul(matrix, vec),要注意通常HLSL要依DirectX計算(V * M)使用mul(vec, matrix)的形式. 特別需要小心的是,vec如果是float3,前后行列不等,違反HLSL規范,但shader編譯也不報錯,直接當成float4(vec, 0)處理,而不是當成float4(vec, 1).即mul(float3, matrix)中的float3被當成向量,而不是頂點. 9.不要在一行中寫過於復雜的表達式, N卡沒問題, A卡很爛,通常都編譯不過.例如: http://www.ozone3d.net/blogs/lab/?p=38

10.GLSL可以只有PixelShader, 沒有Vertex Shader, HLSL不支持. vs_3_0 shader executed in hardware vertex processing mode can only be paired with at least a ps_3_0 shader. 11.GLSL的1.2版本開始支持mat4x3這種non-square矩陣,要注意4x3是4列3行,而不是4行3列.

HLSL小技巧

研究HLSL也有些日子了,其中犯了很多錯誤,現將沿途所遇略作紀錄,以次時刻提醒自己不要重蹈覆轍。

1. Effect文件(.fx)是標准格式,要妥善利用其接口與應用程序通訊,理解語意(Semantic)和注釋(Annoation)是關鍵。 clip_image001

2. HLSL指令集要倒背如流,切不可做出重寫標准庫的蠢事,當初我就寫了一個distance函數來求距離,熟不知標准庫里早有這個函數,仔細一研究,標准庫里不僅支持三維向量,其它的諸如二維也以考慮在內,汗^_^,完整的指令集可以參見DX幫助文件,路徑為DirectX Graphics->HLSL->Reference->Intrinsic Functions。

3. 不僅指令既要倒背如流,還要注意指令的限制,尤其是Shader Model(SM),像ddx,ddy這樣的指令是不能用在Shader Model 1 中的,這個我感覺是比較令人沮喪的事情,程序員的代碼和邏輯都正確,卻限制於硬件配置的問題,還好現在硬件發展迅速,SM3.0甚至SM4.0的顯卡都已經進入主流市場,這些限制會逐漸消失的。具體的限制可以查看DirectX Graphics->HLSL->Reference-> Shader Models。

4. 編譯Effect的時候能用低配置的Profile就用低的,舉例來說能用vs_1_1的就不要用vs_2_0,ps也是一樣的道理,Profile選的越低,你的Effect兼容性就越好,如果不分清楚直接就用最高Profile,到了客戶那因為顯卡配置不夠報錯的概率就大了,至少我現在還沒聽說某款PC游戲只能在SM4.0下才能用,游戲機,測試程序自然不算了,以后沒准等SM5.0都普及的時候,我這話也自然過時了^_^。

5. 在VS中計算屏幕坐標時要把坐標先轉換成齊次坐標

a) 這樣寫是有問題的,mul(input.Position, WorldViewTransform);

b) 要改成mul(float4(input.Position,1), WorldViewTransform);

6. 文件最后一行要在最后加一個空格或一個空行,要不有時會有error X3000: syntax error: unexpected end of file,這樣的錯誤信息,這種錯誤信息有時莫明其妙發生,例如在加了一條注釋后,總之是在編寫Effect的時候要格外小心謹慎。

7. 前幾天還遇到了這樣的錯誤,在ps中寫了個if語句返回某種顏色,不料產生錯誤,錯誤信息如下error X3500: asymetric returns from if statements not yet implemented。現在把Effect文件內容張帖出來,為了搞清楚問題本質,我把不相關代碼全部刪除了,只留下必要地解釋性代碼。一開始沒注意看錯誤信息,以為是那里寫錯了,就幾十行代碼折騰半天不見好轉,后來仔細看錯誤信息后才恍然大悟,原來是Effect編譯器不支持這種if用法,雖然HLSL支持以c的語法來寫shader,但畢竟和c還是有區別的,編譯下面的代碼就會得到上述錯誤信息,只要在第二個return前加else,使其成為一個if-else結構,編譯自然通過。由此可見,寫shader時c的觀念在某些情況下要轉變過來,如果一味以c的直觀印象去評測,極有可能出現問題


免責聲明!

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



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