著色器

電腦圖形學領域中，著色器（shader）是一種電腦程式，原本用於進行圖像的濃淡處理（計算圖像中的光照、亮度、顏色等），但近來，它也被用於完成很多不同領域的工作，比如處理CG特效、進行與濃淡處理無關的影片後期處理、甚至用於一些與電腦圖形學無關的其它領域。

使用著色器在圖形硬體上計算渲染效果有很高的自由度。儘管不是硬性要求，但目前大多數著色器是針對GPU開發的。GPU的可編程繪圖管線已經全面取代傳統的固定管線，可以使用著色器語言對其編程。構成最終圖像的像素、頂點、紋理，它們的位置、色相、飽和度、亮度、對比度也都可以利用著色器中定義的演算法進行動態調整。調用著色器的外部程序，也可以利用它向著色器提供的外部變量、紋理來修改這些著色器中的參數。

在電影後期處理、電腦成像、電子遊戲等領域，著色器常被用來製作各種特效。除了普通的光照模型，著色器還可以調整圖像的色相、飽和度、亮度、對比度，生成模糊、高光、有體積光源、失焦、卡通渲染、色調分離、畸變、凹凸貼圖、色鍵（即所謂的藍幕、綠幕摳像效果）、邊緣檢測等效果。

## 歷史

1988年5月，Pixar公布了第三版RenderMan規範，將「著色器」的使用推廣到了我們目前所知的各大應用領域。

隨著圖形處理器的進步，OpenGL和Direct3D等主要的圖形軟體庫都開始支持著色器。第一批支持著色器的 GPU 僅支持像素著色器，但隨著開發者逐漸認識到著色器的強大，很快便出現了頂點著色器。2000年，第一款支持可編程像素著色器的顯卡 Nvidia GeForce 3（NV20）問世。Direct3D 10 和 OpenGL 3.2 則引入了幾何著色器。

目前，圖形硬體正在朝統一著色器模型發展。

## 設計

著色器是描述頂點或像素特徵的簡單程序。頂點著色器描述頂點的屬性（位置、紋理坐標、顏色等），而像素著色器描述像素的特徵（顏色、z深度和alpha值）。

基本圖形管線如下所示：

- 中央處理器（CPU）發送指令(已編譯的著色器程序)和幾何數據到位於顯卡內的圖形處理器（GPU）。
- 頂點著色器執行幾何變換。
- 若幾何著色器位於圖形處理器內並已激活，它便會修改一些場景中的幾何結構。
- 若細分著色器位於圖形處理器內並已激活，場景中的幾何結構會被細分。
- 計算後的幾何結構被三角化（分割為三角形）。
- 三角形被分解為2 × 2的像素塊。
- 像素塊通過片段著色器被修改。
- 進行深度測試；通過的片段將被寫入螢幕，並可能被混合到幀緩衝區中。

## 種類

常用的著色器有三種。比較老的顯卡傾向於使用不同的處理單元處理不同類型的著色器，但新出的顯卡通常都支持統一著色器模型，可以執行任意類型的著色器、更好地發揮顯卡的處理能力。

### 二維著色器

二維著色器處理的是數字圖像，也叫紋理（texture），著色器可以修改它們的像素。二維著色器也可以參與三維圖形的渲染。目前只有「像素著色器」一種二維著色器。

#### 像素著色器

像素著色器（pixel shader）也叫片段著色器（fragment shader），用於計算「片段」的顏色和其它屬性，此處的「片段」通常是指單獨的像素。最簡單的像素著色器只有輸出顏色值；複雜的像素著色器可以有多個輸入輸出。像素著色器既可以永遠輸出同一個顏色，也可以考慮光照、做凹凸貼圖、生成陰影和高光，還可以實現半透明等效果。像素著色器還可以修改片段的深度，也可以為多個渲染目標輸出多個顏色。

三維圖形學中，單獨一個像素著色器並不能實現非常複雜的效果，因為它只能處理單獨的像素，沒有場景中其它幾何體的資訊。不過，像素著色器有螢幕坐標資訊，如果將螢幕上的內容作為紋理傳入，它就可以對當前像素附近的像素進行採樣。利用這種方法，可以實現大量二維後期特效，例如模糊和邊緣檢測。

像素著色器還可以處理管線中間過程中的任何二維圖像，包括精靈和紋理。因此，如果需要在柵格化後進行後期處理，像素著色器是唯一選擇。

### 三維著色器

三維著色器處理的是三維模型或者其它幾何體，可以訪問用來繪製模型的顏色和紋理。頂點著色器是最早的三維著色器；幾何著色器可以在著色器中生成新的頂點；細分曲面著色器（tessellation shader）則可以向一組頂點中添加細節。

#### 頂點著色器

