Unity-編寫頂點和片元著色器
ShaderLab?著色器描述了在 Material Inspector 中顯示的屬性,包含用于不同圖形硬件的多個著色器實現(xiàn),并配置固定函數(shù)硬件狀態(tài)。可編程著色器(如頂點和片元程序)只是整個?ShaderLab?的著色器概念的一部分。如需了解著色器的更多信息和介紹,請參閱著色器教程。本頁將概要說明低級別硬件著色器的__著色器程序__。
如果要編寫與光照交互的著色器,請參閱表面著色器文檔。如需查看一些示例,請參閱頂點和片元著色器示例。本頁的其余部分假設(shè)著色器不與 Unity 光源(例如特殊效果和后期處理效果)交互。
著色器程序用?HLSL 語言編寫,在著色器文本中嵌入代碼片段(在?Pass?命令中的某個位置)。著色器程序通常如下所示:
?
Pass { ? ? ? ?
?// ...常規(guī)通道狀態(tài)設(shè)置 ... ? ? ? ? ? ? ?
?CGPROGRAM ? ? ? ?
?// 此代碼片段的編譯指令,例如: ? ? ? ?
?#pragma vertex vert ? ? ? ?
?#pragma fragment frag ? ? ? ? ? ? ?
?// Cg/HLSL 代碼本身 ? ? ? ? ? ?
?ENDCG ? ? ? ?
?// ...通道設(shè)置的剩余部分 ... ? ?
}
HLSL 代碼片段
HLSL 程序代碼片段寫入到?CGPROGRAM
?和?ENDCG
?關(guān)鍵字之間,或者?HLSLPROGRAM
?和?ENDHLSL
?之間。后一種形式不會自動包含 HLSLSupport 和 UnityShaderVariables?內(nèi)置頭文件。
在代碼片段的開頭,可使用?#pragma
?語句的形式提供編譯指令。下表列出的指令可指示要編譯的著色器函數(shù):
語句????????????????????????????????????????????????????????????????????????????????功能
#pragma vertex name????????????
作為頂點著色器來編譯函數(shù)?name
。
#pragma fragment name????????????
作為片元著色器來編譯函數(shù)?name
。
#pragma geometry name????????
作為 DX10 幾何著色器來編譯函數(shù)?name
。如下表中所述,此選項會自動開啟?#pragma target 4.0
。
#pragma hull name????????????
作為 DX11 外殼著色器來編譯函數(shù)?name
。如下表中所述,此選項會自動開啟?#
pragma target 5.0
。
#pragma domain name????????????
作為 DX11 域著色器來編譯函數(shù)?name
。如下表中所述,此選項會自動開啟?#pragma target 5.0
。
其他編譯指令:
語句????????????????????????????????????????????????????????????????????????????????????功能
#pragma target name????
設(shè)置要編譯到的著色器目標。有關(guān)更多信息,請參閱著色器編譯目標文檔。
#pragma require feature ...????
對著色器需要的 GPU 功能進行精細控制。有關(guān)更多信息,請參閱著色器編譯目標文檔。
#pragma only_renderers space separated names????
僅為給定的渲染器編譯著色器。默認情況下,將為所有渲染器編譯著色器。
#pragma exclude_renderers space separated names????
不為給定渲染器編譯著色器。默認情況下,系統(tǒng)會為所有渲染器編譯著色器。
#pragma multi_compile ...????
用于處理多個著色器變體。multi_compile
?著色器的未使用變體會包含在游戲構(gòu)建中。
#pragma multi_compile_local ...????
此語句類似于?multi_compile
,但是枚舉的關(guān)鍵字為本地關(guān)鍵字。請參閱編寫多個著色器程序變體:關(guān)鍵字限制文檔以了解更多信息。
#pragma shader_feature ...????
用于處理多個著色器變體。shader_feature
?著色器的未使用變體不會包含在游戲構(gòu)建中。
#pragma shader_feature_local ...????
此語句類似于?shader_feature
,但是枚舉的關(guān)鍵字為本地關(guān)鍵字。請參閱編寫多個著色器程序變體:關(guān)鍵字限制文檔以了解更多信息。
#pragma enable_d3d11_debug_symbols????
為針對 DirectX 11 編譯的著色器生成調(diào)試信息。這將允許您通過 Visual Studio 2012(或更高版本)圖形調(diào)試器來調(diào)試著色器。
#pragma hardware_tier_variants renderer name????
針對每個可以運行所選渲染器的硬件層,生成每個由系統(tǒng)編譯的著色器的多個著色器硬件變體。
#pragma hlslcc_bytecode_disassembly????
將反匯編的 HLSLcc 字節(jié)碼嵌入到轉(zhuǎn)換的著色器中。
#pragma disable_fastmath????
啟用涉及 NaN 處理的精確 IEEE 754 規(guī)則。當前這僅影響 Metal 平臺。
#pragma glsl_es2????
在 GLSL 著色器中進行設(shè)置以生成 GLSL ES 1.0(OpenGL ES 2.0),即使著色器目標為 OpenGL ES 3 也是如此。
#pragma editor_sync_compilation????
強制進行同步編譯。這僅影響 Unity Editor。
#pragma enable_cbuffer????
使用 HLSLSupport 的?CBUFFER_START(name)
?和?CBUFFER_END
?宏時,即使當前平臺不支持常量緩沖區(qū),也要發(fā)出?cbuffer(name)
。
每個代碼片段必須至少包含一個頂點程序和一個片元程序,因此需要使用
?#pragma vertex
?和?#pragma fragment
?指令。
以下編譯指令不執(zhí)行任何操作,因此可以安全刪除:
#pragma glsl
#pragma glsl_no_auto_normalization
#pragma profileoption
#pragma fragmentoption
.
Unity 僅在著色器文件中支持?#pragma
?指令,而在 include 語句中不支持。
渲染平臺
Unity 支持多種渲染 API(例如 Direct3D 11 和 OpenGL),默認情況下,Unity 將所有著色器程序編譯到所有支持的渲染器中。您可以使用?#pragma only_renderers
?或?#pragma exclude_renderers
?指令指示要編譯的渲染器。如果您使用的一些著色器語言功能在某些平臺上無法實現(xiàn),這樣做將非常有用。支持的渲染器名稱包括:
語句????????????????????????????????????????????????????????????????????????????????Renderer
d3d11????????
Direct3D 11/12
glcore????????
OpenGL 3.x/4.x
gles????????
OpenGL ES 2.0
gles3????????
OpenGL ES 3.x
metal????????
iOS/Mac Metal
vulkan????????
Vulkan
d3d11_9x????????
Direct3D 11 9.x 功能級別,通常在 WSA 平臺上使用
xboxone????????
Xbox One
ps4????????
PlayStation 4
n3ds????????
Nintendo 3DS
wiiu????????
Nintendo Wii U
在以下示例中,代碼行僅會將著色器編譯到 D3D11 模式:
# pragma only_renderers d3d11