[譯]Unity Shader: ShaderLab & Fixed Function shaders

加減翻譯,給需要的人快速瀏覽用,某些專有名詞我就保留原文好讓大夥辨識~~

原文:Shaders: ShaderLab & Fixed Function shaders
這個教學將要教你如何製作你自己的shader並讓你的遊戲看起來更棒!

Unity備有一個稱作"ShaderLab“關於shader和material的語言。他很類似CgFX和D3D Efect(.FX)語言,他使用來告訴Material如何呈現。

shader裡記載的properties也會顯示在Unity’s Material的Inspector。針對不同的硬體效能,眾多的shader會根據繪圖硬體描述的render state去修正pipeline設定或是vertex/fragment的使用。Vertex/fragment都是使用高階的Cg/HLSL程式語言。

在這篇教學裡,我們會描述如何撰寫shader去使用 fixed function和 programmable piepline。我們假設讀者對OpenGL或Direct3D的render state, fixed function & programmable pipeline有基礎的認識以及一些Cg, HLSL或OpenGL的知識。在NVIDIA和AMD的開發者網站可以找到一些shader教學和文件。

Getting started

首先創建一個新shader,可選擇"Assets->Create->Shader"或"複製一個現有的shader"。在Project view裡點擊剛才創見出來的shader檔進行編輯。

Shader "Tutorial/Basic" {
    Properties {
        _Color ("Main Color", Color) = (1,0.5,0.5,1)
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
            }
            Lighting On
        }
    }
}

這個簡單的shader展示一個最基本的shader。它定義了一個顏色屬性"Main Color"並將之設定為類玫瑰色(r=100% g=50% b=50% a=100%)。然後會調用一個"Pass",在那個Pass裡設定diffuse material為_Color並開啟pre-vertex lighting。

測試一下這個shader。創建一個新的material,從下拉式選單裡選擇這個shader(Tutorial->Basic),然後將這個material丟到某個物件上。調整Material Inspector裡的顏色並觀察變化。接著來弄個更複雜的吧!

Basic Vertex Lighting

如果你是用現成的且頗複雜的shader,那可能會比較難以閱讀理解。接著我們會來分析Unity內建的"VertexLit"shader。這個shader使用fixed function去做基本的pre-lighting。

Shader "VertexLit" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0.5)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" { }
    }

    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
                Ambient [_Color]
                Shininess [_Shininess]
                Specular [_SpecColor]
                Emission [_Emission]
            }
            Lighting On
            SeparateSpecular On
            SetTexture [_MainTex] {
                constantColor [_Color]
                Combine texture * primary DOUBLE, texture * constant
            }
        }
    }
}

所有的shader都是從關鍵字"Shader"並且後面帶著一個這個shader名稱的字串的地方開始。這個名稱是會出現在Inspector裡的。這shader的所有的程式碼都應該放在大括弧({})裡面。(稱之為一個block)。

這名稱應該是簡短易懂的。它並不會/不需要去符合".shader"的檔案名稱。
要讓shader放在子選單內的話,使用斜線(slashes)。e.g. “MyShaders/Test"會在"MyShaders"的子選單裡顯示為"Test"(MyShaders->Test)。

Properties

在shader一開始的部分你可以定應一些porperties讓美術(unity使用者)在Material Inspector裡面編輯。以"VertexLit"範例的properites會看起來像是這樣:

在Properties區塊裡的properties會個別列出。每個property都會使用內置名稱(Color, MainTex)。緊接著的刮弧內是該property在Inspector裡的名稱以及類型。再來就是該值的預設值:

可使用的type列在 Properties Reference 裡。預設值會根據type而設定。以顏色來說,它的預設值應該會是Vector4。

現在我們有定義好的properties,也準備好開始撰寫shader的主體了!

The Shader Body

在我們開始之前,先來定義幾個基本的structure。

不同的繪圖硬體都有不同的效能。例如,某些繪圖卡支援fragment grograms而其他繪圖卡無法;某些可以一次丟4個texture給pass,但某些只能2個甚至1個。為了讓你的使用者可以在任何硬體上執行,一個shader應該包含多個"SubShaders“。當Unity繪製shader時,它會依序走訪每個subshader,並且執行第一個可執行的。

