title: unity-shader-SamplerState採樣器
categories: Unity3d-Shader
tags: [unity, shader, SamplerState, 採樣器]
date: 2019-05-23 01:35:28
comments: false
unity-shader-SamplerState採樣器
前篇
- 官方文檔: Using sampler states - https://docs.unity3d.com/Manual/SL-SamplerStates.html
說明
之前對在玩 ue4-shader-自定義shader代碼hlsl 就時裏面的 SamplerState 不瞭解, 現在查看 shader graph 內置節點 Normal From Texture 的源碼時又遇到了纔去查了下.
官方 Normal From Texture 節點的源碼
void Unity_NormalFromTexture_float(Texture texture, SamplerState Sampler, float2 UV, float Offset, float Strength, out float3 Out)
{
Offset = pow(Offset, 3) * 0.1;
float2 offsetU = float2(UV.x + Offset, UV.y);
float2 offsetV = float2(UV.x, UV.y + Offset);
float normalSample = Texture.Sample(Sampler, UV);
float uSample = Texture.Sample(Sampler, offsetU);
float vSample = Texture.Sample(Sampler, offsetV);
float3 va = float3(1, 0, (uSample - normalSample) * Strength);
float3 vb = float3(0, 1, (vSample - normalSample) * Strength);
Out = normalize(cross(va, vb));
}
我翻譯後實現: [Normal From Texture 的實現](#Normal From Texture 的實現)
現在一般採用紋理是都用這樣的語法, 使用 sampler2D,sampler3D,samplerCUBE HLSL關鍵字同時聲明貼圖和取樣器。
sampler2D _MainTex;
// ...
half4 color = tex2D(_MainTex, uv);
大部分圖形API和CPU允許貼圖比採樣器多,並且耦合的貼圖+採樣器在寫複雜的shader時可能是不允許的。比如在D3D 11中一個shader中可以使用128張貼圖,但是最多卻只有16個採樣器。
unity允許聲明貼圖和採樣器時使用DX11風格的HLSL語法,用一個特殊的命名慣例來將他們匹配起來;擁有名字爲“sampler”+貼圖名字 的採樣器會對這個紋理進行取樣。
Texture2D _MainTex;
SamplerState sampler_MainTex; // "sampler" + “_MainTex”
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);
unity提供幾個shader宏命令來幫助聲明和採樣貼圖使用這個“分離的採樣器”方法,查看 built-in macros.上面的例子可以被重寫爲下面的樣子:
`UNITY_DECLARE_TEX2D(_MainTex);``UNITY_DECLARE_TEX2D_NOSAMPLER(_SecondTex);``UNITY_DECLARE_TEX2D_NOSAMPLER(_ThirdTex);``// ...``half4 color = UNITY_SAMPLE_TEX2D(_MainTex, uv);``color += UNITY_SAMPLE_TEX2D_SAMPLER(_SecondTex, _MainTex, uv);``color += UNITY_SAMPLE_TEX2D_SAMPLER(_ThirdTex, _MainTex, uv);`
實例代碼
用 unlit shader 爲模板改一下
-
代碼
Shader "test/SamplerState_unlit" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; // sampler2D _MainTex; float4 _MainTex_ST; // Texture2D _MainTex; // SamplerState sampler_MainTex; UNITY_DECLARE_TEX2D(_MainTex); v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // fixed4 col = tex2D(_MainTex, i.uv); // fixed4 col = _MainTex.Sample(sampler_MainTex, i.uv); fixed4 col = UNITY_SAMPLE_TEX2D(_MainTex, i.uv); return col; } ENDCG } } }
-
效果 (tiling 不起作用, 暫時沒去找解決方案)
Normal From Texture 的實現
參考官方 shader graph 的實現: Normal From Texture - https://docs.unity3d.com/Packages/[email protected]/manual/Normal-From-Texture-Node.html
-
shader
Shader "test/Bump2Normal" { Properties { _MainTex ("Texture", 2D) = "white" {} _Offset ("Offset", Float) = 0.5 _Strength ("Strength", Float) = 10 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; float _Offset; float _Strength; // sampler2D _MainTex; float4 _MainTex_ST; UNITY_DECLARE_TEX2D(_MainTex); v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { float offset = _Offset; float Strength = _Strength; float3 Out = float3(0, 0, 0); float2 offsetUV = i.uv; offset = pow(offset, 3) * 0.1; float2 offsetU = float2(offsetUV.x + offset, offsetUV.y); float2 offsetV = float2(offsetUV.x, offsetUV.y + offset); float normalSample = UNITY_SAMPLE_TEX2D(_MainTex, offsetUV); float uSample = UNITY_SAMPLE_TEX2D(_MainTex, offsetU); float vSample = UNITY_SAMPLE_TEX2D(_MainTex, offsetV); float3 va = float3(1, 0, (uSample - normalSample) * Strength); float3 vb = float3(0, 1, (vSample - normalSample) * Strength); Out = normalize(cross(va, vb)); return fixed4(Out, 1); } ENDCG } } }
-
效果