Unity Shader 入門精要 | 第三章 Unity Shader 基礎(chǔ)

歡迎前往個(gè)人博客 駑馬點(diǎn)滴 和視頻空間 嗶哩嗶哩-《挨踢日志》

以渲染模型為例子纫溃,講述了在沒有 Unity 編輯器情形下進(jìn)行渲染的偽代碼:
加載頂點(diǎn)著色器巍沙、片元著色器 -> 加載到 GPU 中 -> 設(shè)置頂點(diǎn)數(shù)據(jù) -> 設(shè)置紋理數(shù)據(jù) -> 設(shè)置 MVP 矩陣 -> 設(shè)置是否混合 -> 深度測(cè)試 -> 其他設(shè)置

這樣的設(shè)置需要管理多個(gè)文件、函數(shù)等象浑,對(duì)開發(fā)者負(fù)擔(dān)比較重蔫饰。

為了解決上面對(duì)問題,Unity 提供了 Unity Shader 讓開發(fā)者更加輕松的管理著色器代碼和渲染設(shè)置愉豺。

3.1 Unity Shader 概述

3.1.1 一對(duì)好兄弟:材質(zhì)和 Unity Shader

Unity 中需要配合使用材質(zhì)(Material)和 Unity Shader 才能達(dá)到需要的效果篓吁。
一個(gè)常見的流程:

  1. 創(chuàng)建一個(gè)材質(zhì);
  2. 創(chuàng)建一個(gè) Unity Shader蚪拦;
  3. 將 Unity Shader 賦給材質(zhì)杖剪;
  4. 將材質(zhì)賦給需要渲染的對(duì)象冻押;
  5. 在材質(zhì)面板中調(diào)整 Unity Shader 的屬性,以得到滿意的效果摘盆;

3.1.2 Unity 中的材質(zhì)

材質(zhì)如何創(chuàng)建翼雀?

  1. Project 視圖->右鍵->Create->Material (推薦做法)
  2. Unity 菜單欄->Assets->Create->Material
    備注:兩個(gè)彈窗是一樣的。

選中創(chuàng)建的材質(zhì)孩擂,會(huì)出現(xiàn)對(duì)應(yīng)的面板狼渊,方便調(diào)整材質(zhì)的參數(shù)。

3.1.3 Unity 中的 Shader

Unity 中的 Shader 有 4 類:

  1. Standard Surface Shader 包含了標(biāo)準(zhǔn)光照模型的表面著色器模板类垦;
  2. Unlit Shader 不含光照的 Shader
  3. Image Effect Shader 為屏幕后處理效果服務(wù)
  4. Compute Shader 主要用于和渲染無(wú)關(guān)的 GPU 計(jì)算(利用 GPU 并行性)

3.2 Unity Shader 的基礎(chǔ) ShaderLab

ShaderLab 是 Unity Shader 的說(shuō)明性語(yǔ)言狈邑。結(jié)構(gòu)如下:

Shader "ShaderName" {
    Properties {
        // 屬性
    }
    SubShader {
        // 顯卡 A 使用的著色器
    }
    SubShader {
        // 顯卡 B 使用的著色器
    }
    Fallback "VertexLit"
}

Unity 會(huì)將 Unity Shader 編譯成真正的代碼和 Shader 文件,開發(fā)人員只需要和 Unity Shader 打交道蚤认。

3.3 Unity Shader 的結(jié)構(gòu)

3.3.1 給我們的 Unity Shader 起個(gè)名字

如果創(chuàng)建的 Shader 形如:

Shader "Custom/MyShader" {}

那么在材質(zhì)面板上選擇 Shader 的時(shí)候米苹,其路徑為: Shader -> Custom -> MyShader

3.3.2 材質(zhì)和 Unity Shader 的橋梁:Properties

Properties {
    Name1 ("display name1", PropertyType1) = DefaultValue1
    Name2 ("display name2", PropertyType2) = DefaultValue2
}
Properties {
    _Color ("Color", Color) = (1,1,1,1)
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
    _Glossiness ("Smoothness", Range(0,1)) = 0.5
    _Metallic ("Metallic", Range(0,1)) = 0.0
}

Properties 語(yǔ)義塊支持的屬性類型:

