yum-archive/Tooner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum-archive/Tooner

yumAdd 4x4 textures to ssfd9b52e08

master
87.9 KiB2551 linesraw
1#include "UnityCG.cginc"
2#include "AutoLight.cginc"
3#include "UnityPBSLighting.cginc"
4
5#include "audiolink.cginc"
6#include "aurora.cginc"
7#include "clones.cginc"
8#include "cnlohr.cginc"
9#include "disinfo.cginc"
10#include "downstairs_02.cginc"
11#include "eyes.cginc"
12#include "fog.cginc"
13#include "gerstner.cginc"
14#include "globals.cginc"
15#include "halos.cginc"
16#include "interpolators.cginc"
17#include "iq_sdf.cginc"
18#include "macros.cginc"
19#include "math.cginc"
20#include "motion.cginc"
21#include "oklab.cginc"
22#include "pbr.cginc"
23#include "pbr_overlay.cginc"
24#include "poi.cginc"
25#include "shear_math.cginc"
26#include "tone.cginc"
27#include "tooner_scroll.cginc"
28#include "trochoid_math.cginc"
29#include "zwrite_abomination.cginc"
30
31#ifndef TOONER_LIGHTING
32#define TOONER_LIGHTING
33
34float3 Shade4PointLightsWrapped(
35    float4 lightPosX, float4 lightPosY, float4 lightPosZ,
36    float3 lightColor0, float3 lightColor1, float3 lightColor2, float3 lightColor3,
37    float4 lightAttenSq,
38    float3 pos, float3 normal,
39    float wrapFactor)
40{
41    float4 toLightX = lightPosX - pos.x;
42    float4 toLightY = lightPosY - pos.y;
43    float4 toLightZ = lightPosZ - pos.z;
44
45    float4 lengthSq = 0;
46    lengthSq += toLightX * toLightX;
47    lengthSq += toLightY * toLightY;
48    lengthSq += toLightZ * toLightZ;
49
50    float4 ndotl = 0;
51    ndotl += toLightX * normal.x;
52    ndotl += toLightY * normal.y;
53    ndotl += toLightZ * normal.z;
54    
55    // Apply wrapped lighting correction
56    float4 wrapped = wrapNoL(ndotl, wrapFactor);
57    float4 corr = rsqrt(lengthSq);
58    ndotl = max(0, wrapped) * corr;
59
60    float4 atten = 1.0 / (1.0 + lengthSq * lightAttenSq);
61    float4 diff = ndotl * atten;
62
63    return diff.x * lightColor0 +
64      diff.y * lightColor1 +
65      diff.z * lightColor2 +
66      diff.w * lightColor3;
67}
68
69void getVertexLightColor(inout v2f i)
70{
71  #if defined(VERTEXLIGHT_ON)
72  float3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
73  uint normals_mode = round(_Mesh_Normals_Mode);
74  bool flat = (normals_mode == 0);
75  float3 flat_normal = normalize(
76    (1.0 / _Flatten_Mesh_Normals_Str) * i.normal +
77    _Flatten_Mesh_Normals_Str * view_dir);
78  i.vertexLightColor = Shade4PointLightsWrapped(
79    unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
80    unity_LightColor[0].rgb,
81    unity_LightColor[1].rgb,
82    unity_LightColor[2].rgb,
83    unity_LightColor[3].rgb,
84    unity_4LightAtten0, i.worldPos, flat ? flat_normal : i.normal,
85		1
86  );
87  #endif
88}
89
90v2f vert(appdata v)
91{
92#if defined(_DISCARD)
93  if (_Discard_Enable_Dynamic) {
94    return (v2f) (0.0 / 0.0);
95  }
96#endif
97
98  v2f o;
99
100  UNITY_INITIALIZE_OUTPUT(v2f, o);
101  UNITY_SETUP_INSTANCE_ID(v);
102  UNITY_TRANSFER_INSTANCE_ID(v, o);
103  UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
104  //UNITY_TRANSFER_VERTEX_OUTPUT_STEREO(v, o);
105
106#if defined(_GIMMICK_BOX_DISCARD)
107  if (_Gimmick_Box_Discard_Enable_Static) {
108    float3 p = getCenterCamPos();
109    float3 c1 = _Gimmick_Box_Discard_Corner_1;
110    float3 c2 = _Gimmick_Box_Discard_Corner_2;
111    bool inside = (p.x >= c1.x && p.x <= c2.x &&
112        p.y >= c1.y && p.y <= c2.y &&
113        p.z >= c1.z && p.z <= c2.z);
114    if (_Gimmick_Box_Discard_Invert && !inside ||
115        !_Gimmick_Box_Discard_Invert && inside) {
116      return (v2f) (0.0 / 0.0);
117    }
118  }
119#endif
120
121  o.centerCamPos = getCenterCamPos();
122
123#if defined(_GIMMICK_QUANTIZE_LOCATION)
124  if (_Gimmick_Quantize_Location_Enable_Dynamic) {
125    float q = _Gimmick_Quantize_Location_Precision /
126      _Gimmick_Quantize_Location_Multiplier;
127#if defined(_GIMMICK_QUANTIZE_LOCATION_AUDIOLINK)
128    // christ what a fucking variable name
129    if (_Gimmick_Quantize_Location_Audiolink_Enable_Dynamic &&
130        AudioLinkIsAvailable()) {
131      // x is lowest frequency, w is highest
132      float4 bands = AudioLinkData(ALPASS_AUDIOLINK).xyzw;
133
134      float e = q *= 1 + (bands.x + bands.y * 0.5) *
135        _Gimmick_Quantize_Location_Audiolink_Strength * 0.1;
136    }
137#endif
138    float3 v_new0 = floor(v.vertex * q) / q;
139    float3 d = v_new0 - v.vertex;
140    float3 v_new1 = v.vertex - d;
141    bool flip_dir = (sign(dot(d, v.normal)) !=
142        sign(_Gimmick_Quantize_Location_Direction));
143    float3 v_q = lerp(v_new0, v_new1, flip_dir);
144    float mask = _Gimmick_Quantize_Location_Mask.SampleLevel(linear_repeat_s,
145        v.uv0.xy, /*lod=*/0);
146    v.vertex.xyz = lerp(v.vertex.xyz, v_q, mask);
147  }
148#endif
149
150#if defined(_TROCHOID)
151  {
152    o.objPos_pre_trochoid = v.vertex.xyz;
153    v.vertex.xyz = cart_to_troch_map(v.vertex.xyz);
154  }
155#endif  // _TROCHOID
156#if defined(_GIMMICK_ZWRITE_ABOMINATION)
157  v.vertex.xyz *= _Gimmick_ZWrite_Abomination_Vertex_Expansion_Factor;
158#endif
159#if defined(_FACE_ME_WORLD_Y)
160  [branch]
161  if (_FaceMeWorldY_Enable_Dynamic) {
162    float3 object_center = mul(unity_ObjectToWorld, float4(0, 0, 0, 1));
163    // Get forward axis of object coordinate system, i.e. the orientation of
164    // the hip bone.
165    // Then project it onto the xz plane.
166    float3 forward_axis = mul(unity_ObjectToWorld, float3(0, 0, 1));
167    forward_axis.y = 0;
168    forward_axis = normalize(forward_axis);
169    float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
170    float3 rd = normalize((worldPos - object_center) - getCenterCamPos());
171    // We apply a factor of -1 to shift the result forward by a phase shift of pi.
172    float cos_t = -dot(normalize(rd.xz), forward_axis.xz);
173    // We want to get sin(t) using the identity:
174    //   || a x b || = || a || || b || sin(t)
175    // For normal vectors, this simplifies to:
176    //   || a x b || = sin(t)
177    // The issue is that the norm operator loses the sign.
178    // We can estimate the sign by assuming that `rd` and `forward_axis` are on
179    // the xz plane.
180    // If that's the case, then the cross product is necessarily constrained to
181    // the y axis.
182    float sin_t_sign = sign(cross(rd, forward_axis).y);
183    // Here we use the identity:
184    //   sin(t) = sqrt(1 - cos(t)^2)
185    // We simply apply the sign correction `sin_t_sign` to the result.
186    // We then invert it, since the goal is not to amplify the rotation, but
187    // to negate it.
188    // Finally, we add a phase correction to make the abomination face us.
189    float sin_t = -sqrt(1 - cos_t * cos_t) * sin_t_sign;
190    float2x2 face_me_rot = float2x2(cos_t, -sin_t, sin_t, cos_t);
191    float2x2 face_me_rot_inv = float2x2(cos_t, sin_t, -sin_t, cos_t);
192    worldPos.xz = mul(face_me_rot, (worldPos.xz - object_center.xz)) + object_center.xz;
193    v.vertex = mul(unity_WorldToObject, worldPos);
194    float3 world_normal = UnityObjectToWorldNormal(v.normal);
195    world_normal.xz = mul(face_me_rot_inv, world_normal.xz);
196    v.normal = normalize(mul(unity_WorldToObject, world_normal));
197  }
198#endif
199
200#if !defined(_SCROLL) && defined(_GIMMICK_SPHERIZE_LOCATION)
201  if (_Gimmick_Spherize_Location_Enable_Dynamic) {
202    float3 p = v.vertex.xyz;
203    float r = _Gimmick_Spherize_Location_Radius;
204    float s = _Gimmick_Spherize_Location_Strength;
205    float l = length(p);
206    p *= lerp(1, (r / l), s);
207    v.vertex.xyz = p;
208  }
209#endif
210#if !defined(_SCROLL) && defined(_GIMMICK_SHEAR_LOCATION)
211  if (_Gimmick_Shear_Location_Enable_Dynamic) {
212    float3 p = v.vertex.xyz;
213    float3 sc = _Gimmick_Shear_Location_Strength.xyz;
214    float3x3 shear_matrix = float3x3(
215          sc.x, 0, 0,
216          0, sc.y, 0,
217          0, 0, sc.z);
218    p = mul(shear_matrix, p);
219    v.vertex.xyz = p;
220  }
221#endif
222#if defined(_GIMMICK_GERSTNER_WATER)
223  {
224    GerstnerParams p = getGerstnerParams();
225    v.vertex.xyz = gerstner_vert(v.vertex.xyz, p);
226  }
227#endif
228
229  o.pos = UnityObjectToClipPos(v.vertex);
230  o.worldPos = mul(unity_ObjectToWorld, v.vertex);
231  o.objPos = v.vertex;
232  o.normal = UnityObjectToWorldNormal(v.normal);
233  o.tangent = float4(UnityObjectToWorldDir(v.tangent.xyz), v.tangent.w);
234  o.uv0 = v.uv0;
235#if !defined(_OPTIMIZE_INTERPOLATORS)
236  o.uv1 = v.uv1;
237#if defined(LIGHTMAP_ON)
238  o.uv2 = v.uv2 * unity_LightmapST.xy + unity_LightmapST.zw;
239  UNITY_TRANSFER_LIGHTING(o, v.uv2);
240#else
241  o.uv2 = v.uv2;
242  o.uv3 = v.uv3;
243  o.uv4 = v.uv4;
244  o.uv5 = v.uv5;
245  o.uv6 = v.uv6;
246  o.uv7 = v.uv7;
247#endif
248#endif  // _OPTIMIZE_INTERPOLATORS
249#if defined(_MIRROR_UV_FLIP)
250  if (_Mirror_UV_Flip_Enable_Dynamic) {
251    bool in_mirror = isInMirror();
252    o.uv0.x = lerp(o.uv0.x, 1 - o.uv0.x, in_mirror);
253#if !defined(_OPTIMIZE_INTERPOLATORS)
254    o.uv1.x = lerp(o.uv1.x, 1 - o.uv1.x, in_mirror);
255    o.uv2.x = lerp(o.uv2.x, 1 - o.uv2.x, in_mirror);
256    o.uv3.x = lerp(o.uv3.x, 1 - o.uv3.x, in_mirror);
257    o.uv4.x = lerp(o.uv4.x, 1 - o.uv4.x, in_mirror);
258    o.uv5.x = lerp(o.uv5.x, 1 - o.uv5.x, in_mirror);
259    o.uv6.x = lerp(o.uv6.x, 1 - o.uv6.x, in_mirror);
260    o.uv7.x = lerp(o.uv7.x, 1 - o.uv7.x, in_mirror);
261#endif
262  }
263#endif
264#if defined(SHADOWS_SCREEN)
265  TRANSFER_SHADOW(o);
266#endif
267
268	float2 suv = o.pos * float2(0.5, 0.5 * _ProjectionParams.x);
269  o.screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * o.pos.w, o.pos.w);
270  o.grabPos = ComputeGrabScreenPos(o.pos);
271
272  getVertexLightColor(o);
273  UNITY_TRANSFER_FOG(o, o.pos);
274
275  return o;
276}
277
278// maxvertexcount == the number of vertices we create
279#if defined(_CLONES)
280[maxvertexcount(21)]
281#else
282[maxvertexcount(3)]
283#endif
284void geom(triangle v2f tri_in[3],
285  uint pid: SV_PrimitiveID,
286  inout TriangleStream<v2f> tri_out)
287{
288  v2f v0 = tri_in[0];
289  v2f v1 = tri_in[1];
290  v2f v2 = tri_in[2];
291
292  float3 v0_objPos;
293  float3 v1_objPos;
294  float3 v2_objPos;
295
296  const float pid_rand = rand((int) pid);
297
298  float explode_phase = 0;
299#if defined(_EXPLODE)
300  float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos));
301  float3 avg_pos;
302
303  float3 n0 = v0.normal;
304  float3 n1 = v1.normal;
305  float3 n2 = v2.normal;
306
307  explode_phase = _Explode_Phase;
308  explode_phase = smoothstep(0, 1, explode_phase);
309  explode_phase *= explode_phase;
310  explode_phase *= 4;
311
312  if (explode_phase > 1E-6) {
313    float3 axis = normalize(float3(
314          rand((int) ((v0.uv0.x + v0.uv0.y) * 1E9)) * 2 - 1,
315          rand((int) ((v1.uv0.x + v1.uv0.y) * 1E9)) * 2 - 1,
316          rand((int) ((v2.uv0.x + v2.uv0.y) * 1E9)) * 2 - 1));
317    float3 np = BlendNormals(n, axis * explode_phase);
318
319    v0.worldPos += np * explode_phase * pid_rand;
320    v1.worldPos += np * explode_phase * pid_rand;
321    v2.worldPos += np * explode_phase * pid_rand;
322
323    v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1));
324    v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1));
325    v2_objPos = mul(unity_WorldToObject, float4(v2.worldPos, 1));
326
327    float chrono = 0;
328#if defined(_AUDIOLINK)
329    if (AudioLinkIsAvailable()) {
330      chrono = (AudioLinkDecodeDataAsUInt( ALPASS_CHRONOTENSITY  + uint2( 2, 1 ) ) % 1000000) / 1000000.0;
331    }
332#endif
333    v0.worldPos += n * explode_phase * sin(_Time[2] + length(v0_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2;
334    v1.worldPos += n * explode_phase * sin(_Time[2] + length(v1_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2;
335    v2.worldPos += n * explode_phase * sin(_Time[2] + length(v2_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2;
336
337    avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3;
338    v0.worldPos -= avg_pos;
339    v1.worldPos -= avg_pos;
340    v2.worldPos -= avg_pos;
341
342    v0.worldPos *= 1 + 2 * pid_rand;
343    v1.worldPos *= 1 + 2 * pid_rand;
344    v2.worldPos *= 1 + 2 * pid_rand;
345
346    float theta = explode_phase * 3.14159 * 4 + explode_phase * (sin(_Time[1] * (1 + pid_rand) / 2.0 + pid_rand) + cos(_Time[1] * (1 + pid_rand) / 6.1 + pid_rand) * 2) * pid_rand * 2;
347    float4 quat = get_quaternion(axis, theta);
348    v0.worldPos = rotate_vector(v0.worldPos, quat);
349    v1.worldPos = rotate_vector(v1.worldPos, quat);
350    v2.worldPos = rotate_vector(v2.worldPos, quat);
351
352    v0.worldPos += avg_pos;
353    v1.worldPos += avg_pos;
354    v2.worldPos += avg_pos;
355
356    n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos));
357    v0.normal = n;
358    v1.normal = n;
359    v2.normal = n;
360
361    // Omit geometry that's too close when exploded.
362    /*
363    if (_Explode_Phase > .05 && length(v0.worldPos - _WorldSpaceCameraPos) < .2) {
364      return;
365    }
366    */
367
368    v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1));
369    v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1));
370    v2_objPos = mul(unity_WorldToObject, float4(v2.worldPos, 1));
371
372    // Apply transformed worldPos to other coordinate systems.
373    if (_Explode_Phase > 1E-6) {
374      v0.pos = UnityObjectToClipPos(v0_objPos);
375      v1.pos = UnityObjectToClipPos(v1_objPos);
376      v2.pos = UnityObjectToClipPos(v2_objPos);
377    }
378  }
379#endif  // __EXPLODE
380#if defined(_SCROLL)
381  {
382    float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos));
383    float3 avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3;
384    v0.worldPos = applyScroll(v0.worldPos, n, avg_pos);
385    v1.worldPos = applyScroll(v1.worldPos, n, avg_pos);
386    v2.worldPos = applyScroll(v2.worldPos, n, avg_pos);
387
388    float3 v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1));
389    float3 v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1));
390    float3 v2_objPos = mul(unity_WorldToObject, float4(v2.worldPos, 1));
391
392#if defined(_GIMMICK_SPHERIZE_LOCATION)
393  if (_Gimmick_Spherize_Location_Enable_Dynamic) {
394    float r = _Gimmick_Spherize_Location_Radius;
395    float s = _Gimmick_Spherize_Location_Strength;
396    float l0 = length(v0_objPos);
397    float l1 = length(v1_objPos);
398    float l2 = length(v2_objPos);
399    v0_objPos *= lerp(1, (r / l0), s);
400    v1_objPos *= lerp(1, (r / l1), s);
401    v2_objPos *= lerp(1, (r / l2), s);
402  }
403#endif
404#if defined(_GIMMICK_SHEAR_LOCATION)
405  if (_Gimmick_Shear_Location_Enable_Dynamic) {
406    v0_objPos = mul(float3x3(
407        _Gimmick_Shear_Location_Strength.x, 0, 0,
408        0, _Gimmick_Shear_Location_Strength.y, 0,
409        0, 0, _Gimmick_Shear_Location_Strength.z),
410        v0_objPos);
411    v1_objPos = mul(float3x3(
412        _Gimmick_Shear_Location_Strength.x, 0, 0,
413        0, _Gimmick_Shear_Location_Strength.y, 0,
414        0, 0, _Gimmick_Shear_Location_Strength.z),
415        v1_objPos);
416    v2_objPos = mul(float3x3(
417        _Gimmick_Shear_Location_Strength.x, 0, 0,
418        0, _Gimmick_Shear_Location_Strength.y, 0,
419        0, 0, _Gimmick_Shear_Location_Strength.z),
420        v2_objPos);
421  }
422#endif
423#if defined(_GIMMICK_SHEAR_LOCATION) || defined(_GIMMICK_SPHERIZE_LOCATION)
424    v0.worldPos.xyz = mul(unity_ObjectToWorld, v0_objPos);
425    v1.worldPos.xyz = mul(unity_ObjectToWorld, v1_objPos);
426    v2.worldPos.xyz = mul(unity_ObjectToWorld, v2_objPos);
427#endif
428
429    v0.pos = UnityObjectToClipPos(v0_objPos);
430    v1.pos = UnityObjectToClipPos(v1_objPos);
431    v2.pos = UnityObjectToClipPos(v2_objPos);
432  }
433#endif
434#if defined(_CLONES)
435  v2f clone_verts[3] = {v0, v1, v2};
436  add_clones(clone_verts, tri_out, pid_rand, explode_phase);
437#endif  // _CLONES
438
439  // Output transformed geometry.
440  tri_out.Append(v0);
441  tri_out.Append(v1);
442  tri_out.Append(v2);
443  tri_out.RestartStrip();
444}
445
446#if defined(_LENS00)
447
448#endif
449
450
451#if defined(_RORSCHACH) || defined(_GLITTER) || defined(_RIM_LIGHTING0_GLITTER) || defined(_RIM_LIGHTING1_GLITTER) || defined(_RIM_LIGHTING2_GLITTER) || defined(_RIM_LIGHTING3_GLITTER)
452struct RorschachPBR {
453  float4 albedo;
454};
455float rorschach_map_sdf(float3 p, float2 e, float3 period, float center_randomization, float speed)
456{
457  float r = _Rorschach_Radius * min(period.x, min(period.y, period.z));
458  float st = sin(_Time[1] * speed * e.y * e.y + e.x * 3.14159265 * 2);
459  r *= st;
460  float3 o = float3(
461    (e.x - 0.5) * period.x,
462    (e.y - 0.5) * period.y,
463    0);
464  o *= center_randomization;
465  return distance_from_sphere(p + o, r);
466}
467
468float rorschach_map_dr(
469    float3 p,
470    float3 period,
471    float3 count,
472    float center_randomization,
473    float speed,
474    out float3 which
475    )
476{
477  which = round(p / period);
478  // Direction to nearest neighboring cell.
479  float3 min_d = p - period * which;
480  float3 o = sign(min_d);
481
482  float d = 1E9;
483  float3 which_tmp = which;
484  for (uint xi = 0; xi < 4; xi++)
485  for (uint yi = 0; yi < 4; yi++)
486  {
487    float3 rid = which + float3(((float) xi) - 1, ((float) yi) - 1, 0) * o;
488    float3 r = p - period * rid;
489    float2 e = float2(
490        rand3(rid / 100.0),
491        rand3(rid / 100.0 + 1));
492    float cur_d = rorschach_map_sdf(r, e, period, center_randomization, speed);
493    which_tmp = cur_d < d ? rid : which;
494    d = min(d, cur_d);
495  }
496
497  which = which_tmp;
498  return d;
499}
500
501struct RorschachParams {
502  float4 color;
503  float count_x, count_y;
504  float mask;
505  float mask_invert;
506  float quantization;
507  float alpha_cutoff;
508  float center_randomization;
509  float speed;
510};
511
512RorschachPBR get_rorschach(float2 uv, RorschachParams p)
513{
514  RorschachPBR result;
515  result.albedo = float4(0, 0, 0, 1);
516
517  float3 ro = float3(uv.x - 0.5, uv.y - 0.5, 0);
518  float3 rd = float3(0, 0, 1);
519
520  float3 which;
521  float3 period = float3(1 / (p.count_x+1), 1 / (p.count_y+1), 1);
522  float3 count = float3(p.count_x, p.count_y, 1);
523  float d = rorschach_map_dr(ro, period, count, p.center_randomization, p.speed, which);
524
525  d *= max(p.count_x + 1, p.count_y + 1);
526
527  d = 1 - d;
528  d = saturate(d);
529
530  // This also quantizes alpha. It isn't exactly intended, but it looks nice.
531  if (p.quantization > 0) {
532    d = round(d * p.quantization) / p.quantization;
533  }
534
535  float4 col = p.color * d;
536  result.albedo = lerp(0, col, d > p.alpha_cutoff);
537
538  float mask = p.mask;
539  mask = p.mask_invert ? 1 - mask : mask;
540  result.albedo *= mask;
541
542  return result;
543}
544
545float get_glitter(float2 uv, float3 worldPos, float3 centerCamPos,
546    float3 normal, float density, float amount, float speed,
547    float mask, float angle, float power)
548{
549  // To increase amount: make count_{x,y} closer to each other
550  // To increase density: make both numbers larger
551  RorschachParams p;
552  p.color = 1;
553  p.count_x = density * amount;
554  p.count_y = density * rcp(amount);
555  p.mask = mask;
556  p.mask_invert = 0;
557  p.quantization = 1;
558  p.alpha_cutoff = 0.5;
559  p.center_randomization = 1;
560  p.speed = speed;
561  RorschachPBR result = get_rorschach(uv, p);
562
563  float glitter = result.albedo.r;
564  if (angle < 90) {
565    float ndotl = abs(dot(normal, normalize(centerCamPos - worldPos)));
566    float cutoff = cos((angle / 180) * 3.14159);
567
568    glitter *= saturate(pow(ndotl / cutoff, power));
569  }
570  if (_Glitter_Vector_Mask_Enabled) {
571    float3 mask_vector = _Glitter_Vector_Mask_Vector;
572    float power = _Glitter_Vector_Mask_Power;
573    float invert = _Glitter_Vector_Mask_Invert;
574    float vector_mask = dot(normal, normalize(mask_vector));
575    // Wrap ndotl
576    vector_mask = (vector_mask + 1) / 2;
577    vector_mask *= vector_mask;
578    vector_mask = max(vector_mask, 0);
579    vector_mask = invert ? 1 - vector_mask : vector_mask;
580    glitter *= pow(vector_mask, power);
581  }
582
583  return glitter;
584
585  /*
586  // A regular divide here causes flickering. The leading guess is that NVIDIA
587  // hardware implements the divide instruction slightly differently on
588  // different cores.
589  precise float idensity = rcp(density);
590  float glitter = rand2(floor(uv * density) * idensity);
591
592  float thresh = 1 - amount / 100;
593  glitter = lerp(0, glitter, glitter > thresh);
594  glitter = (glitter - thresh) / (1 - thresh);
595
596  float b = sin(_Time[2] * speed / 2 + glitter*100);
597  b = speed > 1E-6 ? b : 1;
598  glitter = max(glitter, 0)*max(b, 0);
599
600  glitter *= mask;
601
602  glitter = clamp(glitter, 0, 1);
603
604  if (angle < 90) {
605    float ndotl = abs(dot(normal, normalize(_WorldSpaceCameraPos.xyz - worldPos)));
606    float cutoff = cos((angle / 180) * 3.14159);
607
608    glitter *= saturate(pow(ndotl / cutoff, power));
609  }
610
611  return glitter;
612  */
613}
614#endif  // _GLITTER
615
616float3 CreateBinormal(float3 normal, float3 tangent, float binormalSign) {
617	return cross(normal, tangent) * (binormalSign * unity_WorldTransformParams.w);
618}
619
620float2 matcap_distortion0(float2 matcap_uv) {
621  float3 qvec = float3(matcap_uv * 2 - 1, 0);
622  float t = _Time[0];
623  float e = .4;
624  float3 qaxis = normalize(float3(sin(t * 2.3) * e, sin(t * 2.9) * e * 1.2, 1));
625  float qtheta = t;
626  float4 quat = get_quaternion(qaxis, qtheta);
627  matcap_uv *= ((rotate_vector(qvec, quat) + 1) / 2).xy * 1.3;
628  return matcap_uv;
629}
630
631struct DecalParams {
632    float4 color;
633    texture2D tex;
634    float4 tex_texelsize;
635    float4 tex_st;
636    texture2D roughness_tex;
637    texture2D metallic_tex;
638    float emission_strength;
639    float angle;
640    bool do_roughness;
641    bool do_metallic;
642    float alpha_multiplier;
643    float round_alpha_multiplier;
644    float mask;
645    float uv_select;
646    float tiling_mode;
647    float base_color_mode;
648    float sdf_threshold;
649    float sdf_invert;
650    float sdf_softness;
651    float sdf_px_range;
652    bool domain_warping;
653    texture2D domain_warping_noise;
654    float domain_warping_strength;
655    float domain_warping_speed;
656    float domain_warping_octaves;
657    float domain_warping_scale;
658};
659
660void applyDecalImpl(
661    inout float4 albedo,
662    inout float3 decal_emission,
663    inout float roughness,
664    inout float metallic,
665    v2f i,
666    DecalParams p)
667{
668  float2 d0_uv =
669      ((get_uv_by_channel(i, p.uv_select) - 0.5) - p.tex_st.zw) * p.tex_st.xy + 0.5;
670
671  [branch]
672  if (abs(p.angle) > 1E-6) {
673    float theta = p.angle * 2.0 * 3.14159265;
674    float2x2 rot = float2x2(
675        cos(theta), -sin(theta),
676        sin(theta), cos(theta));
677    d0_uv = mul(rot, d0_uv - 0.5) + 0.5;
678  }
679  d0_uv = (p.tiling_mode == 0) ? saturate(d0_uv) : d0_uv;
680
681  float d0_uv_fwidth = -1;
682  [branch]
683  if (p.domain_warping) {
684    p.domain_warping_octaves = min(p.domain_warping_octaves, 10);
685    for (uint ii = 0; ii < p.domain_warping_octaves; ii++) {
686      float2 warping_speed_vector = normalize(float2(97, 101));
687      float2 noise = p.domain_warping_noise.SampleLevel(linear_repeat_s, d0_uv * p.domain_warping_scale + _Time[0] * p.domain_warping_speed * warping_speed_vector, 0);
688      d0_uv += noise * p.domain_warping_strength;
689    }
690    d0_uv_fwidth = length(fwidth(d0_uv));
691  }
692
693  float4 d0_c = 0;
694  [branch]
695  if (p.base_color_mode == 0) {
696    d0_c = p.tex.SampleBias(
697        linear_repeat_s,
698        d0_uv, _Global_Sample_Bias);
699  } else if (p.base_color_mode == 1) {
700    float sd = p.tex.SampleLevel(linear_repeat_s, d0_uv, 0);
701    sd = p.sdf_invert ? 1 - sd : sd;
702
703    float2 screen_tex_size = 1 / fwidth(d0_uv);
704    float2 cell_size_texels = p.tex_texelsize.zw;
705    float2 unit_range = p.sdf_px_range / cell_size_texels;
706    float screen_px_range = max(0.5 * dot(unit_range, screen_tex_size), p.sdf_px_range);
707
708    float screen_px_distance = screen_px_range * (sd - p.sdf_threshold);
709    float2 grid_res = p.tex_st.xy;
710    float smooth_range = (sqrt(2) / sqrt(screen_px_range)) * p.sdf_softness;
711    float op = smoothstep(-smooth_range, smooth_range, screen_px_distance);
712    d0_c = saturate(op);
713    // TODO mip-like filtering?
714  }
715
716  d0_c *= p.color;
717  d0_c.a *= p.round_alpha_multiplier ? round(p.alpha_multiplier) : p.alpha_multiplier;
718  // Manually apply tiling/clamping correction.
719  float d0_in_range = 1;
720  d0_in_range *= d0_uv.x > 0;
721  d0_in_range *= d0_uv.x < 1;
722  d0_in_range *= d0_uv.y > 0;
723  d0_in_range *= d0_uv.y < 1;
724  d0_in_range = (p.tiling_mode == 0) ? d0_in_range : 1;
725  d0_c *= d0_in_range;
726  d0_c *= p.mask;
727
728  albedo.rgb = lerp(albedo.rgb, d0_c.rgb, d0_c.a);
729  albedo.a = max(albedo.a, d0_c.a);
730  decal_emission = d0_c.rgb * p.emission_strength * d0_c.a + decal_emission * (1 - d0_c.a);
731
732  if (p.do_roughness) {
733    float4 d0_r = p.roughness_tex.SampleBias(linear_clamp_s, saturate(d0_uv), _Global_Sample_Bias);
734    d0_r *= d0_in_range;
735    roughness = lerp(roughness, d0_r, d0_r.a);
736  }
737  if (p.do_metallic) {
738    float4 d0_m = p.metallic_tex.SampleBias(linear_clamp_s, saturate(d0_uv), _Global_Sample_Bias);
739    d0_m *= d0_in_range;
740    metallic = lerp(metallic, d0_m, d0_m.a);
741  }
742}
743
744#define DECAL_PARAMS(n) \
745  MERGE(d,n,_params).do_roughness = false; \
746  MERGE(d,n,_params).do_metallic = false; \
747  MERGE(d,n,_params).mask = 1; \
748  MERGE(d,n,_params).color = MERGE(_Decal,n,_Color); \
749  MERGE(d,n,_params).tex = MERGE(_Decal,n,_BaseColor); \
750  MERGE(d,n,_params).tex_texelsize = MERGE(_Decal,n,_BaseColor_TexelSize); \
751  MERGE(d,n,_params).tex_st = MERGE(_Decal,n,_BaseColor_ST); \
752  MERGE(d,n,_params).roughness_tex = MERGE(_Decal,n,_Roughness); \
753  MERGE(d,n,_params).metallic_tex = MERGE(_Decal,n,_Metallic); \
754  MERGE(d,n,_params).emission_strength = MERGE(_Decal,n,_Emission_Strength); \
755  MERGE(d,n,_params).angle = MERGE(_Decal,n,_Angle); \
756  MERGE(d,n,_params).alpha_multiplier = MERGE(_Decal,n,_Alpha_Multiplier); \
757  MERGE(d,n,_params).round_alpha_multiplier = MERGE(_Decal,n,_Round_Alpha_Multiplier); \
758  MERGE(d,n,_params).uv_select = MERGE(_Decal,n,_UV_Select); \
759  MERGE(d,n,_params).tiling_mode = MERGE(_Decal,n,_Tiling_Mode); \
760  MERGE(d,n,_params).base_color_mode = MERGE(_Decal,n,_BaseColor_Mode); \
761  MERGE(d,n,_params).sdf_threshold = MERGE(_Decal,n,_SDF_Threshold); \
762  MERGE(d,n,_params).sdf_invert = MERGE(_Decal,n,_SDF_Invert); \
763  MERGE(d,n,_params).sdf_softness = MERGE(_Decal,n,_SDF_Softness); \
764  MERGE(d,n,_params).sdf_px_range = MERGE(_Decal,n,_SDF_Px_Range); \
765  MERGE(d,n,_params).domain_warping = MERGE(_Decal,n,_Domain_Warping_Enable_Static); \
766  MERGE(d,n,_params).domain_warping_noise = MERGE(_Decal,n,_Domain_Warping_Noise); \
767  MERGE(d,n,_params).domain_warping_strength = MERGE(_Decal,n,_Domain_Warping_Strength); \
768  MERGE(d,n,_params).domain_warping_speed = MERGE(_Decal,n,_Domain_Warping_Speed); \
769  MERGE(d,n,_params).domain_warping_octaves = MERGE(_Decal,n,_Domain_Warping_Octaves); \
770  MERGE(d,n,_params).domain_warping_scale = MERGE(_Decal,n,_Domain_Warping_Scale);
771
772#define SETUP_DECAL_BASE(n) \
773  DecalParams MERGE(d,n,_params); \
774  DECAL_PARAMS(n)
775
776#define SETUP_DECAL_ROUGHNESS(n) \
777  MERGE(d,n,_params).do_roughness = true;
778
779#define SETUP_DECAL_METALLIC(n) \
780  MERGE(d,n,_params).do_metallic = true;
781
782#define SETUP_DECAL_MASK(n) \
783  MERGE(d,n,_params).mask = MERGE(_Decal,n,_Mask).SampleLevel(linear_repeat_s, \
784      get_uv_by_channel(i, MERGE(_Decal,n,_UV_Select)), 0); \
785  MERGE(d,n,_params).mask = MERGE(_Decal,n,_Mask_Invert) ? 1.0 - MERGE(d,n,_params).mask : MERGE(d,n,_params).mask;
786
787#define SETUP_DECAL_FINISH(n) \
788  applyDecalImpl(albedo, decal_emission, roughness, metallic, i, MERGE(d,n,_params));
789
790void applyDecal(inout float4 albedo,
791    inout float roughness,
792    inout float metallic,
793    inout float3 decal_emission,
794    v2f i)
795{
796#if defined(_DECAL0)
797    SETUP_DECAL_BASE(0)
798    #if defined(_DECAL0_ROUGHNESS)
799        SETUP_DECAL_ROUGHNESS(0)
800    #endif
801    #if defined(_DECAL0_METALLIC)
802        SETUP_DECAL_METALLIC(0)
803    #endif
804    #if defined(_DECAL0_MASK)
805        SETUP_DECAL_MASK(0)
806    #endif
807    SETUP_DECAL_FINISH(0)
808#endif
809
810#if defined(_DECAL1)
811    SETUP_DECAL_BASE(1)
812    #if defined(_DECAL1_ROUGHNESS)
813        SETUP_DECAL_ROUGHNESS(1)
814    #endif
815    #if defined(_DECAL1_METALLIC)
816        SETUP_DECAL_METALLIC(1)
817    #endif
818    #if defined(_DECAL1_MASK)
819        SETUP_DECAL_MASK(1)
820    #endif
821    SETUP_DECAL_FINISH(1)
822#endif
823
824#if defined(_DECAL2)
825    SETUP_DECAL_BASE(2)
826    #if defined(_DECAL2_ROUGHNESS)
827        SETUP_DECAL_ROUGHNESS(2)
828    #endif
829    #if defined(_DECAL2_METALLIC)
830        SETUP_DECAL_METALLIC(2)
831    #endif
832    #if defined(_DECAL2_MASK)
833        SETUP_DECAL_MASK(2)
834    #endif
835    SETUP_DECAL_FINISH(2)
836#endif
837
838#if defined(_DECAL3)
839    SETUP_DECAL_BASE(3)
840    #if defined(_DECAL3_ROUGHNESS)
841        SETUP_DECAL_ROUGHNESS(3)
842    #endif
843    #if defined(_DECAL3_METALLIC)
844        SETUP_DECAL_METALLIC(3)
845    #endif
846    #if defined(_DECAL3_MASK)
847        SETUP_DECAL_MASK(3)
848    #endif
849    SETUP_DECAL_FINISH(3)
850#endif
851
852#if defined(_DECAL4)
853    SETUP_DECAL_BASE(4)
854    #if defined(_DECAL4_ROUGHNESS)
855        SETUP_DECAL_ROUGHNESS(4)
856    #endif
857    #if defined(_DECAL4_METALLIC)
858        SETUP_DECAL_METALLIC(4)
859    #endif
860    #if defined(_DECAL4_MASK)
861        SETUP_DECAL_MASK(4)
862    #endif
863    SETUP_DECAL_FINISH(4)
864#endif
865
866#if defined(_DECAL5)
867    SETUP_DECAL_BASE(5)
868    #if defined(_DECAL5_ROUGHNESS)
869        SETUP_DECAL_ROUGHNESS(5)
870    #endif
871    #if defined(_DECAL5_METALLIC)
872        SETUP_DECAL_METALLIC(5)
873    #endif
874    #if defined(_DECAL5_MASK)
875        SETUP_DECAL_MASK(5)
876    #endif
877    SETUP_DECAL_FINISH(5)
878#endif
879
880#if defined(_DECAL6)
881    SETUP_DECAL_BASE(6)
882    #if defined(_DECAL6_ROUGHNESS)
883        SETUP_DECAL_ROUGHNESS(6)
884    #endif
885    #if defined(_DECAL6_METALLIC)
886        SETUP_DECAL_METALLIC(6)
887    #endif
888    #if defined(_DECAL6_MASK)
889        SETUP_DECAL_MASK(6)
890    #endif
891    SETUP_DECAL_FINISH(6)
892#endif
893
894#if defined(_DECAL7)
895    SETUP_DECAL_BASE(7)
896    #if defined(_DECAL7_ROUGHNESS)
897        SETUP_DECAL_ROUGHNESS(7)
898    #endif
899    #if defined(_DECAL7_METALLIC)
900        SETUP_DECAL_METALLIC(7)
901    #endif
902    #if defined(_DECAL7_MASK)
903        SETUP_DECAL_MASK(7)
904    #endif
905    SETUP_DECAL_FINISH(7)
906#endif
907
908#if defined(_DECAL8)
909    SETUP_DECAL_BASE(8)
910    #if defined(_DECAL8_ROUGHNESS)
911        SETUP_DECAL_ROUGHNESS(8)
912    #endif
913    #if defined(_DECAL8_METALLIC)
914        SETUP_DECAL_METALLIC(8)
915    #endif
916    #if defined(_DECAL8_MASK)
917        SETUP_DECAL_MASK(8)
918    #endif
919    SETUP_DECAL_FINISH(8)
920#endif
921
922#if defined(_DECAL9)
923    SETUP_DECAL_BASE(9)
924    #if defined(_DECAL9_ROUGHNESS)
925        SETUP_DECAL_ROUGHNESS(9)
926    #endif
927    #if defined(_DECAL9_METALLIC)
928        SETUP_DECAL_METALLIC(9)
929    #endif
930    #if defined(_DECAL9_MASK)
931        SETUP_DECAL_MASK(9)
932    #endif
933    SETUP_DECAL_FINISH(9)
934#endif
935}
936
937#if defined(_PIXELLATE)
938float2 pixellate_uv(int2 px_res, float2 uv)
939{
940  return floor(uv * px_res) / px_res;
941}
942
943float4 pixellate_color(int2 px_res, float2 uv, float4 c)
944{
945  float2 px_intra_uv = fmod(uv * px_res, 1.0);
946  float2 px_extra_uv = floor(uv * px_res) / px_res;
947
948  float2 px_uv = floor(uv * px_res) / px_res;
949  if (px_intra_uv.y > 0.1 && px_intra_uv.y < 0.9) {
950    if (px_intra_uv.x < 0.333) {
951      c.xyz = float3(1, 0, 0);
952    } else if (px_intra_uv.x < 0.666) {
953      c.yxz = float3(1, 0, 0);
954    } else {
955      c.zxy = float3(1, 0, 0);
956    }
957    c *= 3;
958  } else {
959    c = 0;
960  }
961
962  return c;
963}
964#endif
965
966#if defined(_GIMMICK_EPILEPSY_MODE)
967float4 map_color_epilepsy(float4 color) {
968  [branch]
969  if (_Gimmick_Epilepsy_Mode_Enable_Dynamic) {
970    color.rgb = saturate(color.rgb);
971
972    color.rgb = LRGBtoOKLCH(color.rgb);
973    color.rgb[0] = dmin(color.rgb[0], _Gimmick_Epilepsy_Mode_Luminance_Cutoff, _Gimmick_Epilepsy_Mode_Rolloff_Power);
974    color.rgb = OKLCHtoLRGB(color.rgb);
975
976    color.rgb = RGBtoHSV(color.rgb);
977    color.rgb[1] = dmin(color.rgb[1], _Gimmick_Epilepsy_Mode_Saturation_Cutoff, _Gimmick_Epilepsy_Mode_Rolloff_Power);
978    color.rgb = HSVtoRGB(color.rgb);
979  }
980
981  return color;
982}
983#define FILTER_COLOR(color) map_color_epilepsy(color)
984#else
985#define FILTER_COLOR(color) color
986#endif
987
988float ssfd(float2 uv, float scale, float max_fwidth, float2 uv_offset, texture3D noise)
989{
990  //float uv_fw = fwidth(uv.x) + fwidth(uv.y);
991  // Original paper uses SVD instead of fwidth.
992  float2x2 M = float2x2(ddx(uv), ddy(uv));
993  float2x2 MtM = mul(transpose(M), M);
994  float trace = MtM[0][0] + MtM[1][1];
995  float det = determinant(MtM);
996  // Calculate eigenvalues using quadratic formula.
997  float tmp = sqrt(trace * trace - 4 * det);
998  float e1 = (trace + tmp) * 0.5;
999  float e2 = (trace - tmp) * 0.5;
1000  float2 singular_values = sqrt(float2(e1, e2));
1001  // Logic from original paper: the smaller eigenvalue corresponds to the
1002  // largest amount of stretching, so we use it to determine when to
1003  // subdivide.
1004  float uv_fw = singular_values.y;
1005  uv_fw *= scale;
1006
1007  uint width, height, depth;
1008  noise.GetDimensions(width, height, depth);
1009  float bayer_res = sqrt(depth);
1010
1011  // Suppose max_fwidth is 1.
1012  // uv_fw is 16. That means UV is changing a lot per pixel. That means we want to shrink the scale of the UV.
1013  // Factor is 16.
1014  // log_2(factor) is 4.
1015  // Divide original by 16.
1016  float fw_factor = uv_fw / max_fwidth;
1017  // log_b(x) = log_a(x) / log_a(b)
1018  float fractal_level = log2(fw_factor) / log2(bayer_res);
1019  float fractal_level_floor = floor(fractal_level);
1020  float fractal_remainder = fractal_level - fractal_level_floor;
1021
1022  uv *= pow(bayer_res, -fractal_level_floor);
1023  uv += uv_offset * pow(bayer_res, -fractal_level_floor);
1024
1025  float n_layers = depth;
1026  float not_used_lo = 1/(n_layers*2);
1027  float not_used_hi = 1 - not_used_lo;
1028
1029  float uvw = (not_used_hi - not_used_lo) * (1 - fractal_remainder) + not_used_lo;
1030
1031  float3 uv_3d = float3(uv, uvw);
1032
1033  float dither = noise.SampleLevel(bilinear_repeat_s, uv_3d, 0);
1034
1035  return dither;
1036}
1037
1038float4 effect(inout v2f i, out float depth)
1039{
1040  ToonerData tdata;
1041  {
1042    float3 full_vec_eye_to_geometry = i.worldPos - _WorldSpaceCameraPos;
1043    float3 world_dir = normalize(i.worldPos - _WorldSpaceCameraPos);
1044    float perspective_divide = 1.0 / i.pos.w;
1045    float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
1046    tdata.screen_uv = i.screenPos.xy * perspective_divide;
1047    tdata.screen_uv_round = floor(tdata.screen_uv * _ScreenParams.xy);
1048  }
1049
1050#if defined(EXPERIMENT__CUSTOM_DEPTH)
1051  {
1052    float4 clip_pos = mul(UNITY_MATRIX_VP, float4(i.worldPos, 1.0));
1053    depth = clip_pos.z / clip_pos.w;
1054  }
1055#else
1056  depth = 0;
1057#endif
1058
1059#if defined(_GIMMICK_UV_DOMAIN_WARPING)
1060  {
1061    float2 uv = i.uv0;
1062    for (uint ii = 0; ii < _Gimmick_UV_Domain_Warping_Octaves; ii++) {
1063      uv +=
1064        (_Gimmick_UV_Domain_Warping_Noise.SampleLevel(
1065          linear_repeat_s,
1066          (uv + _Time[0] * _Gimmick_UV_Domain_Warping_Speed) *
1067          _Gimmick_UV_Domain_Warping_Scale, 0) - 0.5) *
1068        _Gimmick_UV_Domain_Warping_Strength;
1069    }
1070    i.uv0 = uv;
1071  }
1072#endif
1073
1074#if defined(_TROCHOID)
1075  {
1076    float3 my_pos;
1077    [branch]
1078    if (_Trochoid_Enable_Fragment_Normals) {
1079      my_pos = cart_to_troch_map(i.objPos_pre_trochoid.xyz);
1080    } else {
1081      my_pos = i.objPos.xyz;
1082    }
1083    float3 tan1 = ddx(my_pos);
1084    float3 tan2 = ddy(my_pos);
1085    float3 normal = cross(tan1, tan2);
1086    i.normal = -UnityObjectToWorldNormal(normal);
1087    i.tangent.xyz = UnityObjectToWorldDir(tan1);
1088  }
1089#endif
1090
1091  const float3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
1092  const float3 view_dir_c = normalize(i.centerCamPos - i.worldPos);
1093#define VIEW_DIR(center_eye_fix) (center_eye_fix == 1 ? view_dir_c : view_dir)
1094#define CAM_POS(center_eye_fix) (center_eye_fix == 1 ? i.centerCamPos : _WorldSpaceCameraPos.xyz)
1095
1096  // Not necessarily normalized after interpolation.
1097  i.normal = normalize(i.normal);
1098  i.tangent.xyz = normalize(i.tangent.xyz - i.normal * dot(i.tangent.xyz, i.normal));
1099  //i.tangent.xyz = normalize(i.tangent.xyz);
1100
1101#if defined(_UVSCROLL)
1102  float2 orig_uv = i.uv0;
1103  float uv_scroll_mask = round(_UVScroll_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias));
1104  i.uv0 += _Time[0] * float2(_UVScroll_U_Speed, _UVScroll_V_Speed) * uv_scroll_mask;
1105#endif
1106
1107#if defined(_BASECOLOR_MAP)
1108  float4 albedo = _MainTex.SampleBias(GET_SAMPLER_PBR, UV_SCOFF(i, _MainTex_ST, 0), _Global_Sample_Bias);
1109  albedo *= _Color;
1110#else
1111  float4 albedo = _Color;
1112#endif  // _BASECOLOR_MAP
1113
1114#if defined(_FRAME_COUNTER)
1115  const float frame = floor(_Frame_Counter);
1116#elif defined(TOONER_AUDIOLINK_AVAILABLE)
1117  const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x);
1118#else
1119  const float frame = 0;
1120#endif  // _FRAME_COUNTER
1121
1122#if defined(_GIMMICK_GERSTNER_WATER)
1123#if defined(_EXPLODE)
1124
1125  if (_Explode_Phase < 1E-6)
1126#endif
1127  {
1128    GerstnerParams p = getGerstnerParams();
1129    GerstnerFragResult r = gerstner_frag(i.objPos.xyz, p);
1130    i.normal = UnityObjectToWorldNormal(r.normal);
1131    i.tangent = float4(UnityObjectToWorldDir(r.tangent.xyz), r.tangent.w);
1132#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
1133    albedo.xyz *= r.color;
1134    albedo.w = 1;
1135#endif
1136  }
1137#endif
1138
1139#if defined(_UVSCROLL)
1140  if (uv_scroll_mask) {
1141    float uv_scroll_alpha = _UVScroll_Alpha.SampleBias(linear_repeat_s, orig_uv, _Global_Sample_Bias);
1142    albedo.a *= uv_scroll_alpha;
1143  }
1144#endif
1145
1146#if defined(_PIXELLATE)
1147  {
1148    const int2 px_res = int2(
1149        _Gimmick_Pixellate_Resolution_U,
1150        _Gimmick_Pixellate_Resolution_V);
1151
1152    float2 uv = pixellate_uv(px_res, i.uv0);
1153    const float2 duv = float2(ddx(i.uv0.x), ddy(i.uv0.y)) / 16;
1154    float4 color = _Gimmick_Pixellate_Effect_Mask.SampleGrad(linear_clamp_s, uv, duv.x, duv.y);
1155    float2 fw = float2(fwidth(i.uv0.x), fwidth(i.uv0.y));
1156    float fwm = max(fw.x, fw.y);
1157    color.rgb *= albedo;
1158    float4 px_color = pixellate_color(px_res, i.uv0, color);
1159    albedo = lerp(albedo, px_color, pow(0.9, fwm * 100));
1160  }
1161#endif
1162
1163#if defined(_RORSCHACH)
1164  float4 rorschach_albedo = 0;
1165  if (_Rorschach_Enable_Dynamic) {
1166    RorschachParams p;
1167    p.color = _Rorschach_Color;
1168    p.count_x = _Rorschach_Count_X;
1169    p.count_y = _Rorschach_Count_Y;
1170#if defined(_RORSCHACH_MASK)
1171    p.mask = _Rorschach_Mask.SampleLevel(linear_repeat_s, i.uv0.xy, /*lod=*/0);
1172    p.mask_invert = _Rorschach_Mask_Invert;
1173#else
1174    p.mask = 1;
1175    p.mask_invert = 0;
1176#endif
1177    p.quantization = _Rorschach_Quantization;
1178    p.alpha_cutoff = _Rorschach_Alpha_Cutoff;
1179    p.center_randomization = _Rorschach_Center_Randomization;
1180    p.speed = _Rorschach_Speed;
1181    rorschach_albedo = get_rorschach(i.uv0, p).albedo;
1182    albedo.rgb = rorschach_albedo.rgb * rorschach_albedo.a + albedo.rgb * (1 - rorschach_albedo.a);
1183    albedo.a = saturate(rorschach_albedo.a + albedo.a * (1 - rorschach_albedo.a));
1184  }
1185#endif
1186
1187  PbrOverlay ov;
1188  getOverlayAlbedoRoughnessMetallic(ov, i);
1189
1190#if defined(_NORMAL_MAP)
1191  // Use UVs to smoothly blend between fully detailed normals when close up and
1192  // flat normals when far away. If we don't do this, then we see moire effects
1193  // on e.g. striped normal maps.
1194  float3 raw_normal = UnpackScaleNormal(_BumpMap.SampleBias(GET_SAMPLER_PBR,
1195        UV_SCOFF(i, _BumpMap_ST, 0), _Global_Sample_Bias),
1196      _Tex_NormalStr);
1197#else
1198  float3 raw_normal = UnpackNormal(float4(0.5, 0.5, 1, 1));
1199#endif  // _NORMAL_MAP
1200
1201  applyOverlayNormal(raw_normal, albedo, ov, i);
1202
1203  float3 binormal = CreateBinormal(i.normal, i.tangent.xyz, i.tangent.w);
1204  // normalize is not necessary; result is already normalized
1205	float3 normal = float3(
1206		raw_normal.x * normalize(i.tangent) +
1207		raw_normal.y * normalize(binormal) +
1208		raw_normal.z * i.normal
1209	);
1210
1211#if defined(_GIMMICK_HALO_00)
1212  {
1213    Halo00PBR pbr = halo00_march(i.worldPos, i.uv0);
1214    albedo = pbr.albedo;
1215    normal = pbr.normal;
1216  }
1217#endif
1218
1219#if defined(_METALLIC_MAP)
1220  float metallic = _MetallicTex.SampleBias(GET_SAMPLER_PBR,
1221      UV_SCOFF(i, _MetallicTex_ST, 0), _Global_Sample_Bias)[round(_MetallicTexChannel)];
1222#else
1223  float metallic = _Metallic;
1224#endif
1225#if defined(_ROUGHNESS_MAP)
1226  float roughness = _RoughnessTex.SampleBias(GET_SAMPLER_PBR,
1227      UV_SCOFF(i, _RoughnessTex_ST, 0), _Global_Sample_Bias)[round(_RoughnessTexChannel)];
1228  if (_Roughness_Invert) {
1229    roughness = 1 - roughness;
1230  }
1231  roughness *= _Roughness;
1232#else
1233  float roughness = _Roughness;
1234#endif
1235
1236#if defined(_GIMMICK_ZWRITE_ABOMINATION) && defined(FORWARD_BASE_PASS)
1237  {
1238    ZWriteAbominationPBR pbr = zwrite_abomination(i);
1239    i.worldPos = pbr.worldPos;
1240    albedo = pbr.albedo;
1241    metallic = pbr.metallic;
1242    roughness = pbr.roughness;
1243    normal = pbr.normal;
1244    depth = pbr.depth;
1245#if 0
1246    float3 c = 1;
1247    c *= saturate(dot(normal, float3(0, -1, 1)));
1248    return float4(c, albedo.a);
1249#endif
1250  }
1251#endif
1252
1253#if defined(VERTEXLIGHT_ON)
1254  float4 vertex_light_color = float4(i.vertexLightColor, 1);
1255#else
1256  float4 vertex_light_color = float4(0, 0, 0, 1);
1257#endif
1258
1259#if defined(_GIMMICK_EYES_00)
1260  {
1261    float3 eyes_normal = 0;
1262    float3 eyes_albedo = eyes00_march(i.uv0, eyes_normal).rgb;
1263    bool is_ray_hit = (eyes_albedo.r > 0 || eyes_albedo.g > 0 || eyes_albedo.b > 0);
1264    if (is_ray_hit) {
1265      float mask = _Gimmick_Eyes00_Effect_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
1266      albedo.rgb = lerp(eyes_albedo * 1.5, albedo.rgb * 20.0, mask);
1267      normal = eyes_normal;
1268    }
1269  }
1270#endif
1271
1272#if defined(_GIMMICK_EYES_01)
1273  {
1274    Eyes01PBR pbr = eyes01_march(i);
1275    albedo = pbr.albedo;
1276  }
1277#endif
1278
1279
1280#if defined(_GIMMICK_EYES_02)
1281  float3 eyes02_normal = i.normal;
1282  bool eyes02_hit = eyes02_march(i.uv0, eyes02_normal);
1283  {
1284    albedo.rgb += eyes02_hit * _Gimmick_Eyes02_Albedo.rgb;
1285    normal = lerp(normal, eyes02_normal, eyes02_hit);
1286    roughness = lerp(roughness, _Gimmick_Eyes02_Roughness, eyes02_hit);
1287    metallic = lerp(metallic, _Gimmick_Eyes02_Metallic, eyes02_hit);
1288  }
1289#endif
1290
1291#if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1) || defined(_RIM_LIGHTING2) || defined(_RIM_LIGHTING3)
1292  float3 matcap_emission = 0;
1293  float2 matcap_uv;
1294  {
1295    const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1296    const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(view_dir, 0)));
1297    const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1298    float m = 2.0 * sqrt(
1299        cam_refl.x * cam_refl.x +
1300        cam_refl.y * cam_refl.y +
1301        (cam_refl.z + 1) * (cam_refl.z + 1));
1302    matcap_uv = cam_refl.xy / m + 0.5;
1303  }
1304  float2 matcap_uv_center;
1305  {
1306    const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1307    const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(view_dir_c, 0)));
1308    const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1309    float m = 2.0 * sqrt(
1310        cam_refl.x * cam_refl.x +
1311        cam_refl.y * cam_refl.y +
1312        (cam_refl.z + 1) * (cam_refl.z + 1));
1313    matcap_uv_center = cam_refl.xy / m + 0.5;
1314  }
1315#endif
1316
1317  float4 matcap_overwrite_mask = 0;
1318#if defined(_MATCAP0) || defined(_MATCAP1)
1319  {
1320#if defined(_MATCAP0)
1321    {
1322#if defined(_MATCAP0_MASK)
1323      float4 matcap_mask_raw = _Matcap0_Mask.SampleLevel(linear_repeat_s,
1324          get_uv_by_channel(i, _Matcap0_Mask_UV_Select), 0);
1325      float matcap_mask = matcap_mask_raw.r;
1326      matcap_mask = (bool) round(_Matcap0_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1327      matcap_mask *= matcap_mask_raw.a;
1328#else
1329      float matcap_mask = 1;
1330#endif
1331#if defined(_MATCAP0_MASK2)
1332      {
1333        float4 matcap_mask2_raw = _Matcap0_Mask2.SampleLevel(linear_repeat_s,
1334            get_uv_by_channel(i, _Matcap0_Mask2_UV_Select), 0);
1335        float matcap_mask2 = matcap_mask2_raw.r;
1336        matcap_mask2 = _Matcap0_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1337        matcap_mask2 *= _Matcap0_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1338        matcap_mask *= matcap_mask2;
1339      }
1340#endif
1341#if defined(_MATCAP0_NORMAL)
1342      float3 matcap_normal = UnpackScaleNormal(
1343          _Matcap0Normal.SampleBias(linear_repeat_s,
1344            UV_SCOFF(i, _Matcap0Normal_ST, _Matcap0Normal_UV_Select),
1345            _Global_Sample_Bias + _Matcap0Normal_Mip_Bias),
1346          _Matcap0Normal_Str * _Matcap0MixFactor);
1347      raw_normal = MY_BLEND_NORMALS(raw_normal, matcap_normal, matcap_mask * _Matcap0MixFactor);
1348      normal = float3(
1349          raw_normal.x * i.tangent +
1350          raw_normal.y * binormal +
1351          raw_normal.z * i.normal
1352          );
1353      {
1354        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1355        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(VIEW_DIR(_Matcap0_Center_Eye_Fix), 0)));
1356        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1357        float m = 2.0 * sqrt(
1358            cam_refl.x * cam_refl.x +
1359            cam_refl.y * cam_refl.y +
1360            (cam_refl.z + 1) * (cam_refl.z + 1));
1361        matcap_uv = cam_refl.xy / m + 0.5;
1362      }
1363#endif
1364
1365#if defined(_MATCAP0_DISTORTION0)
1366      float2 distort_uv = matcap_distortion0(matcap_uv);
1367      float2 matcap_uv = distort_uv;
1368#endif
1369      float3 matcap = _Matcap0.SampleBias(linear_repeat_s, matcap_uv, _Global_Sample_Bias) * _Matcap0Str;
1370
1371      float q = _Matcap0Quantization;
1372      if (q > 0) {
1373        matcap = floor(matcap * q) / q;
1374      }
1375
1376      int mode = round(_Matcap0Mode);
1377      switch (mode) {
1378        case 0:
1379          albedo.rgb += lerp(0, matcap, matcap_mask);
1380          matcap_emission += lerp(0, matcap, matcap_mask) * _Matcap0Emission;
1381          break;
1382        case 1:
1383          matcap_emission += lerp(0, matcap, matcap_mask) * _Matcap0Emission;
1384          albedo.rgb *= lerp(1, matcap, matcap_mask);
1385          break;
1386        case 2:
1387          matcap_overwrite_mask[0] = max(matcap_mask, matcap_overwrite_mask[0]);
1388          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1389          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Matcap0Emission;
1390          break;
1391        case 3:
1392          albedo.rgb -= lerp(0, matcap, matcap_mask);
1393          matcap_emission -= lerp(0, matcap, matcap_mask) * _Matcap0Emission;
1394          break;
1395        case 4:
1396          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1397          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Matcap0Emission;
1398          break;
1399        case 5:
1400          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1401          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Matcap0Emission;
1402          break;
1403        default:
1404          break;
1405      }
1406    }
1407#endif  // _MATCAP0
1408#if defined(_MATCAP1)
1409    {
1410#if defined(_MATCAP1_MASK)
1411      float4 matcap_mask_raw = _Matcap1_Mask.SampleLevel(linear_repeat_s,
1412          get_uv_by_channel(i, _Matcap1_Mask_UV_Select), 0);
1413      float matcap_mask = matcap_mask_raw.r;
1414      matcap_mask = (bool) round(_Matcap1_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1415      matcap_mask *= matcap_mask_raw.a;
1416#else
1417      float matcap_mask = 1;
1418#endif
1419#if defined(_MATCAP1_MASK2)
1420      {
1421        float4 matcap_mask2_raw = _Matcap1_Mask2.SampleLevel(linear_repeat_s,
1422            get_uv_by_channel(i, _Matcap1_Mask2_UV_Select), 0);
1423        float matcap_mask2 = matcap_mask2_raw.r;
1424        matcap_mask2 = _Matcap1_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1425        matcap_mask2 *= _Matcap1_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1426        matcap_mask *= matcap_mask2;
1427      }
1428#endif
1429#if defined(_MATCAP1_NORMAL)
1430      float3 matcap_normal = UnpackScaleNormal(
1431          _Matcap1Normal.SampleBias(linear_repeat_s,
1432            UV_SCOFF(i, _Matcap1Normal_ST, _Matcap1Normal_UV_Select),
1433            _Global_Sample_Bias + _Matcap1Normal_Mip_Bias),
1434          _Matcap1Normal_Str * _Matcap1MixFactor);
1435      raw_normal = MY_BLEND_NORMALS(raw_normal, matcap_normal, matcap_mask * _Matcap1MixFactor);
1436      normal = float3(
1437          raw_normal.x * i.tangent +
1438          raw_normal.y * binormal +
1439          raw_normal.z * i.normal
1440          );
1441      {
1442        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1443        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(VIEW_DIR(_Matcap1_Center_Eye_Fix), 0)));
1444        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1445        float m = 2.0 * sqrt(
1446            cam_refl.x * cam_refl.x +
1447            cam_refl.y * cam_refl.y +
1448            (cam_refl.z + 1) * (cam_refl.z + 1));
1449        matcap_uv = cam_refl.xy / m + 0.5;
1450      }
1451#endif
1452#if defined(_MATCAP1_DISTORTION0)
1453      float2 distort_uv = matcap_distortion0(matcap_uv);
1454      float2 matcap_uv = distort_uv;
1455#endif
1456      float3 matcap = _Matcap1.SampleBias(linear_repeat_s, matcap_uv, _Global_Sample_Bias) * _Matcap1Str;
1457
1458      float q = _Matcap1Quantization;
1459      if (q > 0) {
1460        matcap = floor(matcap * q) / q;
1461      }
1462
1463      matcap_mask *= _Matcap1MixFactor;
1464
1465      int mode = round(_Matcap1Mode);
1466      switch (mode) {
1467        case 0:
1468          albedo.rgb += lerp(0, matcap, matcap_mask);
1469          matcap_emission += lerp(0, matcap, matcap_mask) * _Matcap1Emission;
1470          break;
1471        case 1:
1472          matcap_emission += lerp(0, matcap, matcap_mask) * _Matcap1Emission;
1473          albedo.rgb *= lerp(1, matcap, matcap_mask);
1474          break;
1475        case 2:
1476          matcap_overwrite_mask[1] = max(matcap_mask, matcap_overwrite_mask[1]);
1477          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1478          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Matcap1Emission;
1479          break;
1480        case 3:
1481          albedo.rgb -= lerp(0, matcap, matcap_mask);
1482          matcap_emission -= lerp(0, matcap, matcap_mask) * _Matcap1Emission;
1483          break;
1484        case 4:
1485          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1486          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Matcap1Emission;
1487          break;
1488        case 5:
1489          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1490          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Matcap1Emission;
1491          break;
1492        default:
1493          break;
1494      }
1495    }
1496#endif  // _MATCAP1
1497  }
1498#endif  // _MATCAP0 || _MATCAP1
1499  matcap_overwrite_mask = 1 - matcap_overwrite_mask;
1500
1501  // TODO get rid of the pow. It's a hack to make matcap replace mode look
1502  // better with overlay tattoos.
1503  float overlay_glitter_mask;
1504  mixOverlayAlbedoRoughnessMetallic(albedo, roughness, metallic, ov,
1505      1 - pow((1 - min(matcap_overwrite_mask[0], matcap_overwrite_mask[1])), 8),
1506      overlay_glitter_mask);
1507#if defined(_DECAL0) || defined(_DECAL1) || defined(_DECAL2) || defined(_DECAL3) || defined(_DECAL4) || defined(_DECAL5) || defined(_DECAL6) || defined(_DECAL7) || defined(_DECAL8) || defined(_DECAL9)
1508  float3 decal_emission = 0;
1509  applyDecal(albedo, roughness, metallic, decal_emission, i);
1510#endif
1511
1512#if defined(_RENDERING_CUTOUT)
1513#if defined(_RENDERING_CUTOUT_STOCHASTIC)
1514  float ar = rand2(i.uv0);
1515  clip(albedo.a - ar);
1516#elif defined(_RENDERING_CUTOUT_IGN)
1517  float ar = ign(floor(tdata.screen_uv_round * _Rendering_Cutout_Noise_Scale) + _Rendering_Cutout_Ign_Seed);
1518  ar = frac(ar + frame * PHI * _Rendering_Cutout_Speed);
1519  clip(albedo.a - ar);
1520#elif defined(_RENDERING_CUTOUT_NOISE_MASK)
1521  float ar = _Rendering_Cutout_Noise_Mask.SampleLevel(point_repeat_s,
1522      tdata.screen_uv * _ScreenParams.xy *
1523      _Rendering_Cutout_Noise_Mask_TexelSize.xy, 0);
1524  ar = frac(ar + frame * PHI * _Rendering_Cutout_Speed);
1525  clip(albedo.a - ar);
1526#elif defined(_RENDERING_CUTOUT_SSFD)
1527  float ar = 1.0 - ssfd(i.uv0, _Rendering_Cutout_SSFD_Scale, _Rendering_Cutout_SSFD_Max_Fwidth, 0, _Rendering_Cutout_SSFD_Noise);
1528  ar = ar > albedo.a ? 1 : 0;
1529  clip(albedo.a - ar);
1530#else
1531  clip(albedo.a - _Alpha_Cutoff);
1532#endif
1533
1534  albedo.a = 1;
1535#endif  // _RENDERING_CUTOUT
1536
1537#if defined(_GIMMICK_AL_CHROMA_00)
1538  if (_Gimmick_AL_Chroma_00_Forward_Pass && AudioLinkIsAvailable()) {
1539    float3 c = AudioLinkData(ALPASS_CCSTRIP + uint2(0, 0)).rgb;
1540#if defined(_GIMMICK_AL_CHROMA_00_HUE_SHIFT)
1541    c = LRGBtoOKLCH(c);
1542    c[2] += _Gimmick_AL_Chroma_00_Hue_Shift_Theta * 2.0 * 3.14159265;
1543    c = OKLCHtoLRGB(c);
1544#endif
1545    albedo.rgb = lerp(albedo.rgb, c, _Gimmick_AL_Chroma_00_Forward_Blend);
1546  }
1547#endif
1548
1549#if defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1) || defined(_RIM_LIGHTING2) || defined(_RIM_LIGHTING3)
1550  {
1551#if defined(_RIM_LIGHTING0)
1552    {
1553      float3 rl_view_dir = VIEW_DIR(_Rim_Lighting0_Center_Eye_Fix);
1554#if defined(_RIM_LIGHTING0_CUSTOM_VIEW_VECTOR)
1555      rl_view_dir.xz = normalize(_Rim_Lighting0_Custom_View_Vector).xz;
1556#endif
1557      float2 rl_uv;
1558      {
1559#if defined(_RIM_LIGHTING0_REFLECT_IN_WORLD)
1560        const float3 cam_normal = _Rim_Lighting0_Use_Texture_Normals ? normal : i.normal;
1561        const float3 cam_view_dir = rl_view_dir;
1562#else
1563        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(_Rim_Lighting0_Use_Texture_Normals ? normal : i.normal, 0)));
1564        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(rl_view_dir, 0)));
1565#endif
1566        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1567        float m = 2.0 * sqrt(
1568            cam_refl.x * cam_refl.x +
1569            cam_refl.y * cam_refl.y +
1570            (cam_refl.z + 1) * (cam_refl.z + 1));
1571        rl_uv = cam_refl.xy / m + 0.5;
1572      }
1573      float rl = length(rl_uv - 0.5);
1574      rl = pow(2, -_Rim_Lighting0_Power * abs(rl - _Rim_Lighting0_Center));
1575      float q = _Rim_Lighting0_Quantization;
1576      if (q > 0) {
1577        rl = floor(rl * q) / q;
1578      }
1579      float3 matcap = rl * _Rim_Lighting0_Color * _Rim_Lighting0_Strength;
1580#if defined(_RIM_LIGHTING0_MASK)
1581      float4 matcap_mask_raw = _Rim_Lighting0_Mask.SampleBias(GET_SAMPLER_RL0,
1582          get_uv_by_channel(i, _Rim_Lighting0_Mask_UV_Select), _Global_Sample_Bias);
1583      float matcap_mask = matcap_mask_raw.r;
1584      matcap_mask = (bool) round(_Rim_Lighting0_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1585      matcap_mask *= matcap_mask_raw.a;
1586#else
1587      float matcap_mask = 1;
1588#endif
1589#if defined(_RIM_LIGHTING0_MASK2)
1590      float4 matcap_mask2_raw = _Rim_Lighting0_Mask2.SampleBias(GET_SAMPLER_RL0,
1591          get_uv_by_channel(i, _Rim_Lighting0_Mask2_UV_Select), _Global_Sample_Bias);
1592      float matcap_mask2 = matcap_mask2_raw.r;
1593      matcap_mask2 = _Rim_Lighting0_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1594      matcap_mask2 *= _Rim_Lighting0_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1595      matcap_mask *= matcap_mask2;
1596#endif
1597#if defined(_MATCAP0)
1598        if (_Matcap0_Overwrite_Rim_Lighting_0) {
1599          matcap_mask *= matcap_overwrite_mask[0];
1600        }
1601#endif
1602#if defined(_MATCAP1)
1603        if (_Matcap1_Overwrite_Rim_Lighting_0) {
1604          matcap_mask *= matcap_overwrite_mask[1];
1605        }
1606#endif
1607#if defined(_RIM_LIGHTING0_POLAR_MASK)
1608        if (_Rim_Lighting0_PolarMask_Enabled) {
1609          float theta = atan2(rl_uv.y - 0.5, rl_uv.x - 0.5);
1610          float pmask_theta = _Rim_Lighting0_PolarMask_Theta;
1611          float pmask_pow = _Rim_Lighting0_PolarMask_Power;
1612          float d = glsl_mod((theta - pmask_theta) - PI, 2 * PI) - PI;
1613          float f = abs(1.0 / (1.0 + pow(abs(d), pmask_pow)));
1614          if (_Rim_Lighting0_Quantization > 0) {
1615            f = floor(f * _Rim_Lighting0_Quantization) / _Rim_Lighting0_Quantization;
1616          }
1617          matcap_mask *= f;
1618        }
1619#endif
1620#if defined(_RIM_LIGHTING0_GLITTER)
1621      float rl_glitter = get_glitter(
1622          get_uv_by_channel(i, round(_Rim_Lighting0_Glitter_UV_Select)),
1623          i.worldPos, CAM_POS(_Rim_Lighting0_Center_Eye_Fix), normal,
1624          _Rim_Lighting0_Glitter_Density,
1625          _Rim_Lighting0_Glitter_Amount, _Rim_Lighting0_Glitter_Speed,
1626          /*mask=*/1, /*angle=*/91, /*power=*/1);
1627      rl_glitter = floor(rl_glitter * _Rim_Lighting0_Glitter_Quantization) / _Rim_Lighting0_Glitter_Quantization;
1628      matcap_mask *= rl_glitter;
1629#endif
1630      int mode = round(_Rim_Lighting0_Mode);
1631      switch (mode) {
1632        case 0:
1633          albedo.rgb += lerp(0, matcap, matcap_mask);
1634          matcap_emission += lerp(0, matcap, matcap_mask) * _Rim_Lighting0_Emission;
1635          break;
1636        case 1:
1637          matcap_emission += albedo.rgb * lerp(0, matcap, matcap_mask) * _Rim_Lighting0_Emission;
1638          albedo.rgb *= lerp(1, matcap, matcap_mask);
1639          break;
1640        case 2:
1641          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1642          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Rim_Lighting0_Emission;
1643          break;
1644        case 3:
1645          albedo.rgb -= lerp(0, matcap, matcap_mask);
1646          matcap_emission -= lerp(0, matcap, matcap_mask) * _Rim_Lighting0_Emission;
1647          break;
1648        case 4:
1649          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1650          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting0_Emission;
1651          break;
1652        case 5:
1653          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1654          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting0_Emission;
1655          break;
1656        default:
1657          break;
1658      }
1659    }
1660#endif  // _RIM_LIGHTING0
1661#if defined(_RIM_LIGHTING1)
1662    {
1663      float3 rl_view_dir = VIEW_DIR(_Rim_Lighting1_Center_Eye_Fix);
1664#if defined(_RIM_LIGHTING1_CUSTOM_VIEW_VECTOR)
1665      rl_view_dir.xz = normalize(_Rim_Lighting1_Custom_View_Vector).xz;
1666#endif
1667      float2 rl_uv;
1668      {
1669#if defined(_RIM_LIGHTING1_REFLECT_IN_WORLD)
1670        const float3 cam_normal = normal;
1671        const float3 cam_view_dir = rl_view_dir;
1672#else
1673        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1674        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(rl_view_dir, 0)));
1675#endif
1676        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1677        float m = 2.0 * sqrt(
1678            cam_refl.x * cam_refl.x +
1679            cam_refl.y * cam_refl.y +
1680            (cam_refl.z + 1) * (cam_refl.z + 1));
1681        rl_uv = cam_refl.xy / m + 0.5;
1682      }
1683      float rl = length(rl_uv - 0.5);
1684      rl = pow(2, -_Rim_Lighting1_Power * abs(rl - _Rim_Lighting1_Center));
1685      float q = _Rim_Lighting1_Quantization;
1686      if (q > 0) {
1687        rl = floor(rl * q) / q;
1688      }
1689      float3 matcap = rl * _Rim_Lighting1_Color * _Rim_Lighting1_Strength;
1690#if defined(_RIM_LIGHTING1_MASK)
1691      float4 matcap_mask_raw = _Rim_Lighting1_Mask.SampleBias(GET_SAMPLER_RL1,
1692          get_uv_by_channel(i, _Rim_Lighting1_Mask_UV_Select), _Global_Sample_Bias);
1693      float matcap_mask = matcap_mask_raw.r;
1694      matcap_mask = (bool) round(_Rim_Lighting1_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1695      matcap_mask *= matcap_mask_raw.a;
1696#else
1697      float matcap_mask = 1;
1698#endif
1699#if defined(_RIM_LIGHTING1_MASK2)
1700      float4 matcap_mask2_raw = _Rim_Lighting1_Mask2.SampleBias(GET_SAMPLER_RL1,
1701          get_uv_by_channel(i, _Rim_Lighting1_Mask2_UV_Select), _Global_Sample_Bias);
1702      float matcap_mask2 = matcap_mask2_raw.r;
1703      matcap_mask2 = _Rim_Lighting1_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1704      matcap_mask2 *= _Rim_Lighting1_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1705      matcap_mask *= matcap_mask2;
1706#endif
1707#if defined(_MATCAP0)
1708        if (_Matcap0_Overwrite_Rim_Lighting_1) {
1709          matcap_mask *= matcap_overwrite_mask[0];
1710        }
1711#endif
1712#if defined(_MATCAP1)
1713        if (_Matcap1_Overwrite_Rim_Lighting_1) {
1714          matcap_mask *= matcap_overwrite_mask[1];
1715        }
1716#endif
1717#if defined(_RIM_LIGHTING1_POLAR_MASK)
1718        if (_Rim_Lighting1_PolarMask_Enabled) {
1719          float theta = atan2(rl_uv.y - 0.5, rl_uv.x - 0.5);
1720          float pmask_theta = _Rim_Lighting1_PolarMask_Theta;
1721          float pmask_pow = _Rim_Lighting1_PolarMask_Power;
1722          float d = glsl_mod((theta - pmask_theta) - PI, 2 * PI) - PI;
1723          float f = abs(1.0 / (1.0 + pow(abs(d), pmask_pow)));
1724          if (_Rim_Lighting1_Quantization > 0) {
1725            f = floor(f * _Rim_Lighting1_Quantization) / _Rim_Lighting1_Quantization;
1726          }
1727          matcap_mask *= f;
1728        }
1729#endif
1730#if defined(_RIM_LIGHTING1_GLITTER)
1731      float rl_glitter = get_glitter(
1732          get_uv_by_channel(i, round(_Rim_Lighting1_Glitter_UV_Select)),
1733          i.worldPos, CAM_POS(_Rim_Lighting1_Center_Eye_Fix), normal,
1734          _Rim_Lighting1_Glitter_Density,
1735          _Rim_Lighting1_Glitter_Amount, _Rim_Lighting1_Glitter_Speed,
1736          /*mask=*/1, /*angle=*/91, /*power=*/1);
1737      rl_glitter = floor(rl_glitter * _Rim_Lighting1_Glitter_Quantization) / _Rim_Lighting1_Glitter_Quantization;
1738      matcap_mask *= rl_glitter;
1739#endif
1740      int mode = round(_Rim_Lighting1_Mode);
1741      switch (mode) {
1742        case 0:
1743          albedo.rgb += lerp(0, matcap, matcap_mask);
1744          matcap_emission += lerp(0, matcap, matcap_mask) * _Rim_Lighting1_Emission;
1745          break;
1746        case 1:
1747          matcap_emission += albedo.rgb * lerp(0, matcap, matcap_mask) * _Rim_Lighting1_Emission;
1748          albedo.rgb *= lerp(1, matcap, matcap_mask);
1749          break;
1750        case 2:
1751          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1752          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Rim_Lighting1_Emission;
1753          break;
1754        case 3:
1755          albedo.rgb -= lerp(0, matcap, matcap_mask);
1756          matcap_emission -= lerp(0, matcap, matcap_mask) * _Rim_Lighting1_Emission;
1757          break;
1758        case 4:
1759          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1760          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting1_Emission;
1761          break;
1762        case 5:
1763          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1764          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting1_Emission;
1765          break;
1766        default:
1767          break;
1768      }
1769    }
1770#endif  // _RIM_LIGHTING1
1771#if defined(_RIM_LIGHTING2)
1772    {
1773      float3 rl_view_dir = VIEW_DIR(_Rim_Lighting2_Center_Eye_Fix);
1774#if defined(_RIM_LIGHTING2_CUSTOM_VIEW_VECTOR)
1775      rl_view_dir.xz = normalize(_Rim_Lighting2_Custom_View_Vector).xz;
1776#endif
1777      float2 rl_uv;
1778      {
1779#if defined(_RIM_LIGHTING2_REFLECT_IN_WORLD)
1780        const float3 cam_normal = normal;
1781        const float3 cam_view_dir = rl_view_dir;
1782#else
1783        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1784        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(rl_view_dir, 0)));
1785#endif
1786        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1787        float m = 2.0 * sqrt(
1788            cam_refl.x * cam_refl.x +
1789            cam_refl.y * cam_refl.y +
1790            (cam_refl.z + 1) * (cam_refl.z + 1));
1791        rl_uv = cam_refl.xy / m + 0.5;
1792      }
1793      float rl = length(rl_uv - 0.5);
1794      rl = pow(2, -_Rim_Lighting2_Power * abs(rl - _Rim_Lighting2_Center));
1795      float q = _Rim_Lighting2_Quantization;
1796      if (q > 0) {
1797        rl = floor(rl * q) / q;
1798      }
1799      float3 matcap = rl * _Rim_Lighting2_Color * _Rim_Lighting2_Strength;
1800#if defined(_RIM_LIGHTING2_MASK)
1801      float4 matcap_mask_raw = _Rim_Lighting2_Mask.SampleBias(GET_SAMPLER_RL2,
1802          get_uv_by_channel(i, _Rim_Lighting2_Mask_UV_Select), _Global_Sample_Bias);
1803      float matcap_mask = matcap_mask_raw.r;
1804      matcap_mask = (bool) round(_Rim_Lighting2_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1805      matcap_mask *= matcap_mask_raw.a;
1806#else
1807      float matcap_mask = 1;
1808#endif
1809#if defined(_RIM_LIGHTING2_MASK2)
1810      float4 matcap_mask2_raw = _Rim_Lighting2_Mask2.SampleBias(GET_SAMPLER_RL2,
1811          get_uv_by_channel(i, _Rim_Lighting2_Mask2_UV_Select), _Global_Sample_Bias);
1812      float matcap_mask2 = matcap_mask2_raw.r;
1813      matcap_mask2 = _Rim_Lighting2_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1814      matcap_mask2 *= _Rim_Lighting2_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1815      matcap_mask *= matcap_mask2;
1816#endif
1817#if defined(_MATCAP0)
1818        if (_Matcap0_Overwrite_Rim_Lighting_2) {
1819          matcap_mask *= matcap_overwrite_mask[0];
1820        }
1821#endif
1822#if defined(_MATCAP1)
1823        if (_Matcap1_Overwrite_Rim_Lighting_2) {
1824          matcap_mask *= matcap_overwrite_mask[1];
1825        }
1826#endif
1827#if defined(_RIM_LIGHTING2_POLAR_MASK)
1828        if (_Rim_Lighting2_PolarMask_Enabled) {
1829          float theta = atan2(rl_uv.y - 0.5, rl_uv.x - 0.5);
1830          float pmask_theta = _Rim_Lighting2_PolarMask_Theta;
1831          float pmask_pow = _Rim_Lighting2_PolarMask_Power;
1832          float d = glsl_mod((theta - pmask_theta) - PI, 2 * PI) - PI;
1833          float f = abs(1.0 / (1.0 + pow(abs(d), pmask_pow)));
1834          if (_Rim_Lighting2_Quantization > 0) {
1835            f = floor(f * _Rim_Lighting2_Quantization) / _Rim_Lighting2_Quantization;
1836          }
1837          matcap_mask *= f;
1838        }
1839#endif
1840#if defined(_RIM_LIGHTING2_GLITTER)
1841      float rl_glitter = get_glitter(
1842          get_uv_by_channel(i, round(_Rim_Lighting2_Glitter_UV_Select)),
1843          i.worldPos, CAM_POS(_Rim_Lighting2_Center_Eye_Fix), normal,
1844          _Rim_Lighting2_Glitter_Density,
1845          _Rim_Lighting2_Glitter_Amount, _Rim_Lighting2_Glitter_Speed,
1846          /*mask=*/1, /*angle=*/91, /*power=*/1);
1847      rl_glitter = floor(rl_glitter * _Rim_Lighting2_Glitter_Quantization) / _Rim_Lighting2_Glitter_Quantization;
1848      matcap_mask *= rl_glitter;
1849#endif
1850      int mode = round(_Rim_Lighting2_Mode);
1851      switch (mode) {
1852        case 0:
1853          albedo.rgb += lerp(0, matcap, matcap_mask);
1854          matcap_emission += lerp(0, matcap, matcap_mask) * _Rim_Lighting2_Emission;
1855          break;
1856        case 1:
1857          matcap_emission += albedo.rgb * lerp(0, matcap, matcap_mask) * _Rim_Lighting2_Emission;
1858          albedo.rgb *= lerp(1, matcap, matcap_mask);
1859          break;
1860        case 2:
1861          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1862          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Rim_Lighting2_Emission;
1863          break;
1864        case 3:
1865          albedo.rgb -= lerp(0, matcap, matcap_mask);
1866          matcap_emission -= lerp(0, matcap, matcap_mask) * _Rim_Lighting2_Emission;
1867          break;
1868        case 4:
1869          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1870          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting2_Emission;
1871          break;
1872        case 5:
1873          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1874          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting2_Emission;
1875          break;
1876        default:
1877          break;
1878      }
1879    }
1880#endif  // _RIM_LIGHTING2
1881#if defined(_RIM_LIGHTING3)
1882    {
1883      float3 rl_view_dir = VIEW_DIR(_Rim_Lighting3_Center_Eye_Fix);
1884#if defined(_RIM_LIGHTING3_CUSTOM_VIEW_VECTOR)
1885      rl_view_dir.xz = normalize(_Rim_Lighting3_Custom_View_Vector).xz;
1886#endif
1887      float2 rl_uv;
1888      {
1889#if defined(_RIM_LIGHTING3_REFLECT_IN_WORLD)
1890        const float3 cam_normal = normal;
1891        const float3 cam_view_dir = rl_view_dir;
1892#else
1893        const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(normal, 0)));
1894        const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(rl_view_dir, 0)));
1895#endif
1896        const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
1897        float m = 2.0 * sqrt(
1898            cam_refl.x * cam_refl.x +
1899            cam_refl.y * cam_refl.y +
1900            (cam_refl.z + 1) * (cam_refl.z + 1));
1901        rl_uv = cam_refl.xy / m + 0.5;
1902      }
1903      float rl = length(rl_uv - 0.5);
1904      rl = pow(2, -_Rim_Lighting3_Power * abs(rl - _Rim_Lighting3_Center));
1905      float q = _Rim_Lighting3_Quantization;
1906      if (q > 0) {
1907        rl = floor(rl * q) / q;
1908      }
1909      float3 matcap = rl * _Rim_Lighting3_Color * _Rim_Lighting3_Strength;
1910#if defined(_RIM_LIGHTING3_MASK)
1911      float4 matcap_mask_raw = _Rim_Lighting3_Mask.SampleBias(GET_SAMPLER_RL3,
1912          get_uv_by_channel(i, _Rim_Lighting3_Mask_UV_Select), _Global_Sample_Bias);
1913      float matcap_mask = matcap_mask_raw.r;
1914      matcap_mask = (bool) round(_Rim_Lighting3_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
1915      matcap_mask *= matcap_mask_raw.a;
1916#else
1917      float matcap_mask = 1;
1918#endif
1919#if defined(_RIM_LIGHTING3_MASK2)
1920      float4 matcap_mask2_raw = _Rim_Lighting3_Mask2.SampleBias(GET_SAMPLER_RL3,
1921          get_uv_by_channel(i, _Rim_Lighting3_Mask2_UV_Select), _Global_Sample_Bias);
1922      float matcap_mask2 = matcap_mask2_raw.r;
1923      matcap_mask2 = _Rim_Lighting3_Mask2_Invert_Colors ? 1 - matcap_mask2 : matcap_mask2;
1924      matcap_mask2 *= _Rim_Lighting3_Mask2_Invert_Alpha ? 1 - matcap_mask2_raw.a : matcap_mask2_raw.a;
1925      matcap_mask *= matcap_mask2;
1926#endif
1927#if defined(_MATCAP0)
1928        if (_Matcap0_Overwrite_Rim_Lighting_3) {
1929          matcap_mask *= matcap_overwrite_mask[0];
1930        }
1931#endif
1932#if defined(_MATCAP1)
1933        if (_Matcap1_Overwrite_Rim_Lighting_3) {
1934          matcap_mask *= matcap_overwrite_mask[1];
1935        }
1936#endif
1937#if defined(_RIM_LIGHTING3_POLAR_MASK)
1938        if (_Rim_Lighting3_PolarMask_Enabled) {
1939          float theta = atan2(rl_uv.y - 0.5, rl_uv.x - 0.5);
1940          float pmask_theta = _Rim_Lighting3_PolarMask_Theta;
1941          float pmask_pow = _Rim_Lighting3_PolarMask_Power;
1942          float d = glsl_mod((theta - pmask_theta) - PI, 2 * PI) - PI;
1943          float f = abs(1.0 / (1.0 + pow(abs(d), pmask_pow)));
1944          if (_Rim_Lighting3_Quantization > 0) {
1945            f = floor(f * _Rim_Lighting3_Quantization) / _Rim_Lighting3_Quantization;
1946          }
1947          matcap_mask *= f;
1948        }
1949#endif
1950#if defined(_RIM_LIGHTING3_GLITTER)
1951      float rl_glitter = get_glitter(
1952          get_uv_by_channel(i, round(_Rim_Lighting3_Glitter_UV_Select)),
1953          i.worldPos, CAM_POS(_Rim_Lighting3_Center_Eye_Fix), normal,
1954          _Rim_Lighting3_Glitter_Density,
1955          _Rim_Lighting3_Glitter_Amount, _Rim_Lighting3_Glitter_Speed,
1956          /*mask=*/1, /*angle=*/91, /*power=*/1);
1957      rl_glitter = floor(rl_glitter * _Rim_Lighting3_Glitter_Quantization) / _Rim_Lighting3_Glitter_Quantization;
1958      matcap_mask *= rl_glitter;
1959#endif
1960      int mode = round(_Rim_Lighting3_Mode);
1961      switch (mode) {
1962        case 0:
1963          albedo.rgb += lerp(0, matcap, matcap_mask);
1964          matcap_emission += lerp(0, matcap, matcap_mask) * _Rim_Lighting3_Emission;
1965          break;
1966        case 1:
1967          matcap_emission += albedo.rgb * lerp(0, matcap, matcap_mask) * _Rim_Lighting3_Emission;
1968          albedo.rgb *= lerp(1, matcap, matcap_mask);
1969          break;
1970        case 2:
1971          albedo.rgb = lerp(albedo.rgb, matcap, matcap_mask);
1972          matcap_emission = lerp(albedo.rgb, matcap, matcap_mask) * _Rim_Lighting3_Emission;
1973          break;
1974        case 3:
1975          albedo.rgb -= lerp(0, matcap, matcap_mask);
1976          matcap_emission -= lerp(0, matcap, matcap_mask) * _Rim_Lighting3_Emission;
1977          break;
1978        case 4:
1979          albedo.rgb = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask);
1980          matcap_emission = lerp(albedo.rgb, min(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting3_Emission;
1981          break;
1982        case 5:
1983          albedo.rgb = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask);
1984          matcap_emission = lerp(albedo.rgb, max(albedo.rgb, matcap), matcap_mask) * _Rim_Lighting3_Emission;
1985          break;
1986        default:
1987          break;
1988      }
1989    }
1990#endif  // _RIM_LIGHTING3
1991  }
1992#endif  // _RIM_LIGHTING0 || _RIM_LIGHTING1 || _RIM_LIGHTING2 || _RIM_LIGHTING3
1993
1994#if defined(_GIMMICK_LETTER_GRID)
1995  float3 gimmick_letter_grid_emission = 0;
1996  {
1997    int2 cell_pos;
1998    int2 font_res = int2(round(_Gimmick_Letter_Grid_Tex_Res_X), round(_Gimmick_Letter_Grid_Tex_Res_Y)); 
1999    int2 grid_res = int2(round(_Gimmick_Letter_Grid_Res_X), round(_Gimmick_Letter_Grid_Res_Y)); 
2000    float2 cell_uv;  // uv within each letter cell
2001
2002    float4 scoff = _Gimmick_Letter_Grid_UV_Scale_Offset;
2003    float2 uv = ((get_uv_by_channel(i, _Gimmick_Letter_Grid_UV_Select) - 0.5) - scoff.zw) * scoff.xy + 0.5;
2004    bool in_box = getBoxLoc(uv,
2005        /*bottom_left=*/0,
2006        /*top_right=*/1,
2007        /*res=*/grid_res,
2008        /*padding=*/_Gimmick_Letter_Grid_Padding,
2009        cell_pos, cell_uv);
2010
2011    float n_glyphs = font_res.x * font_res.y;
2012    float cell_rand = rand2(cell_pos);
2013    float c = glsl_mod(cell_pos.y * grid_res.x + cell_pos.x + cell_rand * n_glyphs + _Time[3], n_glyphs);
2014    float3 msd = renderInBox(c, uv, cell_uv, _Gimmick_Letter_Grid_Texture, font_res).rgb;
2015    float sd = median(msd);
2016    float px_range = 2;  // determined by msdf-atlas-gen.exe; 2 is default
2017    float2 unit_range = px_range / 1024;
2018    float2 screen_tex_size = 1 / fwidth(cell_uv);
2019    float screen_px_range = max(0.5 * dot(unit_range, screen_tex_size), 1.0);
2020    float screen_px_distance = screen_px_range * (sd - 0.5);
2021    float op = saturate(screen_px_distance + 0.5);
2022    op = saturate(floor(op * 4));
2023
2024    float4 grid_color = _Gimmick_Letter_Grid_Color;
2025
2026#if defined(_GIMMICK_LETTER_GRID_COLOR_WAVE)
2027    {
2028      float2 c = grid_res/2;
2029      float d = floor(length(cell_pos - c));
2030      d *= _Gimmick_Letter_Grid_Color_Wave_Frequency;
2031
2032      float3 col = LRGBtoOKLCH(grid_color.rgb);
2033      col[2] += d - _Time[3] * _Gimmick_Letter_Grid_Color_Wave_Speed;
2034      col = OKLCHtoLRGB(col);
2035      grid_color.rgb = col;
2036    }
2037#endif  // _GIMMICK_LETTER_GRID_COLOR_WAVE
2038#if defined(_GIMMICK_LETTER_GRID_RIM_LIGHTING)
2039    {
2040      float theta = atan2(length(cross(MATCAP_VIEW_DIR(), normal)), dot(MATCAP_VIEW_DIR(), normal));
2041      float rl = abs(theta) / PI;  // on [0, 1]
2042      rl = pow(2, -_Gimmick_Letter_Grid_Rim_Lighting_Power * abs(rl - _Gimmick_Letter_Grid_Rim_Lighting_Center));
2043      float q = _Gimmick_Letter_Grid_Rim_Lighting_Quantization;
2044      if (q > 0) {
2045        rl = floor(rl * q) / q;
2046      }
2047
2048      float4 matcap_mask_raw = _Gimmick_Letter_Grid_Rim_Lighting_Mask.SampleBias(GET_SAMPLER_RL3,
2049          get_uv_by_channel(i, _Gimmick_Letter_Grid_Rim_Lighting_Mask_UV_Select), _Global_Sample_Bias);
2050      float matcap_mask = matcap_mask_raw.r;
2051      matcap_mask = (bool) round(_Gimmick_Letter_Grid_Rim_Lighting_Mask_Invert) ? 1 - matcap_mask : matcap_mask;
2052      matcap_mask *= matcap_mask_raw.a;
2053
2054      op *= rl * matcap_mask;
2055    }
2056#endif  // GIMMICK_LETTER_GRID_RIM_LIGHTING
2057
2058    albedo = lerp(albedo, grid_color, op * in_box);
2059    metallic = lerp(metallic, _Gimmick_Letter_Grid_Metallic, op * in_box);
2060    //metallic = lerp(metallic, glsl_mod(_Time[3], 1.0), op * in_box);
2061    roughness = lerp(roughness, _Gimmick_Letter_Grid_Roughness, op * in_box);
2062    gimmick_letter_grid_emission = _Gimmick_Letter_Grid_Color * _Gimmick_Letter_Grid_Emission * op * in_box;
2063  }
2064#endif  // _GIMMICK_LETTER_GRID
2065
2066#if defined(_GIMMICK_LETTER_GRID_2)
2067  float3 gimmick_letter_grid_2_emission = 0;
2068#if defined(_GIMMICK_LETTER_GRID_2_MASK)
2069  float mask = _Gimmick_Letter_Grid_2_Mask.SampleLevel(linear_repeat_s, get_uv_by_channel(i, 0), 0);
2070#else
2071  float mask = 1;
2072#endif
2073  {
2074    int2 cell_pos;
2075    int2 font_res = int2(round(_Gimmick_Letter_Grid_2_Tex_Res_X), round(_Gimmick_Letter_Grid_2_Tex_Res_Y));
2076    int2 grid_res = int2(round(_Gimmick_Letter_Grid_2_Res_X), round(_Gimmick_Letter_Grid_2_Res_Y));
2077    float2 cell_uv;  // uv within each letter cell
2078
2079    float4 scoff = _Gimmick_Letter_Grid_2_UV_Scale_Offset;
2080    float2 uv = ((get_uv_by_channel(i, 0) - 0.5) - scoff.zw) * scoff.xy + 0.5;
2081
2082    bool in_box = getBoxLoc(uv,
2083        /*bottom_left=*/0,
2084        /*top_right=*/1,
2085        /*res=*/grid_res,
2086        /*padding=*/_Gimmick_Letter_Grid_2_Padding,
2087        cell_pos, cell_uv);
2088
2089    // Extract char from _Gimmick_Letter_Grid_2_Data_Row_0 et al using cell_pos.
2090    cell_pos.y = (grid_res.y - cell_pos.y) - 1;
2091    float c = lerp(
2092      lerp(
2093        _Gimmick_Letter_Grid_2_Data_Row_0[cell_pos.x],
2094        _Gimmick_Letter_Grid_2_Data_Row_1[cell_pos.x],
2095        cell_pos.y),
2096      lerp(
2097        _Gimmick_Letter_Grid_2_Data_Row_2[cell_pos.x],
2098        _Gimmick_Letter_Grid_2_Data_Row_3[cell_pos.x],
2099        cell_pos.y - 2),
2100      cell_pos.y/2);
2101    c += _Gimmick_Letter_Grid_2_Global_Offset;
2102
2103    float3 msd = renderInBox(c, uv, cell_uv, _Gimmick_Letter_Grid_2_Texture, font_res).rgb;
2104    float sd = median(msd);
2105    // screenPxRange()
2106    float screen_px_range;
2107    {
2108      float2 tex_size = float2(_Gimmick_Letter_Grid_2_Texture_TexelSize.zw);
2109      float2 real_cell_size = floor(tex_size / grid_res);  // size of cell in texels
2110      float2 unit_range = _Gimmick_Letter_Grid_2_Screen_Px_Range / real_cell_size;
2111      // fwidth(x) = abs(abs(ddx(x)) + abs(ddy(x)))
2112      // 1 / fwidth(cell_uv)
2113      //   = 1 / abs(abs(ddx(cell_uv)) + abs(ddy(cell_uv)))
2114      // This is just the manhattan length of the triangle with edges
2115      //   ddx(cell_uv.x) and ddy(cell_uv.x).
2116      // In other words, an approximation of the gradient of cell_uv.x.
2117
2118      // fwidth is an approximation showing how much cell_uv changes per pixel.
2119      // By inverting it, we get an approximation of how many pixels are
2120      // spanned by the whole texture, if it was rendered with this pixel's
2121      // properties.
2122      float2 screen_tex_size = 1 / fwidth(cell_uv);
2123
2124      screen_px_range = max(0.5 * dot(unit_range, screen_tex_size), _Gimmick_Letter_Grid_2_Min_Screen_Px_Range);
2125    }
2126    float screen_px_distance = screen_px_range * (sd - _Gimmick_Letter_Grid_2_Alpha_Threshold);
2127    float smooth_range = (length(grid_res) / sqrt(screen_px_range)) * _Gimmick_Letter_Grid_2_Blurriness;
2128    float op = smoothstep(-smooth_range, smooth_range, screen_px_distance);
2129    op *= mask;
2130    //op = floor(op);
2131
2132    albedo = lerp(albedo, _Gimmick_Letter_Grid_2_Color, op * in_box);
2133    metallic = lerp(metallic, _Gimmick_Letter_Grid_2_Metallic, op * in_box);
2134    roughness = lerp(roughness, _Gimmick_Letter_Grid_2_Roughness, op * in_box);
2135    gimmick_letter_grid_2_emission = _Gimmick_Letter_Grid_2_Color * _Gimmick_Letter_Grid_2_Emission * op * in_box;
2136  }
2137#endif  // _GIMMICK_LETTER_GRID
2138
2139
2140#if defined(_OKLAB)
2141  // Do hue shift in perceptually uniform color space so it doesn't look like
2142  // shit.
2143 float oklab_mask = _OKLAB_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
2144 if (_OKLAB_Mask_Invert) {
2145   oklab_mask = 1 - oklab_mask;
2146 }
2147 if (oklab_mask > 0.01 &&
2148     (_OKLAB_Hue_Shift > 1E-6 ||
2149      abs(_OKLAB_Chroma_Shift) > 1E-6 ||
2150      abs(_OKLAB_Lightness_Shift) > 1E-6)) {
2151   float3 c = albedo.rgb;
2152   c = LRGBtoOKLCH(c);
2153   c.x += _OKLAB_Lightness_Shift;
2154   c.y += _OKLAB_Chroma_Shift;
2155   c.z += _OKLAB_Hue_Shift;
2156   c = OKLCHtoLRGB(c);
2157   albedo.rgb = c;
2158 }
2159#endif
2160
2161#if defined(_HSV0)
2162 {
2163   float hsv_mask = _HSV0_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
2164   if (_HSV0_Mask_Invert) {
2165     hsv_mask = 1 - hsv_mask;
2166   }
2167   if (hsv_mask > 0.01 &&
2168       (_HSV0_Hue_Shift > 1E-6 ||
2169        abs(_HSV0_Sat_Shift) > 1E-6 ||
2170        abs(_HSV0_Val_Shift) > 1E-6)) {
2171     float3 c = albedo.rgb;
2172     c = RGBtoHSV(c);
2173     c += float3(_HSV0_Hue_Shift, _HSV0_Sat_Shift, _HSV0_Val_Shift);
2174     c.x = glsl_mod(c.x, 1.0);
2175     c.yz = saturate(c.yz);
2176     c = HSVtoRGB(c);
2177     albedo.rgb = c;
2178   }
2179 }
2180#endif
2181
2182#if defined(_HSV1)
2183 {
2184   float hsv_mask = _HSV1_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
2185   if (_HSV1_Mask_Invert) {
2186     hsv_mask = 1 - hsv_mask;
2187   }
2188   if (hsv_mask > 0.01 &&
2189       (_HSV1_Hue_Shift > 1E-6 ||
2190        abs(_HSV1_Sat_Shift) > 1E-6 ||
2191        abs(_HSV1_Val_Shift) > 1E-6)) {
2192     float3 c = albedo.rgb;
2193     c = RGBtoHSV(c);
2194     c += float3(_HSV1_Hue_Shift, _HSV1_Sat_Shift, _HSV1_Val_Shift);
2195     c.x = glsl_mod(c.x, 1.0);
2196     c.yz = saturate(c.yz);
2197     c = HSVtoRGB(c);
2198     albedo.rgb = c;
2199   }
2200 }
2201#endif
2202
2203#if defined(_HSV2)
2204 {
2205   float hsv_mask = _HSV2_Mask.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
2206   if (_HSV2_Mask_Invert) {
2207     hsv_mask = 1 - hsv_mask;
2208   }
2209   if (hsv_mask > 0.01 &&
2210       (_HSV2_Hue_Shift > 1E-6 ||
2211        abs(_HSV2_Sat_Shift) > 1E-6 ||
2212        abs(_HSV2_Val_Shift) > 1E-6)) {
2213     float3 c = albedo.rgb;
2214     c = RGBtoHSV(c);
2215     c += float3(_HSV2_Hue_Shift, _HSV2_Sat_Shift, _HSV2_Val_Shift);
2216     c.x = glsl_mod(c.x, 1.0);
2217     c.yz = saturate(c.yz);
2218     c = HSVtoRGB(c);
2219     albedo.rgb = c;
2220   }
2221 }
2222#endif
2223
2224#if defined(_AMBIENT_OCCLUSION)
2225  float ao = _Ambient_Occlusion.SampleBias(linear_repeat_s,
2226      UV_SCOFF(i, _Ambient_Occlusion_ST, /*uv_channel=*/0),
2227      _Global_Sample_Bias);
2228  ao = 1 - (1 - ao) * _Ambient_Occlusion_Strength;
2229#else
2230  float ao = 1;
2231#endif
2232
2233#if defined(_GIMMICK_FLAT_COLOR)
2234  if (round(_Gimmick_Flat_Color_Enable_Dynamic)) {
2235    albedo = _Gimmick_Flat_Color_Color;
2236    normal = i.normal;
2237  }
2238#endif
2239#if defined(_GLITTER)
2240  float3 glitter_color_unlit;
2241  {
2242    float glitter_mask =
2243      _Glitter_Mask.SampleLevel(linear_repeat_s, i.uv0, /*lod=*/0);
2244    glitter_mask *= min(matcap_overwrite_mask[0], matcap_overwrite_mask[1]);
2245    glitter_mask *= overlay_glitter_mask;
2246    float glitter = get_glitter(
2247        get_uv_by_channel(i, round(_Glitter_UV_Select)),
2248        i.worldPos, i.centerCamPos, normal,
2249        _Glitter_Density, _Glitter_Amount, _Glitter_Speed,
2250        glitter_mask, _Glitter_Angle, _Glitter_Power);
2251        glitter_color_unlit = glitter * _Glitter_Color;
2252  }
2253  albedo.rgb += glitter_color_unlit * _Glitter_Brightness_Lit;
2254#endif
2255
2256#if defined(_GIMMICK_DS2)
2257  Gimmick_DS2_Output ds2 = (Gimmick_DS2_Output)0;
2258  // TODO if these remain mutually exclusive, we should use an enum + switch
2259  switch (round(_Gimmick_DS2_Choice)) {
2260    case 0:
2261      ds2 = Gimmick_DS2_00(i);
2262      break;
2263    case 1:
2264      ds2 = Gimmick_DS2_01(i);
2265      break;
2266    case 2:
2267      ds2 = Gimmick_DS2_02(i);
2268      break;
2269    case 3:
2270      ds2 = Gimmick_DS2_03(i);
2271      break;
2272    case 10:
2273      ds2 = Gimmick_DS2_10(i);
2274      break;
2275    case 11:
2276      ds2 = Gimmick_DS2_11(i, tdata);
2277      break;
2278    default:
2279      ds2 = (Gimmick_DS2_Output)0;
2280      break;
2281  }
2282  float ds2_mask = _Gimmick_DS2_Mask.SampleLevel(linear_clamp_s, i.uv0, 0);
2283  albedo = ds2.albedo * _Gimmick_DS2_Albedo_Factor * ds2_mask;
2284  normal = ds2.normal;
2285  metallic = ds2.metallic * ds2_mask;
2286  roughness = ds2.roughness;
2287  i.worldPos = ds2.worldPos;
2288  {
2289    float4 clip_pos = mul(UNITY_MATRIX_VP, float4(ds2.worldPos, 1.0));
2290    depth = clip_pos.z / clip_pos.w;
2291  }
2292#endif
2293
2294  float3 diffuse_contrib = 0;
2295  // TODO restore this
2296  // For some dumb fucking dipshit reason, this is incompatible with clearcoat
2297  // in worlds. Probably the compiler optimizer shitting the bed.
2298#if 0 && defined(_GIMMICK_FOG_01)
2299  [branch]
2300  if (!_Gimmick_Fog_01_Overlay_Mode) {
2301    Fog01PBR fog_01_pbr = getFog01(i, tdata);
2302    albedo = fog_01_pbr.albedo;
2303    //depth = fog_01_pbr.depth;
2304#if defined(_RENDERING_TRANSPARENT) || defined(_RENDERING_TRANSCLIPPING)
2305    albedo.rgb *= albedo.a;
2306#endif
2307    return albedo;
2308  }
2309#endif
2310#if defined(_GIMMICK_AURORA)
2311  {
2312    AuroraPBR pbr = getAurora(i);
2313    albedo = pbr.albedo;
2314    depth = pbr.depth;
2315    diffuse_contrib += pbr.diffuse;
2316  }
2317#endif
2318
2319  float4 lit = getLitColor(vertex_light_color, albedo, i.worldPos, normal,
2320      metallic, 1.0 - roughness, i.uv0, ao, /*enable_direct=*/true,
2321      diffuse_contrib, i, tdata);
2322
2323#if defined(_GIMMICK_FOG_00)
2324  {
2325    if (round(_Gimmick_Fog_00_Overlay_Mode)) {
2326      Fog00PBR pbr = __getFog00(i, tdata, mul(unity_WorldToObject, float4(i.worldPos, 1.0)).xyz, tdata.screen_uv);
2327      lit = pbr.albedo + lit * (1 - pbr.albedo.a);
2328    } else {
2329      Fog00PBR pbr = getFog00(i, tdata);
2330      albedo = pbr.albedo;
2331      depth = pbr.depth;
2332#if defined(_RENDERING_TRANSPARENT) || defined(_RENDERING_TRANSCLIPPING)
2333      albedo.rgb *= albedo.a;
2334#endif
2335      return albedo;
2336    }
2337  }
2338#endif
2339
2340#if defined(_GIMMICK_LENS_00)
2341  {
2342    // Use tdata.screen_uv to sample 8x8 Bayer matrix.
2343    //uint2 screen_uv_round = floor(tdata.screen_uv * _ScreenParams.xy * _Gimmick_Lens_00_Scale);
2344    //uint2 screen_uv_round = floor(tdata.screen_uv * _ScreenParams.xy * _Gimmick_Lens_00_Scale);
2345    uint2 glasses_uv_round = floor(i.uv0 * _ScreenParams.xy * _Gimmick_Lens_00_Scale);
2346    uint2 bayer_idx = (glasses_uv_round % 8);
2347    float2 grab_uv = i.grabPos.xy / i.grabPos.w;
2348    float3 grab_color = _Tooner_Grabpass.SampleLevel(linear_clamp_s, grab_uv, 0).rgb;
2349#if defined(_GIMMICK_LENS_00_BAYER)
2350    float mask = BayerM8x8[bayer_idx.y * 8 + bayer_idx.x];
2351    mask = frac(mask + frame * PHI * _Gimmick_Lens_00_Frame_Counter_Speed);
2352#elif defined(_GIMMICK_LENS_00_INTERLEAVED_GRADIENT_NOISE)
2353    float mask = ign(glasses_uv_round);
2354    mask = frac(mask + frame * PHI * _Gimmick_Lens_00_Frame_Counter_Speed);
2355#elif defined(_GIMMICK_LENS_00_SSFD)
2356    float3 mask = float3(
2357      ssfd(i.uv0, _Gimmick_Lens_00_SSFD_Scale / grab_color.r, _Gimmick_Lens_00_SSFD_Max_Fwidth, 0, _Gimmick_Lens_00_SSFD_Noise),
2358      ssfd(i.uv0, _Gimmick_Lens_00_SSFD_Scale / grab_color.g, _Gimmick_Lens_00_SSFD_Max_Fwidth, 0, _Gimmick_Lens_00_SSFD_Noise),
2359      ssfd(i.uv0, _Gimmick_Lens_00_SSFD_Scale / grab_color.b, _Gimmick_Lens_00_SSFD_Max_Fwidth, 0, _Gimmick_Lens_00_SSFD_Noise)
2360    );
2361    mask = mask > grab_color * _Gimmick_Lens_00_SSFD_Size_Factor ? 1 : 0;
2362#endif
2363
2364    //grab_uv = floor(grab_uv * _ScreenParams.xy * _Gimmick_Lens_00_Scale) / (_ScreenParams.xy * _Gimmick_Lens_00_Scale);
2365    grab_color = round(grab_color * _Gimmick_Lens_00_Subdivisions) / _Gimmick_Lens_00_Subdivisions;
2366    lit.rgb = (grab_color > mask);
2367    //lit.rgb = mask;
2368  }
2369#endif
2370
2371#if defined(_GIMMICK_FLAT_COLOR)
2372  if (round(_Gimmick_Flat_Color_Enable_Dynamic)) {
2373#if defined(_RENDERING_CUTOUT)
2374#if defined(_RENDERING_CUTOUT_STOCHASTIC)
2375    float ar = rand2(i.uv0);
2376    clip(albedo.a - ar);
2377#else
2378    clip(albedo.a - _Alpha_Cutoff);
2379#endif
2380    albedo.a = 1;
2381#endif
2382    return float4(lit.rgb +
2383        _Gimmick_Flat_Color_Emission * _Global_Emission_Factor,
2384        albedo.a);
2385  }
2386#endif
2387
2388  float4 result = lit;
2389#if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1)
2390  result.rgb += matcap_emission * _Global_Emission_Factor;
2391#endif
2392#if defined(_DECAL0) || defined(_DECAL1) || defined(_DECAL2) || defined(_DECAL3) || defined(_DECAL4) || defined(_DECAL5) || defined(_DECAL6) || defined(_DECAL7) || defined(_DECAL8) || defined(_DECAL9)
2393  result.rgb += decal_emission * _Global_Emission_Factor;
2394#endif
2395#if defined(_GLITTER)
2396  result.rgb += glitter_color_unlit * _Glitter_Brightness;
2397#endif
2398#if defined(_GIMMICK_DS2)
2399  result = ds2.fog + result * (1 - ds2.fog.a);
2400  result.rgb += ds2.emission * _Gimmick_DS2_Emission_Factor * ds2_mask;
2401#endif
2402
2403#if defined(_GIMMICK_FOG_01)
2404  [branch]
2405  if (_Gimmick_Fog_01_Overlay_Mode) {
2406    float4 fog_color = apply_fog(
2407      length(i.worldPos.xyz - getCenterCamPos()),
2408      _Gimmick_Fog_01_Density,
2409      normalize(i.worldPos.xyz - getCenterCamPos()),
2410      _Gimmick_Fog_01_Sun_Direction,
2411      _Gimmick_Fog_01_Sun_Color,
2412      _Gimmick_Fog_01_Sun_Exponent,
2413      _Gimmick_Fog_01_Sun_Color_2_Enable,
2414      _Gimmick_Fog_01_Sun_Color_2,
2415      _Gimmick_Fog_01_Sun_Exponent_2,
2416      _Gimmick_Fog_01_Color
2417    );
2418    result.xyz = fog_color * fog_color.a + result * (1 - fog_color.a);
2419  }
2420#endif
2421
2422#if defined(_ACES_FILMIC)
2423  result.rgb = aces_filmic(max(result.rgb, 0));
2424#endif
2425
2426  // This version exists for compatibility with the Bakery lightmapper. We
2427  // specifically need to expose _EmissionMap and _EmissionColor.
2428#if defined(_EMISSION)
2429  {
2430    float3 emission = _EmissionMap.SampleBias(linear_repeat_s, i.uv0, _Global_Sample_Bias);
2431    result.rgb += emission * _EmissionColor * _Global_Emission_Factor;
2432  }
2433#endif
2434#if defined(_EMISSION0)
2435  {
2436    float3 emission = _Emission0Tex.SampleBias(linear_repeat_s, get_uv_by_channel(i, round(_Emission0_UV_Select)), _Global_Sample_Bias);
2437    result.rgb += emission * _Emission0Color *
2438      _Global_Emission_Factor * _Emission0Multiplier;
2439  }
2440#endif
2441#if defined(_EMISSION1)
2442  {
2443    float3 emission = _Emission1Tex.SampleBias(linear_repeat_s, get_uv_by_channel(i, round(_Emission1_UV_Select)), _Global_Sample_Bias);
2444    result.rgb += emission * _Emission1Color *
2445      _Global_Emission_Factor * _Emission1Multiplier;
2446  }
2447#endif
2448#if defined(_RORSCHACH)
2449  result.rgb += rorschach_albedo.rgb * _Rorschach_Emission_Strength;
2450#endif
2451#if defined(_GIMMICK_LETTER_GRID)
2452  result.rgb += gimmick_letter_grid_emission;
2453#endif
2454#if defined(_GIMMICK_LETTER_GRID_2)
2455  result.rgb += gimmick_letter_grid_2_emission;
2456#endif
2457
2458#if defined(_EXPLODE) && defined(_AUDIOLINK)
2459  if (AudioLinkIsAvailable() && _Explode_Phase > 1E-6) {
2460    float4 al_color =
2461      AudioLinkData(
2462          ALPASS_CCLIGHTS +
2463          uint2(uint(i.uv0.x * 8) + uint(i.uv0.y * 16) * 8, 0 )).rgba;
2464    result = lerp(result, al_color, _Explode_Phase * _Explode_Phase);
2465  }
2466#endif
2467#if defined(_RENDERING_TRANSPARENT) || defined(_RENDERING_TRANSCLIPPING)
2468  result.rgb *= result.a;
2469#endif
2470  result.rgb += getOverlayEmission(ov, i) * _Global_Emission_Factor;
2471  result.rgb += _Global_Emission_Additive_Factor * albedo.rgb;
2472
2473#if defined(_SURFACE_STABLE_FRACTAL_DITHERING)
2474  [branch]
2475  if (_Surface_Stable_Fractal_Dithering_Enable_Dynamic) {
2476    float3 c = result.rgb * _Surface_Stable_Fractal_Dithering_Brightness_Factor;
2477    // Let's draw dots at the vertices of an equilateral triangle.
2478    // The internal angle is 60 degrees.
2479    // sin(60d) = sqrt(3) / 2
2480    // cos(60d) = 1 / 2
2481#if 1
2482    float3 mask = float3(
2483      ssfd(i.uv0, _Surface_Stable_Fractal_Dithering_Scale / c.r,
2484          _Surface_Stable_Fractal_Dithering_Max_Fwidth,
2485          _Surface_Stable_Fractal_Dithering_UV_Offset_R,
2486          _Surface_Stable_Fractal_Dithering_Noise),
2487      ssfd(i.uv0, _Surface_Stable_Fractal_Dithering_Scale / c.g,
2488          _Surface_Stable_Fractal_Dithering_Max_Fwidth,
2489          _Surface_Stable_Fractal_Dithering_UV_Offset_G,
2490          _Surface_Stable_Fractal_Dithering_Noise),
2491      ssfd(i.uv0, _Surface_Stable_Fractal_Dithering_Scale / c.b,
2492          _Surface_Stable_Fractal_Dithering_Max_Fwidth,
2493          _Surface_Stable_Fractal_Dithering_UV_Offset_B,
2494          _Surface_Stable_Fractal_Dithering_Noise)
2495    );
2496    float3 thresholded = lerp(0, 1, mask > 1 - c * _Surface_Stable_Fractal_Dithering_Size_Factor);
2497#else
2498    float cc = length(c) / sqrt(3);
2499    float mask = ssfd(i.uv0, _Surface_Stable_Fractal_Dithering_Scale / cc,
2500          _Surface_Stable_Fractal_Dithering_Max_Fwidth,
2501          0.8,
2502          _Surface_Stable_Fractal_Dithering_Noise);
2503    float3 thresholded = lerp(0, 1, mask > 1 - cc * _Surface_Stable_Fractal_Dithering_Size_Factor);
2504#endif
2505
2506    result.rgb = thresholded;
2507  }
2508#endif
2509
2510
2511  return result;
2512}
2513
2514fixed4 frag_debug(v2f i)
2515{
2516  float3 view_dir = normalize(_WorldSpaceCameraPos - i.worldPos);
2517  float3 indirect_specular = getIndirectSpecular(i, view_dir, i.normal,
2518      /*smoothness=*/1, /*metallic=*/0, i.worldPos);
2519  const float3 l = reflect(-view_dir, i.normal);
2520  const float3 h = normalize(l + view_dir);
2521  const float NoH = dot(i.normal, h);
2522  return float4(saturate(NoH) * indirect_specular, 1);
2523}
2524
2525fixed4 frag(v2f i
2526#if defined(EXPERIMENT__CUSTOM_DEPTH)
2527, out float depth: SV_DepthGreaterEqual
2528#endif
2529    ) : SV_Target
2530{
2531#if !defined(EXPERIMENT__CUSTOM_DEPTH)
2532  float depth;
2533#endif
2534  UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy);
2535  UNITY_SETUP_INSTANCE_ID(i);
2536  UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
2537
2538/*
2539#if defined(_TROCHOID)
2540  float3x3 vector_mover = cyl2_to_troch_jacobian(i.objPos_pre_trochoid);
2541  float det = determinant(vector_mover);
2542  det = saturate(abs(det));
2543  return float4(det, det, det, 1);
2544#endif
2545*/
2546
2547  return FILTER_COLOR(effect(i, depth));
2548}
2549
2550#endif  // TOONER_LIGHTING
2551