unity 5相比較與之前的版本來說,在shader方面做了許多重要的更新。一些更新很容易被大家察覺,例如,如果讀者直接把在unity 4中使用的一些shader源**貼上到unity 5中,往往會發現和unity 4中得到的渲染結果不盡相同,甚至還會報錯。本章會對unity 5進行的一些重要的更新(僅關注shader方面的更新)進行解釋,來幫助讀者加深對unity shader的理解。
//unity 5之前的shader經常包含了類似下面的**
//而在unity 5中,我們不再需要進行x2的操作
c.rgb=s.albedo*_lightcolor0.rgb*(diff*atten*2);
這類**通常會在光照結果的最後乘以係數2,而作者往往解釋說,因為不乘以2的話場景會看起來很暗。但是,如果我們仍然在unity 5中編寫類似上面的**,場景就會看起來變亮了,這通常不是我們希望看到的。unity 5之前的shader需要乘以2是乙個歷史遺留的原因,並最終在unity 5得到了修正。在unity 5中,光照的強度被自動增強到原來的2倍。這意味著,如果我們在場景中放置乙個存白色的平面,同時讓乙個平行光從它的正上方垂直照射到它的表面,那麼平面的得到的漫反射光照結果就是平行光本身的顏色。而在unity 5之前的版本中,上述的平面並不會得到和光源顏色一致的結果。
因此,如果讀者直接從之前的專案中使用現成的shader**並把它移植到unity 5中,需要去掉光照計算中乘以2的部分,來得到和之前一致的光照結果。
如果讀者把一些老版本下使用的表面著色器**直接貼上到unity 5中使用,可能法線原來沒有報錯的**在unity 5下報錯了,這些報錯資訊通常是指shader中的數學指令或插值暫存器數目超過了限制,並提示需要使用更高的shader model,如sm3.0。
這些報錯資訊的出現,是因為unity 5的表面著色器在背後進行了更多的計算。我們在前面解釋過表面著色器的實現原理,概括來說就是unity會在背後把表面著色器轉換成對應的頂點/片元著色器。這些轉換過程是有規律可循的,而在unity 5中,unity 在轉換過程中使用了更多的計算和插值暫存器,從而造成一些自定義的表面著色器可能會在新版本中報錯。這些新新增的計算和插值暫存器通常是為了計算陰影、霧效、非統一縮放模型的法線變換矩陣。在unity 5之前,如果需要使用法線紋理,unity會把觀察方向和光照方向在頂點著色器中變換到切線空間下再傳遞給片元著色器,但unity 5選擇首先在頂點著色器中計算從切線空間到世界空間的變換矩陣,再在片元著色器中把法線變換到世界空間下,從而需要使用更多的插值暫存器來儲存變換矩陣。由於unity預設的shader model版本為2.0,這些新新增的計算再加上一些自定義的變數和計算就很有可能會超過sm2.0中對計算指令和插值暫存器數目的限制。
對上述問題的解決方法也很簡單。一種方法是直接使用更高的shader model,例如,在shader中新增如下**來指明使用的sm3.0:
#pragma target 3.0
另乙個方法是減少表面著色器背後的計算,這可以通過表面著色器的編譯指令來實現。例如,我們可以通過類似下面的編譯指令,來指明不需要為該物體計算陰影紋理座標(不接收陰影)、光照紋理座標以及霧效:
#pragma su***ce su***cefunction lightmodel noshadow nolightmap nofog
unity 5另乙個重要的改進是,非統一縮放的網格不再由unity提前在cpu中處理了。我們曾在前面講到過非統一縮放對法線變換的影響,非統一縮放的網格需要使用原變換矩陣的逆轉置矩陣來變換法線才可以得到正確的變換結果。然而,在unity 5之前的版本,我們並不需要在shader中考慮非統一縮放帶來的種種影響,因為傳到shader中的資料已經不存在非統一縮放了。那麼,這是如何做到的呢?unity 5之前的版本會在cpu中把涉及非統一縮放的模型變換成統一縮放的模型,也就是說,unity會在cpu中再建立乙個和非統一縮放模型空間大小相同,但只包含統一縮放的模型。因此,我們常常會在一些較舊的shader版本中看到類似下面的**:
//#define scaled_normal(v.normal*unity_scale.w)
float worldnormal=mul((float3×3)_object2world,scaled_normal);
上面的**把法線從模型空間變換到世界空間下,由於只包含了統一縮放,因此**首先使用統一縮放係數unity_scale.w(在unity4.x中,該值表示的值為1/統一縮放係數)來得到歸一化後的法線,然後再使用模型空間到世界空間的變換矩陣直接變換法線方向。unity 5之前採用這種做法的好處是,我們不需要在渲染中考慮非統一縮放的影響,而它的缺點是,cpu的計算消耗會更大,而且需要占用更多記憶體空間來儲存這些重新縮放的模型。
unity 5正式拋棄了之前的做法,它直接將原頂點資訊和包含非統一縮放的矩陣傳遞給shader,因此,unity_scale也就沒有意義了。如果我們需要在頂點/片元著色器中變換頂點法線,就需要時刻小心非統一縮放的影響,以及需要對變換後的法線進行手動歸一化操作。
實際上很多平台早已不支援固定管線著色器。unity仍然保留對固定管線著色器的支援,是出於兩個主要原因:首先,有很多專案和資源包都大量使用了固定管線著色器,其次是固定管線著色器的**通常要比實現相同功能的頂點/片元著色器要少很多。現在unity支援的絕大多數平台實際上已經完全不再支援固定管線程式設計,unity需要在背後把我們編寫的固定管線著色器轉換成相應的可程式設計管線著色器。
unity5.x版本對固定管線著色器的匯入和編譯進行了優化。截止到unity5.2版本,所有固定管線著色器都會在匯入時被轉換成真正的頂點/片元著色器,並且已經支援所有的平台,包括遊戲機平台。我們還可以在shader的匯入面板中檢視固定管線著色器生成的頂點/片元著色器,如下圖所示:
但缺點是,以前一些固定管線著色器的功能,例如,使用texgen命令來生成紋理座標以及進行紋理座標變換的矩陣操作等,已經被拋棄了。而且我們也不可以在指令碼中使用類似new material(「fixed function shader string」)的**來實時建立乙個固定管線的著色器。除此之外,我們也不可以再混用可程式設計和固定管線的著色器。
實際上,由於unity目前支援的所有平台都已經拋棄了固定管線著色器,我們已經沒有必要再使用固定管線著色器來進行渲染了。
第十八章 B樹
施工中施工中 基本操作主要包括 搜尋b樹,建立空b樹,插入關鍵字。18.3放出刪除關鍵字的 class program region 磁碟操作 為結點初始化對應的磁碟頁 private static node t allocate node t 磁碟寫操作 private static void d...
第十八章 定製特性
目錄 18.1 使用定製特性 18.2 定義自己的特性類 18.3 特性構造器和字段 屬性資料型別 18.4 檢測定製特性 18.5 兩個特性例項的相互匹配 18.6 檢測定製特性時不建立從attribute派生的物件 18.7 條件特性類 定製特性 利用定製特性,可宣告式地為自己的 構造新增註解來...
第十八章 18 2 3節練習
練習18.18 已知遊俠面的swap的典型定義 參見13.3節,第457頁 當mem1是乙個string時程式使用swap的哪個版本?如果mem1是int呢?說明在這兩種情況下名字查詢的過程。void swap t v1,t v2 解答 這裡典型定義應該指的是有乙個專為string交換而建立的swa...