Shader也叫著色器乞而,是Unity里面比較難的一個(gè)點(diǎn)箩退,網(wǎng)上有很多別人寫好的shader丑罪,我們可以下載下來(lái)用或者修改學(xué)習(xí)传黄。
Shader可以做出很多非常不錯(cuò)的效果杰扫,因?yàn)樗遣逶阡秩竟艿览锩娴某绦颍粊?lái)是性能好膘掰,是GPU執(zhí)行的章姓,不需要CPU再去做額外的處理,二來(lái)就是可控性強(qiáng)识埋,可以控制到每個(gè)頂點(diǎn)凡伊,每個(gè)像素的著色。
比如把一張圖片置灰窒舟,插入一個(gè)像素Shader系忙,每個(gè)像素在紋理著色的時(shí)候把整個(gè)RGBA求一個(gè)灰度出來(lái),這樣就變成一個(gè)灰色的圖片惠豺,這就是一個(gè)典型的像素Shader的使用银还。
Shader
1: Shader是給GPU執(zhí)行的程序,中文叫做著色器;
2: 著色器是運(yùn)行在圖形處理單元上风宁,可以讓開(kāi)發(fā)人員直接操作圖形硬件渲染功能;
3: shader能開(kāi)發(fā)出很多好的效果蛹疯,UV動(dòng)畫戒财,水, 霧 等一些特效, 這些用程序開(kāi)發(fā)出來(lái)(cpu)比較困難,性能還不好;
4: 渲染流水線, 模型投影, 定點(diǎn)著色;
5: shader一般主要有: 固定管線著色器, 頂點(diǎn)片元著色器, 表面著色器;
固定管線著色器(慢慢會(huì)被淘汰);
頂點(diǎn)shader: 干預(yù)模型形態(tài)的shader;?
像素shader: 干預(yù)像素著色的shader;
6: 模型定點(diǎn)運(yùn)算的時(shí)候捺弦,可以加入頂點(diǎn)shader來(lái)干預(yù)頂點(diǎn)的位置;
頂點(diǎn)著色的時(shí)候饮寞,加入像素shader來(lái)干預(yù)像素的上色;
UV動(dòng)畫:在模型上面再貼一張圖,不斷地改變這個(gè)新貼圖的紋理坐標(biāo)列吼,就產(chǎn)生不斷滾動(dòng)的效果骂际,就像cocos案例里面烏龜在水里游,身體被波光覆蓋的那個(gè)動(dòng)畫效果冈欢。
渲染流水線:一個(gè)3D模型拿到GPU里面渲染歉铝,有一個(gè)工作流水線,正是因?yàn)橛辛诉@些流水線凑耻,GPU才公開(kāi)一些接口出來(lái)太示,方便程序員在流水線通道里面插入自己的代碼。也就是說(shuō)支持用戶自己寫代碼插入流水線通道里面香浩,來(lái)實(shí)現(xiàn)用戶需要的特殊效果类缤。
頂點(diǎn)shader:模型頂點(diǎn)進(jìn)來(lái)了以后,我們可以通過(guò)shader把頂點(diǎn)變換成另外一種形狀邻吭,比如我們有一個(gè)網(wǎng)格餐弱,是直來(lái)直去的那種,我們可以讓shader干預(yù)一下這個(gè)網(wǎng)格上的頂點(diǎn)囱晴,讓它變得彎彎的像波浪那種的樣子膏蚓,再貼上紋理。
正弦波
像素shader:當(dāng)我們成像上去后畸写,要對(duì)點(diǎn)進(jìn)行上色驮瞧,哪個(gè)點(diǎn)要貼哪個(gè)紋理,所以需要對(duì)它們進(jìn)行上色枯芬,上色的時(shí)候也可以用shader進(jìn)行處理论笔,比如剛才的烏龜?shù)腢V動(dòng)畫,把另外一個(gè)紋理和原來(lái)紋理結(jié)合千所。
巖漿狂魔,本來(lái)做好了紋理的,但是是靜態(tài)的淫痰,我們可以通過(guò)動(dòng)態(tài)地改變紋理坐標(biāo)最楷,讓巖漿流動(dòng)起來(lái)妙痹,實(shí)際上是改變了每個(gè)頂點(diǎn)著色的紋理坐標(biāo)
Direct3D和opengl
1: 什么是Direct3D和opengl;
2: 目前面向GPU的編程語(yǔ)言主要有三種:
HLSL 語(yǔ)言 通過(guò)Direct3D編寫的著色器程序狂丝,只能在Direct3D里面使用;
Cg 語(yǔ)言 NVIDIA和微軟合作提供的語(yǔ)言,與C相似稍走,Direct3D和opengl都支持原探;
GLSL語(yǔ)言 支持OpenGL上編寫Shader程序;
3: Unity使用ShaderLab來(lái)進(jìn)行著色程序的編寫,對(duì)不同的平臺(tái)進(jìn)行編譯蚯撩,重點(diǎn)支持Cg語(yǔ)言;
顯卡要支持Direct3D什么什么的......
Direct3D和opengl:PC發(fā)展史础倍,PC實(shí)際上是繼承在操作系統(tǒng)上面的,PC上面有各種各樣的硬件在發(fā)展胎挎,如顯卡沟启,顯卡就提出越來(lái)越多的把很多的圖形單元放在GPU上面運(yùn)算,可是我的顯卡雖然支持這種計(jì)算犹菇,但是怎樣告訴程序德迹,所以要把顯卡的功能做出一組API出來(lái),公布給程序使用揭芍。
現(xiàn)在有兩個(gè)端口胳搞,一個(gè)是操作系統(tǒng)是OS:Windows,Linux称杨,一個(gè)是顯卡產(chǎn)商N(yùn)vidia肌毅,AMD,兩個(gè)顯卡產(chǎn)商姑原,它們之間要怎么統(tǒng)一標(biāo)準(zhǔn)悬而,所以微軟提出來(lái)一個(gè)叫DirectX的標(biāo)準(zhǔn),圖形的標(biāo)準(zhǔn)锭汛,里面定義很多硬件加速的接口笨奠,顯卡產(chǎn)商就負(fù)責(zé)在顯卡驅(qū)動(dòng)里面來(lái)實(shí)現(xiàn)支持這些接口,所以當(dāng)DirectX裝好了以后唤殴,我們的代碼使用DirectX的API般婆,由于顯卡的驅(qū)動(dòng)接好了底層的API的實(shí)現(xiàn),所以API就能夠使用顯卡加速眨八,來(lái)獲得很好的圖形性能腺兴,這就是為什么顯卡總要裝一個(gè)驅(qū)動(dòng),因?yàn)樗b好驅(qū)動(dòng)以后要把圖形圖像的接口統(tǒng)一起來(lái)接好廉侧,這樣通過(guò)DirectX就能訪問(wèn)得到顯卡的硬件加速。
微軟DirectX不開(kāi)源的篓足,而Linux的OpenGL是開(kāi)源的段誊,安卓,Linux栈拖,IOS连舍,都支持OpenGL,而不支持DirectX涩哟,微軟也支持OpenGL索赏,大家在Windows上面習(xí)慣使用DirectX盼玄,在Linux上面習(xí)慣使用OpenGL
而Unity是跨平臺(tái)的游戲引擎,所以在Windows上使用DirectX,潜腻,在Linux上使用OpenGL埃儿。
有了這兩個(gè)標(biāo)準(zhǔn)以后,顯卡產(chǎn)商就通過(guò)驅(qū)動(dòng)的形式融涣,把標(biāo)準(zhǔn)接入到標(biāo)準(zhǔn)庫(kù)里面去童番,這樣應(yīng)用程序只要調(diào)用API就能夠使用顯卡加速,如果有的話威鹿。
同時(shí)DirectX和OpenGL也支持用戶直接塞程序剃斧,比如塞shader給顯卡執(zhí)行,所以GPU顯卡也有編程語(yǔ)言忽你,有三種HLSL幼东,Cg,GLSL語(yǔ)言
由于Unity是跨平臺(tái)的游戲引擎科雳,所以它重點(diǎn)支持cg語(yǔ)言根蟹,但是它又不直接使用cg語(yǔ)言,而是自己搞一個(gè)shaderLab語(yǔ)言來(lái)做著色程序的編寫炸渡,這樣我們就可以使用Unity的shaderLab的語(yǔ)法來(lái)生成各種各樣平臺(tái)不同的著色程序娜亿。
我們所說(shuō)的shader就是使用Unity的shaderLab來(lái)編寫的著色程序。
Shader Lab語(yǔ)法基礎(chǔ)
1: 定義一個(gè)Shader,每一個(gè)著色程序都要有一個(gè)Shader
Shader “name” { // name shader名字
// 定義的一些屬性蚌堵,定義在這里的會(huì)在屬性查看器里面顯示;?
[Propeties]?
// 子著色器列表买决,一個(gè)Shader必須至少有一個(gè)子著色器;?
Subshaders: {....}
// 如果子著色器顯卡不支持,就會(huì)降級(jí),即Fallback操作;
[Fallback]
}
Properties
1:name(“display name”, type) = 值;
name指的是屬性的名字吼畏,Unity中用下劃線開(kāi)始_Name;
display name是在屬性檢查器的名字;
type: 這個(gè)屬性的類型
值: 只這個(gè)屬性的默認(rèn)值;
2: 類型:
Float, Int, Color(num, num, num, num)(0 ~ 1) Vector(4維向量), Range(start, end)
2D: 2D紋理屬性;
Rect: 矩形紋理屬性;
Cube: 立方體紋理屬性;
3D: 3D紋理屬性;
name(“displayname”, 2D) = “name” {options}
3: Options: 紋理屬性選項(xiàng)
TexGen:紋理生成模式,紋理自動(dòng)生成紋理坐標(biāo)的模式;頂點(diǎn)shader將會(huì)忽略這個(gè)選項(xiàng);?
ObjectLinear, EyeLinear, SphereMap, CubeReflect CubeNormal
LightmapMod: 光照貼圖模式如果設(shè)置這個(gè)選項(xiàng),紋理會(huì)被渲染器的光線貼圖所影響督赤。
例子
1: _Range (“range value”, Range(0, 1)) = 0.3; // 定義一個(gè)范圍
2: _Color(“color”, Color) = (1, 1, 1, 1); // 定義一個(gè)顏色
3: _FloatValue(“float value”, Float) = 1 // 定義一個(gè)浮點(diǎn)
4: _MainTex (“Albedo”, Cube) = “skybox” {TexGen CubeReflect} // 定義一個(gè)立方貼圖紋理屬性;
Fallback
1:降級(jí): 定義在所有子著色器之后,如果沒(méi)有任何子著色器能運(yùn)行,則嘗試降級(jí);
2: Fallback “著色器名稱”;
3: Fallback Off;
沒(méi)有降級(jí)泻蚊,并且不會(huì)打印任何警告;
SubShader
子著色器躲舌,里面包含一個(gè)一個(gè)連接通道的管道的合集
1: SubShader {[Tags], [CommonState], Pass {} }子著色器由 標(biāo)簽(Tags),通用狀態(tài),通道列表組成,它定義了一個(gè)渲染通道列表,并可選為所有通道初始化需要的通用狀態(tài);
pass就是通道性雄,就是流水線上面一個(gè)一個(gè)的通道没卸,物體模型經(jīng)過(guò)一個(gè)一個(gè)通道,最終把經(jīng)過(guò)通道處理的物體繪制出來(lái)秒旋。
2: SubShader渲染的時(shí)候约计,將優(yōu)先渲染一個(gè)被每個(gè)通道所定義的對(duì)象。
3: 通道的類型: RegularPass, UsePass, GrabPass,
4: 在通道中定義狀態(tài)同時(shí)對(duì)整個(gè)子著色器可見(jiàn)迁筛,那么所有的通道可以共享狀態(tài);
SubShader 語(yǔ)法
1: SubShader {
Tags {“Queue”, “Transparent” }
Pass {
Lighting Off // 關(guān)閉光照
....
}
}
Tags?
1: Tags {“標(biāo)簽1” = “value1” “key2” = “value2”}
2: 標(biāo)簽的類型:
Queue tag 隊(duì)列標(biāo)簽;
RenderType tag 渲染類型標(biāo)簽;
DisableBatching tag 禁用批處理標(biāo)簽;
ForceNoShadowCasting Tag 強(qiáng)制不投陰影標(biāo)簽;
IgnoreProjecttor 忽略投影標(biāo)簽;
CanUseSpriteAtlas Tag,使用精靈圖集標(biāo)簽;
PreviewType Tag預(yù)覽類型標(biāo)簽;
Pass
通道煤蚌,可以把一個(gè)一個(gè)的通道看成一個(gè)一個(gè)的盒子,物體經(jīng)過(guò)盒子進(jìn)行加工,然后出來(lái)尉桩,就可以了筒占。
1: subshader 包裝了一個(gè)渲染方案,這些方案由一個(gè)個(gè)通道(Pass)來(lái)執(zhí)行的蜘犁,SubShader可以包括很多通道塊,每個(gè)Pass都能使幾何體渲染一次;
2: Pass基本語(yǔ)法:
Pass { [Name and Tags] [RenderSetup] [Texture Setup]}
Pass塊的Name引用此Pass,可以在其它著色器的Pass塊中引用它翰苫,減少重復(fù)操作,Name命令必須打大寫;
RegularPass 通道渲染設(shè)置
1: Lighting 光照: 開(kāi)啟關(guān)閉定點(diǎn)光照 On/Off
2: Material{材質(zhì)塊}: 材質(zhì),定義一個(gè)使用定點(diǎn)光照管線的材質(zhì);
3:ColorMaterial: 顏色集 計(jì)算定點(diǎn)光照的時(shí)使用頂點(diǎn)顏色;
4: SeparateSpecular: 開(kāi)光狀態(tài) 開(kāi)啟或關(guān)閉頂點(diǎn)光照相關(guān)的鏡面高光顏色,On/Off;
5: Color 設(shè)置定點(diǎn)光照關(guān)閉時(shí)的所使用的顏色;
6: Fog{霧塊}: 設(shè)置霧參數(shù);
7: AlphaTest: Alpha測(cè)試
8: ZTest: 深度測(cè)試模式;
9: ZWrite: 深度寫模式;
10: Blend: 混合模式 SourceBlendMode, DestBlendMode, AlphaSourcesBlendMode, AlphaDstBlendMode;
11: ColorMask 顏色遮罩: 設(shè)置顏色遮罩,顏色值可以由RGB或A或0或R,G,B,A的組合,設(shè)置為0關(guān)閉所有顏色通道渲染;
12: Offset偏移因子: 設(shè)置深度偏移;
UsePass特殊通道
1: UsePass: 插入所有來(lái)自其它著色器的給定名字的通道;
UsePass ”Shader/Nmae”, Name為著色器通道;
UsePass “Specular/BASE” // 插入Specular中為Bass的通道;
GrabPass
1: GrabPass {}: 一種特殊通道類型沽瘦,他會(huì)捕獲物體所在的位置的屏幕的內(nèi)容革骨,并寫入一個(gè)紋理中,這個(gè)紋理能被用于后續(xù)通道中完成一些高級(jí)圖像特效,后續(xù)通道可以使用
_GrabTexture進(jìn)行訪問(wèn);
2: GrabPass{“紋理名稱”} 捕獲屏幕內(nèi)容到指定紋理中析恋,后續(xù)通道可以通過(guò)紋理名稱來(lái)訪問(wèn);
Category分類
1:分類是渲染命令的邏輯組良哲。例如著色器可以有多個(gè)子著色器,他們都需要關(guān)閉霧效果,和混合
Shader “xxxx” {
Categroy {
Fog { Mode Off }
SubShader {...}
SubShader {...}
}
}