文章出處

Image(1)

關于《Thinking in Unity3D

筆者在研究和使用Unity3D的過程中,獲得了一些Unity3D方面的信息,同時也感嘆Unity3D設計之精妙。不得不說,筆者最近幾年的引擎研發工作中,早已習慣性的從Unity3D中尋找解決方案。

Unity3D雖比不上UE那么老練沉穩,氣勢磅礴。也比不上CE那樣炫麗多姿,盛氣凌人。但它的發展勢如破竹,早已遍地生花!故而在此記錄一些自己的心得體會,供大家參詳交流。若有欠妥之處,還望各位及時指正。
 
Thinking in Unity3D由一系列文章組成,文章列表地址:http://www.cnblogs.com/geniusalex/p/5321545.html
 

什么是材質?


材質是一個相對廣泛的概念,不同的專業領域有不同的定義。 在此也不一一舉例說明了,我們只說在3D游戲引擎中,材質的定義。

材質的本質定義,是指能夠描述一個物體的顯示外觀的一系列數據。它包括幾個方面

1、渲染狀態

     渲染狀態是指早期的setRenderState那一套東西。比如,前后面裁剪,是否開啟混合,混合因子等等。

2、著色方式

     著色方式,在固定管線年代,是通過一系列的API進設置。 在可編程管線年代。就對應的是我們的著色器代碼。

3、參數

     不管是固定管線還是非固定管線,我們都可以設置一些參數用于著色計算。比如顏色,光源信息等等

4、紋理貼圖

     紋理貼圖是表現一個物體表現的顏色細節的必不可少的東西。就是一張張圖片。

有了上面的這些數據后,我們就可以根據一定的運算規則,將一個幾何體的質感顯示為我們想要的樣子。

 材質、Shader、模型關系圖

材質系統的常見需求


一個工具或者系統的設計不可能是憑空而出的。 一定是根據需求和經驗的積累,才形成了我們今天這種“材質系統”的概念。 說到這里,那么我們常見的材質系統需要做到什么樣子呢。

一、模板 + 實例

     材質是一個模板,通過對某一個材質進行實例化,指定不同的數據和貼圖,就可以讓物體表現出不同的顯示效果。 和Class + Object的關系很像。

二、多Pass

     有時候,我們為了實現一個繪制效果,靠單次繪制是無法實現的。比如描邊效果。 這就要求我們單個物體能夠在進行繪制的時候,多次提交材質并繪制。

三、多Technique

     多Technique是指一個材質中,應該包含不只一個實現方案。 這樣當我們進行材質更替,或者進行高中低端機適配的時候。 就不會那么麻煩。 同時在數據管理上,也顯得更為規范。

四、高中低端機適配

     高中低端機適配是一個很重要的特性,因為玩家的機型不可能是一樣的。 在需要保證效率的情況下,我們很多時候需要降低物體渲染的復雜度。在《3D游戲中的畫質與效率適配》一文中。筆者也描述過,有兩種方案。 一種是通過宏定義,一種是動態切換Technique。

總結下來,就是說一個材質模板文件應該像這樣的一個結構

MaterialTemplate
{
     Technique
     {
          Pass{}
          Pass{}
     }
     Technique
     {
          Pass{}
          Pass{}
     }
}

 

Unity3D中的材質系統


在說到Unity3D中的材質系統的時候,我們先來看一下我們創建一個材質需要做的事情。

一、創建一個Shader并編寫出自己想要的效果

二、創建一個Material并將這個Material的Shader指定為自己的材質

三、為這個Material設置參數,賦上貼圖等

四、將創建好的Material拖到對象上

我們再來看一個典型的Shader應該具備的內容

Shader "MyShader" { 
    Properties { 
        _MyTexture ("My Texture", 2D) = "white" { } 
        // other properties like colors or vectors go here as well 
    } 
    SubShader {

          LOD 100 
        // here goes the 'meat' of your 
        // - surface shader or 
        // - vertex and program shader or 
        // - fixed function shader

          Pass{}

          Pass{}

    } 
    SubShader {

          LOD 1000 
        // here goes a simpler version of the SubShader 
        // above than can run on older graphics cards

          Pass{}

          Pass{} 
    } 
}

 

