Unity-使用采樣器狀態(tài)
耦合的紋理和采樣器
大多數(shù)情況下,在著色器中采樣紋理時,紋理采樣狀態(tài)應(yīng)來自紋理設(shè)置;本質(zhì)上,紋理和采樣器會耦合在一起。使用 DX9 風(fēng)格的著色器語法時,這是默認(rèn)行為:
使用 HLSL 關(guān)鍵字 sampler2D、sampler3D 和 samplerCUBE 可聲明紋理和采樣器。
大部分情況下,這是您想要的結(jié)果,而且在較舊的圖形 API (OpenGL ES) 中,這是唯一受支持的選項。
單獨的紋理和采樣器
很多圖形 API 和 GPU 都允許使用的采樣器數(shù)量少于紋理,而耦合的紋理+采樣器語法可能不允許編寫更復(fù)雜的著色器。例如,Direct3D 11 允許在單個著色器中最多使用 128 個紋理,但最多僅允許使用 16 個采樣器。
Unity 允許使用 DX11 風(fēng)格的 HLSL 語法來聲明紋理和采樣器,但需要通過一個特殊的命名約定來讓它們匹配:名稱為“sampler”+TextureName 格式的采樣器將從該紋理中獲取采樣狀態(tài)。
以上部分中的著色器代碼片段可以用 DX11 風(fēng)格的 HLSL 語法重寫,并且也會執(zhí)行相同的操作:
但這樣一來,就可以編寫著色器來重復(fù)使用其他紋理中的采樣器,同時采樣多個紋理。在以下示例中,采樣了三個紋理,但僅一個采樣器用于所有這些紋理:
但是請注意,DX11 風(fēng)格的 HLSL 語法在某些較舊的平臺(例如,OpenGL ES 2.0)上無效,請參閱著色語言以了解詳細(xì)信息。您可能希望指定?#pragma target 3.5
(請參閱著色器編譯目標(biāo))以避免較舊的平臺使用著色器。
Unity 提供了一些著色器宏幫助您使用這種“單獨采樣器”方法來聲明和采樣紋理,請參閱內(nèi)置宏。以上示例可以采用所述的宏重寫為下列形式:
以上代碼將在 Unity 支持的所有平臺上進行編譯,但會在 DX9 等舊平臺上回退到使用三個采樣器。
內(nèi)聯(lián)采樣器狀態(tài)
除了能識別名為“sampler”+TextureName 的 HLSL SamplerState 對象,Unity 還能識別采樣器名稱中的某些其他模式。這對于直接在著色器中聲明簡單硬編碼采樣狀態(tài)很有用。例如:
名稱 “my_point_clamp_sampler”將被識別為應(yīng)該使用點(距離最近)紋理過濾和鉗制紋理包裹模式的采樣器。
采樣器名稱被識別為“內(nèi)聯(lián)”采樣器狀態(tài)(全都不區(qū)分大小寫):
*“Point”、“Linear”或“Trilinear”(必需)設(shè)置紋理過濾模式。
*“Clamp”、“Repeat”、“Mirror”或“MirrorOnce”(必需)設(shè)置紋理包裹模式。
* 可根據(jù)每個軸 (UVW) 來指定包裹模式,例如"ClampU_RepeatV"。
*“Compare”(可選)設(shè)置用于深度比較的采樣器;與 HLSL SamplerComparisonState 類型和 SampleCmp/SampleCmpLevelZero 函數(shù)配合使用。
以下是分別使用?sampler_linear_repeat
?和?sampler_point_repeat
?采樣器狀態(tài)進行紋理采樣的示例,說明了如何通過名稱控制過濾模式:

以下是分別使用?SmpClampPoint
、SmpRepeatPoint
、SmpMirrorPoint
、SmpMirrorOncePoint
?和?Smp_ClampU_RepeatV_Point
?采樣器狀態(tài)的示例,說明了如何通過名稱控制包裹模式。在上一個示例中,為水平軸 (U) 和垂直軸 (V) 設(shè)置了不同的包裹模式。在任何情況下,紋理坐標(biāo)的范圍都是從 –2.0 到 +2.0。
就像單獨的紋理+采樣器語法一樣,某些平臺不支持內(nèi)聯(lián)采樣器狀態(tài)。目前在 Direct3D 11/12、PS4、XboxOne 和 Metal 上實現(xiàn)了內(nèi)聯(lián)采樣器狀態(tài)。
請注意,大部分移動端 GPU/API 上不支持“MirrorOnce”紋理包裹模式,并將在不支持的情況下回退到 Mirror 模式。