_Int("Int", Int) = 2
_Float("Float", Float) = 1.5
_Range("Range", Range(0.0, 5.0)) = 3.0
_Color("Color", Color) = (1,1,1,1)
_Vector("Vector", Vector) = (2,3,6,1)
_2D("2D", 2D) = ""{}
_Cube("Cube", Cube) = "white" {}
_3D("3D", 3D) = "black"{}

為了在 Shader 中使用這些屬性,需要在 Cg 代碼片中定義這些屬性類型相匹配的變量砰琢。
Properties 語(yǔ)義塊的作用僅僅是為了讓這些屬性可以出現(xiàn)在材質(zhì)面板中蘸嘶。

3.3.3 重量級(jí)成員 SubShader

一個(gè) Unity Shader 可以有多個(gè) SubShader 語(yǔ)義塊。Unity 加載 Unity Shader 時(shí)陪汽,會(huì)掃描所有的 SubShader 训唱,選擇第一個(gè)能夠在目標(biāo)平臺(tái)上運(yùn)行的 SubShader。否則將使用 Fallback 指定的 Unity Shader挚冤】鲈觯——這樣可以針對(duì)不同顯卡的設(shè)備進(jìn)行有針對(duì)性的表現(xiàn)。

SubShader 的格式如下:

    [Tags]
    [RenderSetup]
    Pass {
    }
    // .......

Pass 可以有多個(gè)训挡,但是多個(gè) Pass 會(huì)造成渲染性能下降——盡量使用最少數(shù)目的 Pass澳骤。
[RenderSetup] 是可選狀態(tài),包括剔除模式澜薄、深度測(cè)試为肮、深度寫入、混合模式相關(guān)的內(nèi)容表悬。(具體的參數(shù)暫時(shí)不需要了解弥锄,后續(xù)深入學(xué)習(xí))

[Tags] 是一個(gè)鍵值對(duì),鍵和值都是字符串蟆沫。

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }

包括以下標(biāo)簽:
Queue——控制渲染順序 Tags {"Queue"="Transparent"}
RenderType——對(duì)著色器進(jìn)行分類 Tags {"RenderType"="Opaque"}
DisableBatching——是否禁用批處理 Tags {"DisableBatching"="True"}
ForceNoShaderCasting——強(qiáng)制沒有投射陰影 Tags {"ForceNoShaderCasting"="True"}
IgnoreProjector——是否忽略 Projector 的影響(通常用于半透明物體) Tags {"IgnoreProjector"="True"}
CanUseSpriteAtlas——當(dāng)該 SubShader 用于精靈時(shí)籽暇,該標(biāo)簽設(shè)置為 False Tags {"CanUseSpriteAtlas"="False"}
PreviewType——指明材質(zhì)面板將如何預(yù)覽該材質(zhì)(默認(rèn)是一個(gè)球形,可以改為 "Plane"饭庞、"SkyBox") Tags {"PreviewType"="Plane"}

Pass 語(yǔ)義塊
UsePass:復(fù)用其他 Unity Shader 中的 Pass戒悠。 用法: UsePass "MyShader/MYPASSNAME"
GrabPass:該 Pass 抓取屏幕并將結(jié)果儲(chǔ)存在一張紋理中,用于后續(xù)的 Pass 處理舟山。

3.4 Unity Shader 的形式

Unity 中主要可以使用 3 種形式來(lái)便攜 Unity Shader

  1. 表面著色器
  2. 頂點(diǎn)/片元著色器
  3. 固定函數(shù)著色器
    無(wú)論哪種著色器绸狐,真正意義上的 Shader 代碼都需要包含在 ShaderLab 語(yǔ)義塊中:
Shader "MyShader" {
    Properties {
        // 所需的各種屬性
    }
    SubShader {
        // 真正意義上的 Shader 代碼出現(xiàn)在此處
        // 表面著色器
        // 頂點(diǎn)/片元著色器
        // 固定函數(shù)著色器   
    }
}

3.4.1 表面著色器

表面著色器(Surface Shader)是 Unity 自己創(chuàng)造的一種著色器代碼類型卤恳。特點(diǎn)是:需要的代碼量少,渲染代價(jià)比較大寒矿,多光照?qǐng)鼍跋率褂谩?/p>

