頂點片元著色器(important)
1.需要在Pass渲染通道中編寫著色器邏輯
2.可以使用cG或HLSL兩種shader語言去編寫Shader邏輯
3.代碼量較多,靈活性較強,性能消耗更可控,可以實現更多渲染細節
4.適用于光照處理較少,自定義染效果較多時(移動平臺首選)
表面著色器是Unity對頂點/片元著色器的封裝
可以用更少的代碼實現復雜的邏輯
但是性能和可控性較差
它的特點是
1.直接在subshader語句塊中書寫著色器邏輯
2.我們不需要關心也不需要使用多個Pass,每個Pass如何染,Unity會在內部幫助我們去處理
3.可以使用cG或HLSL兩種shader語言去編寫shader邏輯
4.代碼量較少,可控性較低,性能消耗較高
5.適用于處理需要和各種光源打交道的著色器,但是在移動平臺上需要注意性能表現
表面著色器 和頂點/片元著色器這兩種unity Shader形式都使用了可編程管線
而對于一些老設備(Dx7.0、0penGL1.5或OpenGLES1.1):它們不支持可編程管線著色器
這時就需要使用固定函數著色器來進行渲染
這些著色器只能實現一些非常簡單的效果
它的特點是:
1.需要在Pass染通道中編寫著色器邏輯
2.需要使用shaderLab語法中的染設置命令來編寫,而非cG和HLSL著色器語言
但是由于這些舊設備目前市面上幾乎已經沒有了
所以固定函數著色器我們幾乎不會再使用
只做了解即可
即使我們現在在unity中使用固定函數著色器來編寫Shader,在內部也會被編譯為頂點/片元著色器
因此真正意義的固定函數著色器已經不存在了
subshader語句塊
渲染標簽
通過標簽來確定什么時候以及如何對物體進行渲染
渲染隊列(Render Queue)優化渲染效率、正確處理透明物體、減少渲染錯誤
隊列名 | 隊列值(Queue) | 渲染順序(從小到大) | 用途 |
---|---|---|---|
Background | 1000 | 最早渲染 | 用于背景物體,通常比不透明物體更早渲染 |
Geometry | 2000 | 渲染大部分不透明物體 | 絕大多數 3D 模型、地面、建筑 |
AlphaTest | 2450 | 用于透明裁剪(如葉子、柵欄) | 用于 clip() 處理的材質,如草叢、柵欄 |
Transparent | 3000 | 后渲染(需要正確混合透明效果) | 玻璃、水、煙霧等需要 Alpha 混合的對象 |
Overlay | 4000 | 最晚渲染 | UI、HUD、特效等最前景的物體 |
(Opaque) → 應該先渲染,因為它們會遮擋后面的物體,減少 GPU 計算量
(Transparent) → 必須后渲染,否則無法正確混合(比如玻璃、水等)透明物體依賴前面已經渲染好的背景
特效、后處理 → 可能需要在所有物體之后渲染。
- 你有 半透明水,希望它在透明物體 之后 渲染,但又不想晚于 UI → 可以設定
"Queue" = "Transparent + 10"
- 你有 特效 Shader,希望它比普通透明物體 稍早渲染,避免遮擋問題 → 可以設定
"Queue" = "Transparent - 1"
RenderType方便 Unity 進行批量優化,
渲染管線(Render Pipeline)或后處理效果(Post Processing)可以識別、管理和優化不同類型的 Shader
一個 SubShader 只能有一個 RenderType
當使用批處理時,模型會被變換到世界空間中,模型空間會被丟棄
這可能會導致某些使用模型空間頂點數據的shader最終無法實現想要的結果
可以通過開啟禁用批處理來解決該問題
?
渲染狀態
通過狀態來確定渲染時的剔除方式、深度測試方式、混合方式等等內容
Shader 間接控制片元,光柵化階段(Rasterization) 生成GPU 底層的片元
Shader 控制的片元是 GPU 片元的“表現層”
片元(Fragment)主要由片元著色器(Fragment Shader)或像素著色器(Pixel Shader)控制,表示屏幕上即將被渲染的像素信息(顏色、深度等)
剔除,就是不渲染,背面剔除就是背面不渲染,正面剔除就是正面不渲染,不剔除就是都渲染
Cull Back背面剔除
Cull Front正面剔除
Cull off不剔除
不設置的話,默認為背面剔除
深度緩沖(Depth Buffer):
深度緩沖是一個與屏幕像素對應的緩沖區,用于存儲每個像素的深度值(距離相機的距離)。
在渲染場景之前,深度緩沖被初始化為最大深度值,表示所有像素都在相機之外。
最后留在深度緩沖中的信息會被染
ZWrite on寫入深度緩沖
Zwrite off不寫入深度緩沖
不設置的話,默認為寫入
一般情況下,我們在做透明等特殊效果時,會設置為不寫入
當前像素的深度值小于深度緩沖中的值,說明當前像素在其他物體之前,它會被繪制,并更新深度緩沖。
當前像素的深度值大于等于深度緩沖中的值,說明當前像素在其他物體之后,它會被丟棄,不會被繪制,并保持深度緩沖不變。
當前深度緩沖中的值
ZTest Less
ZTest Greater
ZTest LEqual 小于等于
ZTest GEqual 大于等于
ZTest Equal
ZTest NotEqual不等于當前深度緩沖中的值,就通過測試,寫入到深度緩沖中
ZTestAlways 始終通過深度測試,寫入深度緩沖中
不設置的話,默認為LEqual
深度緩沖(Z-Buffer)用于存儲每個像素的深度值(Z 值),片元的深度值由 投影變換后的位置 計算得出
混合是在深度測試之后去進行的,混合過后它就會把顏色存入到一個顏色緩沖區當中,顏色緩沖區其實就是一個內存空間,
混合(Blending)決定當前片元的顏色如何與已經存儲在顏色緩沖區的顏色進行合成,常用于半透明材質、特效(如火焰、光暈、煙霧)
混合發生在 深度測試(Z-Test)之后,顏色寫入(Color Write)之前:先檢查 當前片元(Fragment) 是否應該被渲染,如果當前片元被擋住(ZTest 失敗) → 直接丟棄,不執行混合
如果通過,獲取當前片元的顏色(源顏色,SrcColor),獲取顏色緩沖區(Framebuffer)中的顏色(目標顏色,DstColor)
常見的混合模式(Blend Mode)
混合模式 | 公式 | 用途 |
---|---|---|
Alpha 混合 | FinalColor = SrcColor * SrcAlpha + DstColor * (1 - SrcAlpha) | 玻璃、煙霧、透明物體 |
Additive(加法混合) | FinalColor = SrcColor * 1 + DstColor * 1 | 光效、火焰、魔法特效 |
Multiplicative(乘法混合) | FinalColor = SrcColor * DstColor | 陰影、濾鏡效果 |
Shader "Custom/LODExample"
{
? ? SubShader
? ? {
? ? ? ? LOD 100
? ? ? ? Pass { /* 低 LOD 的 Shader 代碼 */ }
? ? }? ? SubShader
? ? {
? ? ? ? LOD 300
? ? ? ? Pass { /* 高 LOD 的 Shader 代碼 */ }
? ? }
}
ColorMask 配置 | 用途 |
---|---|
ColorMask RGB | 忽略 Alpha 通道,避免透明度影響 |
ColorMask A | 僅寫入 Alpha,用于特效 |
ColorMask 0 | 只影響深度緩沖,不影響顏色(Shadow Map) |
一個Shader設定之后,執行順序
步驟 | 執行階段 | Shader 相關代碼 | 作用 |
---|---|---|---|
① 解析 Shader 標簽 | Shader 解析階段 | Tags { "Queue"="Geometry" } | 確定渲染順序、是否透明 |
② 選擇 SubShader | 運行時自動匹配 | LOD 300 | 選擇適合當前硬件的 Shader |
③ Pass 開始 | GPU 處理 | Pass {} | 進入渲染 Pass |
④ 處理渲染狀態 | 設置 GPU 狀態 | Cull Back 、ZTest Less | 控制渲染面、深度計算方式 |
⑤ 片元著色器執行 | GPU 計算顏色 | frag() | 計算顏色值 |
⑥ 深度測試 | 片元寫入前 | ZTest 、ZWrite | 確保正確的片元渲染 |
⑦ 顏色混合 | 顏色計算 | Blend | 計算透明度混合 |
⑧ 顏色寫入 | 最終像素寫入 | ColorMask RGB | 控制通道寫入 |
在subshader語句塊中使用渲染狀態會影響之后的所有渲染通道Pass
在Pass語句塊中使用渲染狀態只會影響當前Pass渲染通道,不會影響其他的Pass
渲染通道
具體實現著色器代碼的地方(每個subshader語句塊中至少有一個渲染通道,可以有多個)
Unity內部會把Pass名稱轉換為大寫字母
因此在使用usePass命令時必須使用大寫形式的名字
在其他shader中復用該Pass代碼時
UsePass "TeachShader/Lesson4/MYPAss"
但是subshader語句塊中的 渲染標簽 不能夠在Pass中使用
Pass當中有自己專門的標簽
1.Tags{"LightMode”=“標簽值"}
主要作用
指定了該Pass應該在哪個階段執行
可以將著色器代碼分配給適當的渲染階段,以實現所需的效果
Always
始終渲染:不應用光照
ForwardBase
在前向渲染中使用:應用環境光、主方向光、頂點/SH光源和光照貼圖
ForwardAdd
在前向染中使用:應用附加的每像素光源(每個光源有一個通道)
Deferred
在延遲渲染中使用;渲染G緩沖區
Shadowcaster
將對象深度染到陰影貼圖或深度紋理中
MotionVectors
用于計算每對象運動矢量
PrepassBase
在舊版延遲光照中使用;渲染法線和鏡面反射指數
PrepassFinal
在舊版延遲光照中使用:通過組合紋理、光照和反光來渲染最終顏色
Vertex
當對象不進行光照貼圖時在舊版頂點光照誼染中使用;應用所有頂點光源
VertexLMRGBM
當對象不進行光照貼圖時在舊版頂點光照渲染中使用;在光照貼圖為 RGBM 編碼的平臺上(PC 和游戲主機)
VertexLM
當對象不進行光照貼圖時在舊版頂點光照渲染中使用;在光照貼圖為雙LDR編碼的平臺上(移動平臺)
2.Tags{“RequireOptions”=“標簽值”}
主要作用
用于指定當滿足某些條件時才渲染該Pass
3.Tags{"PassFlags"="標簽值"}
主要作用:
一個染通道Pass可指示一些標志來更改染管線向Pass傳遞數據的方式
目前unity僅支持
Tags{"PassFlags"="OnlyDirectional"}
意味著非重要光源的數據將不會傳遞到頂點光源或球諧函數著色器變量
備用shader的語法非常簡單
Fallback "shader名"
或者
FallbackOff
它的主要作用就是提供“救命稻草”
我們一般會使用較為低級的效果作為備用shader
確保對象在低端設備上也能夠正常渲染
-------------------
Shader的屬性主要就是三種類型
數值、顏色和向量、紋理貼圖
我們只需要掌握屬性聲明的基礎語法即可
它的主要是:
1.可以在材質面板被編輯
2.可以在后續當作輸入變量提供給所有子著色器使用
紋理貼圖屬性的定義
1.顏色
Name("Display Name",Color) =(number1,number2,number3,number4)
注意:顏色值中的RGBA的取值范圍是0~1(映射e~255)
2.向量
Name("Display Name",Vector)=(number1,number2,number3,number4)
注意:向量值中的XYZW的取值范圍沒有限制
Shader選擇的路徑
1.直接修改shader文件中Shader后的名字即可
2.Shader的名字決定了在材質面板的選擇路徑
可以選擇對應的圖形接口,生成查看(方便根據不同平臺的情況去查看Shader生成的對應代碼)
PBR 參數(Metallic、Smoothness、Albedo)FX Shader(特效 Shader)
一般的使用流程是
Shader---材質----賦值給GameObject對象上依附的MeshRenderer等相關渲染器組件上進行使用
為什么 Unity 需要 ShaderLab?
ShaderLab 是 Unity 專用的著色器(Shader)編寫語言,用于定義 Unity 渲染管線如何處理 材質、光照、特效 等。它的作用類似于 OpenGL 的 GLSL、DirectX 的 HLSL,但 ShaderLab 不是單純的編程語言,而是一個著色器封裝框架,允許你在 Unity 里編寫 Shader 代碼,同時管理材質參數和渲染狀態。
提供了 結構化的寫法可以用 HLSL(高階著色器語言) 來寫 Shader
管理 Pass、渲染狀態、ShaderLab 里定義 Shader 變量、HLSL 計算最終顏色
Unity 默認的所有 Shader 都是 ShaderLab 結構
Unity 的核心設計理念是 跨平臺 + 可擴展、允許開發者自定義 Shader、兼顧不同的渲染后端(如 DirectX、OpenGL、Vulkan、Metal)
Windows(DirectX)、Mac(Metal)、安卓(Vulkan)、WebGL(OpenGL)每個平臺的 Shader 語言都不一樣
ShaderLab 的核心作用就是對各個平臺的 Shader 語言進行封裝和統一,讓開發者在 Unity 里寫 Shader 時不需要直接面對不同的底層 API(DirectX、Metal、Vulkan、OpenGL),而是通過 ShaderLab 提供的統一結構來管理和適配不同平臺。
Technical Artist核心技能要求:
Shader & 渲染優化(最核心)【第 1 階段:3-5 周】
為什么先學 Shader?
Shader 是 TA 的核心技能,它控制了畫面的最終呈現,而且學 Shader 能直接出作品,有利于建立信心和作品集。
? 學習 Shader 編程
- HLSL(Unity) → Unity Shader Graph + ShaderLab
- GLSL(OpenGL)(如果以后想研究 OpenGL)
- Unreal Shader(USF)(如果想做 Unreal 開發)
- 練習:寫幾個基礎 Shader(溶解、描邊、透明效果)
? 理解現代渲染管線
- 先學 Unity SRP(URP/HDRP)
- 再學 Unreal 渲染架構(Deferred / Forward)
- 練習:用 Unity URP/HDRP 寫一個 PBR Shader
? 性能優化
- Draw Call 優化
- GPU Profiler 調試
- LOD、貼圖優化
- 練習:優化一個小場景(減少 Draw Call,提升 FPS)
美術工具 & 資產管線【第 2 階段:3-4 周】
為什么第二步學美術工具?
Shader 只是渲染的一部分,但模型、貼圖、動畫 都由美術資源決定,你要學會如何處理這些資源,提高美術生產效率。
? 熟悉 3D 美術工具
- Maya / Blender(基本建模、綁定)
- Photoshop(貼圖處理)
- ZBrush(雕刻,次世代角色管線)
- 練習:制作一個簡單的 3D 角色(帶 UV 和貼圖)
? 資產管線(Art Pipeline)
- 如何高效導入游戲資源(FBX、USD、GLTF)
- 練習:導出 FBX,并正確在 Unity / Unreal 里顯示
? 材質 & 貼圖
- UV 貼圖、法線貼圖、光照貼圖(Lightmap)
- 練習:給一個 3D 物體制作完整材質
編程能力(技術美術必備)【第 3 階段:4-6 周】
為什么第三步學編程?
Shader 和美術技能都有了之后,就需要寫工具來提升工作流效率,比如自動化模型導入、Shader 調試工具等。
? 掌握一門編程語言
- C++(Unreal Engine)
- C#(Unity,SRP、Editor Tool)
- Python(Maya / Blender 插件,工具開發)
- 練習:用 Python 寫一個 Maya 插件(自動導出 FBX)
? 圖形 API(進階,選學)
- OpenGL / DirectX / Vulkan(如有更深入需求)
- 練習:用 OpenGL 畫一個簡單的模型渲染
? 工具開發
- 用 Python/C++ 編寫插件,提升美術工作效率
- 練習:制作一個 Unity 編輯器工具(批量修改 Shader 參數)
美術基礎 & 審美?-----長期積累
為什么美術基礎放到第四步?
因為審美是長期積累的東西,你需要在 Shader、美術管線、工具開發的過程中不斷鍛煉它。
? 良好的色彩、光影、構圖感
- 練習:調整一個 3D 場景的光照,讓它更好看
- 練習:用后處理(Post Processing)做出電影感
? 了解動畫、綁定
- 角色管線:綁定、蒙皮(Maya / Blender)
- 動畫導入導出、IK 處理
- 練習:綁定一個角色,并在游戲中正確播放動畫
加分項(可選學習)
這些內容可以在 掌握了基礎之后 選擇性學習。
? VFX(特效)
- Unity VFX Graph、Unreal Niagara
- 粒子系統、流體模擬(Houdini)
- 練習:制作一個魔法特效
? 后處理(Post Processing)
- Bloom、DOF、Motion Blur、Color Grading
- 練習:制作一個高質量的后處理特效
? 機器學習(次世代游戲優化)
- AI 生成貼圖、智能 LOD 優化
- 了解 NVIDIA DLSS、AI Upscaling
- 練習:用 AI 生成貼圖并優化資源
30 天計劃快速入門:
第 1-2 周(Shader 基礎)
? 了解 Unity ShaderLab / HLSL
? 做一個溶解 Shader、描邊 Shader
? 了解光照模型(PBR)
第 3-4 周(渲染優化 + 美術管線)
? 了解 Unity SRP / HDRP
? 了解 Draw Call 優化、GPU Profiler
? 掌握 Maya、PS 的基礎,能導入 3D 資源
第 5-6 周(編程 + 自動化工具)
? 掌握 C++ / C#(Unity / Unreal)
? 用 Python 寫一個工具,優化美術管線
? 用 C# 在 Unity 里開發一個小插件
第 7 周(整合作品)
? 制作一個 Shader + VFX 效果
? 導出 FBX,優化資源,并展示在游戲中
? 用 GPU Profiler 進行優化