頂點著色器是最常見的一種 3D 著色器，對每個交給圖形處理器的頂點都運行一次。目的是將每個頂點在虛擬空間中的 3D 坐標變換到在螢幕上顯示的 2D 坐標（深度緩衝（Z-Buffer）的深度值也是如此）。頂點著色器可以掌控頂點的位置、顏色和紋理坐標等屬性，但無法生成新的頂點。頂點著色器的輸出傳遞到流水線的下一步。如果有之後定義了幾何著色器，則幾何著色器會處理頂點著色器的輸出數據，否則，光柵化器繼續流水線任務。

### 幾何著色器

幾何著色器在 OpenGL 3.2 和 Direct3D 10 中被引入, 以前可在帶擴展的 OpenGL 2.0+ 中使用。改類型的著色器可以生成新的圖形基元，比如點，線和三角形。幾何著色器可以從多邊形網格中增刪頂點。它能夠執行對 CPU 來說過於繁重的生成幾何結構和增加模型細節的工作。Direct3D 10 增加了支持幾何著色器的API，成為 Shader Model 4.0 的組成部分。OpenGL 只可通過它的一個插件來使用幾何著色器，但極有可能在3.1版本中該功能將會歸併。幾何著色器的輸出連接光柵化器的輸入。

#### 曲面細分著色器

曲面細分著色器作為一類新的著色器，在 OpenGL 4.0 和 Direct3D 11 中被引入，並在著色器的模型增加了兩個階段：曲面細分控制著色器(或外殼著色器)和曲面細分評估著色器(或域著色器)。這允許了較簡單的網格藉由特定函式計算，實時被細分成更細膩的網格。這個函示可以與多種變數相關，包含與視點的距離，因此可以主動調整細節層次，使較接近相機的物體有著較多細節。藉由在著色器單元中才加上細節，這還可以大幅降低網格所需的頻寬，也不需要降採樣記憶體中的網格。有些計算方式可以上採樣任意的網格，有些則允許「提示」網格所要凸顯的頂點和邊緣。

#### 圖元和網格著色器

大約 2017 年, 圖元著色器做為新的著色器階段被 AMD Vega 微體系結構所支持。類似可以訪問必要數據的計算著色器來處理幾何體。

#### 光線追蹤著色器

光線追蹤著色器被微軟的 DirectX 光線追蹤，Khronos Group 的 Vulkan，GLSL 和 SPIR-V，蘋果的 Metal 所支持。

#### 計算著色器

計算著色器並不僅限於圖形應用程式，還有使用相同的通用圖形處理單元執行資源的程序。它們可能在圖形管線中被使用，比如額外的動畫階段或光照演算法。一些渲染 API 允許計算著色器輕鬆的與圖形管線共享數據資源。

## 並行處理

著色器被用來同時處理大量的數據，比如螢幕上的一整塊像素群，或者一個模型結構的所有頂點。並行計算適用於這樣的情況，而且當今的GPU也設計有多核結構來極大的提高處理效率。

## 編程

用於編寫著色器的程式語言取決於目標環境。官方的OpenGL和OpenGL ES著色語言是OpenGL著色語言，也稱為GLSL，官方的Direct3D著色語言是高級著色器語言，也稱為HLSL。Cg是英偉達開發的第三方著色語言，可輸出OpenGL和Direct3D著色器；然而，自2012年以來，它一直被棄用。蘋果發布了自己的著色語言，稱為Metal著色語言，作為Metal框架的一部分。

### GUI 著色器編輯器

現代電子遊戲開發平台，如 Unity，Unreal Engine 和 Godot 越來越多的包含了基於節點的編輯器，允許創建著色器而無需編寫實際的代碼。向使用者展現了包含相互連接的節點的有向圖，允許用戶將各種各樣的紋理，映射和數學函數直接導向輸出值，如漫反射顏色，高亮和強度，金屬度/粗糙度，高度，法向量等。自動將這些圖編譯為實際的已編譯的著色器。

## 拓展閱讀

- GLSL : OpenGL Shading Language @ Lighthouse 3D - GLSL Tutorial
- Steve Upstill: The RenderMan Companion: A Programmer's Guide to Realistic Computer Graphics, Addison-Wesley, ISBN 0-201-50868-0
- David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley: Texturing and modeling: a procedural approach, AP Professional, ISBN 0-12-228730-4. Ken Perlin is the author of Perlin noise, an important procedural texturing primitive.
- Randima Fernando, Mark Kilgard. The Cg Tutorial: The Definitive Guide to Programmable Real-Time Graphics, Addison-Wesley Professional, ISBN 0-321-19496-9
- Randi J. Rost: OpenGL Shading Language, Addison-Wesley Professional, ISBN 0-321-19789-5
- Riemer's DirectX & HLSL Tutorial : HLSL Tutorial using DirectX with lots of sample code
- GPGPU: general purpose GPU
- MSDN: Pipeline Stages (Direct3D 10)

## 外部連結

- Geometry shader tutorial
- nVidia releases a new programming environment and language compiler specifically for writing science applications that run on the shader units of its graphics cards. Also see developer's home page .
- OpenGL geometry shader extension