Shader "Custom/Simple Surface Shader" {
    SubShader {
        Tags { "RenderType"="Opaque"}
        CGPROGRAM
        #pragma surface surf Lambert
        struct Input {
            float4 color : COLOR;
        };
        void surf(Input IN, inout SurfaceOutput o){
            o.Albedo = 1;
        }
        ENDCG
    }
    Fallback "Diffuse"
}

注意點(diǎn): Cg/HLSL 語(yǔ)言和原生的基本一致突琳,但少數(shù)原生函數(shù)和用法 Unity 沒有支持。

3.4.2 頂點(diǎn)/片元著色器

頂點(diǎn)/片元著色器的代碼要寫在 CGPROGRAM 和 ENDCG 之間符相。我們可能要編寫更多的代碼拆融,但是靈活性最高。

Shader "Custom/Simple VertexFragment Shader" {
    SubShader {
        Pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            float4 vert(float4 v : POSITION) : SV_POSITION {
                return mul (UNITY_MATRIX_MVP, v);
            }
            fixed4 frag() : SV_Target {
                return fixed4(1.0,0.0,0.0,1.0);
            }
            ENDCG
        }
    }
}

3.4.3 固定函數(shù)著色器 Fixed Function Shader

固定著色器必須使用 ShaderLab 語(yǔ)法啊终。后續(xù)基本不實(shí)用镜豹。

3.4.4 選擇哪種形式的 Unity Shader

  1. 除非明確需要使用到固定函數(shù)著色器,否則一般不使用蓝牲;
  2. 如果需要和各種光源打交道趟脂,那么使用表面著色器。但是需要小心移動(dòng)平臺(tái)的性能表現(xiàn)例衍;
  3. 如果光源比較少昔期,比如只有一個(gè)平行光,那么使用頂點(diǎn)/片元著色器是一個(gè)更好的選擇佛玄;
  4. 如果有很多需要自定義的渲染效果镇眷,請(qǐng)選擇頂點(diǎn)/片元著色器。

3.5 本書使用的 Unity Shader 的形式

本書重點(diǎn)使用頂點(diǎn)/片元著色器進(jìn)行 Unity Shader 的編寫翎嫡。

歡迎前往個(gè)人博客 駑馬點(diǎn)滴 和視頻空間 嗶哩嗶哩-《挨踢日志》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市永乌,隨后出現(xiàn)的幾起案子惑申,更是在濱河造成了極大的恐慌,老刑警劉巖翅雏,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圈驼,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡望几,警方通過(guò)查閱死者的電腦和手機(jī)绩脆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)橄抹,“玉大人靴迫,你說(shuō)我怎么就攤上這事÷ナ模” “怎么了玉锌?”我有些...
    開封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)疟羹。 經(jīng)常有香客問我主守,道長(zhǎng)禀倔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任参淫,我火速辦了婚禮救湖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涎才。我一直安慰自己鞋既,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開白布憔维。 她就那樣靜靜地躺著涛救,像睡著了一般。 火紅的嫁衣襯著肌膚如雪业扒。 梳的紋絲不亂的頭發(fā)上检吆,一...
    開封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天,我揣著相機(jī)與錄音程储,去河邊找鬼蹭沛。 笑死,一個(gè)胖子當(dāng)著我的面吹牛章鲤,可吹牛的內(nèi)容都是我干的摊灭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼败徊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼帚呼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起皱蹦,我...
    開封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤煤杀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后沪哺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沈自,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年辜妓,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枯途。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡籍滴,死狀恐怖酪夷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情孽惰,我是刑警寧澤捶索,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站灰瞻,受9級(jí)特大地震影響腥例,放射性物質(zhì)發(fā)生泄漏辅甥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一燎竖、第九天 我趴在偏房一處隱蔽的房頂上張望璃弄。 院中可真熱鬧,春花似錦构回、人聲如沸夏块。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)脐供。三九已至,卻和暖如春借跪,著一層夾襖步出監(jiān)牢的瞬間政己,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工掏愁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留歇由,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓果港,卻偏偏與公主長(zhǎng)得像沦泌,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辛掠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容