Shader "Structure Example" {
    Properties { /* ...shader properties... }
    SubShader {
    	// ...subshader that uses vertex/fragment programs...
    }
    SubShader {
    	// ...subshader that uses four textures per pass...
    }
    SubShader {
    	// ...subshader that uses two textures per pass...
    }
    SubShader {
    	// ...subshader that might look ugly but runs on anything🙂
    }
}

這套系統可以讓Unity支援現有的所有硬體,並保有最大限度的質量。但是會變成一個冗長的shader就是…

在subshader裡的任何render state設定都會和所有的pass共享;但是會有各自的rendering pass。完整的可使用指令可在SubShader Reference裡找到。

Passes

每個subshader都是pass的一個集合。對於每個pass來說,幾何物件是要被繪製的,所以在pass內至少要有一個subpass。我們的VertexLit"shaer只有一個subshader:

// ...snip...
Pass {
    Material {
        Diffuse [_Color]
        Ambient [_Color]
        Shininess [_Shininess]
        Specular [_SpecColor]
        Emission [_Emission]
    }
    Lighting On
    SeparateSpecular On
    SetTexture [_MainTex] {
        constantColor [_Color]
        Combine texture * primary DOUBLE, texture * constant
    }
}
// ...snip...

任何一個在pass中的指令都會設定graphics硬體用特定的方式繪製幾何體。

在前面的範例裡,我們將Material的區塊綁上我們property的設定值給fixed function lighting material 的設定。指令"Lightint On"會開啟標準的vertex lighting。"SeparateSpecular On"會去啟用specular highlight 的 separate color。

上述的所有指令都可以很直接的對應到OpenGl/Direct3D硬體模組(hardware model)。參考OpenGL red book可以得到更多相關的資訊。

接下來的指令"SetTexture"非常重要。這些指令定義我們要如何去使用如何混合這個texture,組合以及應用他們在我們的rendering。SetTexture指令根據我們給予texture的名稱使用(這裡是"_MainTex"),在後面的中括弧內的內容是定義該texture要如何去apply。括弧內的設定是會apply在要繪製在screen上的每個pixel。

在這個block內我們設定了一個常數color值,也就是Material的Color"_Color"。我們會在下面用到。

下個指令我們指定如何使用color值去混合texture。使用"Combine"指令去定義texture如何和其他texture或color混合。通會像是這樣:

Combine ColorPart, AlphaPart

這裡的"ColorPart"和"AlphaPart"定義混合時的color(RGB)和alpha(A)。如果省略"AlphaPart",就會直接使用和"ColorPart"。

在"VertexLit"範例中:

Combine texture * primary DOUBLE, texture * constant

這裡的"texture"是來自目前使用中的texture的color(這裡是"_MainTex")。它會乘上"primary"的vertex color。Primary color是只vertex lighting color,是在處理Material時被計算的。最後,這個結果會在乘上2來增加亮度(DOUBLE)。這個alpha值(在逗號之後的部分)是把"texture"乘上"constant"值(在前面設定的"constantColor")。另一個常用到的組合模式叫做"previous"(沒有在這個shader使用到)。這是代表任何一個先前使用"SetTexture"後的結果值,可以用再組合其他多個texuture和/或color。

Summary

在"VertexLit"shader設定了標準的vertex lighting和設定texture組合器讓光照強度變為2倍。

我們可以放入更多pass到shader中,他們會依序繪製。就目前來說是非必要的,因為我們已經達到期望的效果。我們只需要一個SubShader(像是我們做的),並沒有用到更進階的東西,這個特別的shader可以在任何Unity支援的顯卡上執行。

這個"VertexLit"shader是我們所能想到的最為基本的。我們沒有使用任何硬體設定的操作,也沒用到任何ShaderLab和Cg提供的更特殊更酷炫指令。

下一個章節,我們將會解說如何使用Cg撰寫自訂vertex & fragment programs。
——

如果有何錯誤或用詞詭異的話,請留言給我修改~3Q!!

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s