我們可以看到。 每一個Shader有多個SubShader,每一個SubShader有多個Pass。 這樣看起來和我們前面提到的MaterialTemplate結構幾乎一致。

而在Unity3D中。Shader就是材質模版。 Material就是一個材質實例。 每一個Material你可以認為是一個材質實例的序列化存儲。

 

Unity3D中的材質LOD


那對于前面提到的 高中低端機適配。 有兩種方法解決。一是通過宏定義,這個并不是Unity3D的推薦方式,且需要Shader編寫的相關知識,在這里不作詳細討論。 如果有興趣的朋友,可以訪問括號中的鏈接(http://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html),以后的文章在涉及Unity3D的Shader編寫方面的內容時,再進行討論。 在此主要討論Unity3D中通過材質LOD進行畫質控制。

在Unity3D的Shader中,可以為每一個SubShader指定一個LOD值,這個LOD值可以通過設置Shader.globalMaximumLODShader.maximumLOD來實現SubShader的切換。所有的SubShader按順序進行判定,當一個SubShader滿足下面兩個條件時,才表明可用。

1、SubShaderLOD值小于設定的值。(你可以把LOD看作是開銷,開銷越大的SubShader指定越高的LOD值)

2、SubShader所有Pass使用到的顯卡特性被當前設備支持。

:Shader API文檔地址:http://docs.unity3d.com/ScriptReference/Shader.html

:Shader LOD文檔地址:http://docs.unity3d.com/Manual/SL-ShaderLOD.html

:Unity3D為每一檔的內置Shader都設置了一個默認值,在LOD文檔中有

:如果不指定LOD值,那LOD=infinite 。 你可以當它是一個小于0的值。

:這個值除了可以自己給以外,還可以在Edit->Project Settings->Quality面板中指定,如下圖

Image(3)

 設置面板

Unity3D中的材質替換


官方文檔地址http://docs.unity3d.com/Manual/SL-ShaderReplacement.html

Image(4)

夜視效果

有時候,我們希望能夠進行一些特殊操作。將場景物體的按另一種渲染方式渲染到RT中。 比如,僅渲染物體的深度,把物體渲染成純白,把物體渲染成紅綠熱成像模式等等。但是,我們的材質在一開始就指定好了。如果要替換的話,就需要遍歷所有對像,為它們重新指定材質。渲染完畢后,再切換回來。Unity3D為我們提供了更直接的方式。Camera.RenderWithShaderCamera.SetReplacementShader。前者是僅作用一次,后者是一直生效,如果想取消設置。 使用Camera.ResetReplacementShader即可


那么問題來了,我們有時候只想渲染一些特殊的物體。比如,我們想處理除主角以外的內容。 這就需要對主角進行剔除。 那上面兩個函數的第二個參數replacementTag就起作用了。如果設置了它,在進行材質替換時,它會和SubShader中的 RenderType的值 進行比對。 比如,我們即將替換的材質如下。

Shader "EffectShader" { 
     SubShader { 
         Tags { "RenderType"="Opaque" } 
         Pass { 
             ... 
         } 
     } 
     SubShader { 
         Tags { "RenderType"="SomethingElse" } 
         Pass { 
             ... 
         } 
     } 
...

}

 

 

如果我們調用了camera.SetReplacementShader (EffectShader, "RenderType");那么,一個物體在被渲染時,會產生以下幾種結果。

1、如果物體當前激活的SubShader的RenderType是Opaque,那么將會采用EffectShader的第一個SubShader。

2、如果物體當前激活的SubShader的RenderType是SomethingElse,那么將會采用EffectShader的第二個SubShader。

3、如果物體當前激活的SubShader的RenderType在EffectShader中沒有與之對應的項,此物體將會在渲染中被忽略。

4、如果物體當前激活的SubShader沒有RenderType這個Tag,此物體將會在渲染中被忽略。

 

結束語


Unity3D擁有著一個靈活的渲染管線和自由的材質系統。與其它圖形引擎不一樣的是,Unity3D針對游戲需求所留出來的接口非常好用。

而本文僅僅是對Unity3D的材質系統進行初步的描述。要想完全把Unity3D的材質系統總結出來,不是一兩篇文章可以搞定的。Unity3D文檔中的 Shader Reference可以作為一個十分不錯的開始http://docs.unity3d.com/Manual/SL-Reference.html


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()