着色器

電腦圖學領域中，**著色器**（英語：**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 的像素塊。
* 像素塊通過片段著色器被修改。
* 進行深度測試；通過的片段將被寫入螢幕，並可能被混合到影格緩衝區中。

## 種類

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

### 二維著色器

二維著色器處理的是數位影像，也叫紋理，著色器可以修改它們的像素。二維著色器也可以參與三維圖形的彩現。目前只有「像素著色器」一種二維著色器。

#### 像素著色器

**像素著色器**（英語：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
* SPIR-V
* HLSL
* 著色器語言
* GPGPU

## 參考資料

## 拓展閱讀

* 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