unity-shader-tutorial-dither

buildin效果图

urp效果图

概念

用有限的颜色来表示出多种色阶变化的技术叫做dither。

Dither.shader

Dither.shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
Shader "HHF/Tutorial/Dither"
{
Properties
{
_BaseColor("Base Color",color) = (1,1,1,1)
_BaseMap("BaseMap", 2D) = "white" {}
_DitherMap("DitherMap", 2D) = "white" {}
_Clip("Clip",range(0,1)) = 0
}

SubShader
{
Tags { "Queue"="Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True" "RenderPipeline" = "UniversalPipeline"}
LOD 100

Pass
{
HLSLPROGRAM
// Required to compile gles 2.0 with standard srp library
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};

CBUFFER_START(UnityPerMaterial)
half4 _BaseColor;
float4 _BaseMap_ST;
half _Clip;
CBUFFER_END
TEXTURE2D (_BaseMap);SAMPLER(sampler_BaseMap);
TEXTURE2D (_DitherMap);SAMPLER(sampler_DitherMap);

// 2x2的矩阵
half Dither2x2_Matrix(uint2 uv )
{
uv %= 2;
float2x2 M2x2 = float2x2(
0,1,
1,0
);
return M2x2[uv.x][uv.y];
}

// 4x4的矩阵
half Dither4x4_Matrix(uint2 uv )
{
uv %= 4;
float4x4 M4x4 = float4x4(
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
);
return M4x4[uv.x][uv.y];
}

// 4x4的数组
half Dither4x4_Array(uint2 uv )
{
uv %= 4;
float A4x4[16] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
};
return A4x4[uv.x*4+uv.y];
}

// 4x4的数组
half Dither4x4Pixel_Array(uint2 uv ,half col)
{
uv %= 4;
float A4x4[16] = {
0,8,2,10,
12,4,14,6,
3,11,1,9,
15,7,13,5
};
half d = A4x4[uv.x*4+uv.y]/15;
return step(d,col);
}

// 8x8的数组
half Dither8x8_Array(uint2 uv )
{
uv %= 8;
float A4x4[64] = {
0,32,8,40,2,34,10,42,
48,16,56,24,50,18,58,26,
12,44,4,36,14,46,6,38,
60,28,52,20,62,30,54,22,
3,35,11,43,1,33,9,41,
51,19,59,27,49,17,57,25,
15,47,7,39,13,45,5,37,
63,31,55,23,61,29,53,21
};
return A4x4[uv.x*8+uv.y]/65;
}

v2f vert(appdata v)
{
v2f o = (v2f)0;
o.positionCS = TransformObjectToHClip(v.vertex.xyz);
o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
return o;
}

half4 frag(v2f i) : SV_Target
{
uint2 uv = (uint2)i.positionCS.xy;

half dither2x2_Matrix = Dither2x2_Matrix(uv);
half dither4x4_Matrix = Dither4x4_Matrix(uv);
half dither4x4_Array = Dither4x4_Array(uv);
half dither8x8_Array = Dither8x8_Array(uv);

half4 baseMap = SAMPLE_TEXTURE2D(_BaseMap,sampler_BaseMap,i.uv);
half4 ditherMap = SAMPLE_TEXTURE2D(_DitherMap,sampler_DitherMap, i.positionCS.xy % 100 / 100);
// return ditherMap.g;

// 灰度像素风
// half grey = dot(baseMap.rgb,half3(0.22,0.707,0.071));
// half dither4x4Pexil_Arry = Dither4x4Pixel_Array(uv/2,grey);

// 彩色像素风
// half dither4x4Pexil_Arry_r = Dither4x4Pixel_Array(uv/2,baseMap.r);
// half dither4x4Pexil_Arry_g = Dither4x4Pixel_Array(uv/2,baseMap.g);
// half dither4x4Pexil_Arry_b = Dither4x4Pixel_Array(uv/2,baseMap.b);
// half3 dither4x4Pexil_Arry = half3(dither4x4Pexil_Arry_r,dither4x4Pexil_Arry_g,dither4x4Pexil_Arry_b);
// return half4(dither4x4Pexil_Arry,1);

clip(ditherMap.r - _Clip);
return baseMap;
}
ENDHLSL
}
}

SubShader
{
Tags { "RenderType"="Opaque" }

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag

#include "UnityCG.cginc"
#include "AutoLight.cginc"

struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};

struct v2f
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
};

half4 _BaseColor;
half _Clip;
sampler2D _BaseMap; float4 _BaseMap_ST;
sampler2D _DitherMap;

// 2x2的矩阵
half Dither2x2_Matrix(uint2 uv )
{
uv %= 2;
float2x2 M2x2 = float2x2(
0,1,
1,0
);
return M2x2[uv.x][uv.y];
}

// 4x4的矩阵
half Dither4x4_Matrix(uint2 uv )
{
uv %= 4;
float4x4 M4x4 = float4x4(
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
);
return M4x4[uv.x][uv.y];
}

// 4x4的数组
half Dither4x4_Array(uint2 uv )
{
uv %= 4;
float A4x4[16] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
};
return A4x4[uv.x*4+uv.y];
}

// 8x8的数组
half Dither8x8_Array(uint2 uv )
{
uv %= 8;
float A4x4[64] = {
0,32,8,40,2,34,10,42,
48,16,56,24,50,18,58,26,
12,44,4,36,14,46,6,38,
60,28,52,20,62,30,54,22,
3,35,11,43,1,33,9,41,
51,19,59,27,49,17,57,25,
15,47,7,39,13,45,5,37,
63,31,55,23,61,29,53,21
};
return A4x4[uv.x*8+uv.y]/65;
}

v2f vert(appdata v)
{
v2f o = (v2f)0;
o.positionCS = UnityObjectToClipPos(v.vertex.xyz);
o.uv = TRANSFORM_TEX(v.uv, _BaseMap);
return o;
}

half4 frag(v2f i) : SV_Target
{
uint2 uv = (uint2)i.positionCS.xy;

half dither2x2_Matrix = Dither2x2_Matrix(uv);
half dither4x4_Matrix = Dither4x4_Matrix(uv);
half dither4x4_Array = Dither4x4_Array(uv);
half dither8x8_Array = Dither8x8_Array(uv);

half4 baseMap = tex2D(_BaseMap, i.uv);
half4 ditherMap = tex2D(_DitherMap, i.positionCS.xy % 100 / 100);
// return ditherMap.g;

clip(ditherMap.r - _Clip);
return baseMap;
}
ENDCG
}
}
}