yum-archive/2ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum-archive/2ner

yumAdd anisotropic reflectionsd0c27e8

master
11.6 KiB338 linesraw
1#ifndef __YUM_PBR
2#define __YUM_PBR
3
4#include "cnlohr.cginc"
5#include "data.cginc"
6#include "decals.cginc"
7#include "features.cginc"
8#include "filamented.cginc"
9#include "glitter.cginc"
10#include "globals.cginc"
11#include "math.cginc"
12#include "oklab.cginc"
13#include "texture_utils.cginc"
14
15void propagateRoughness(in float smoothness, out float roughness_perceptual, out float roughness) {
16  roughness_perceptual = normalFiltering(1.0 - smoothness, float3(0, 0, 1));
17  roughness = roughness_perceptual * roughness_perceptual;
18}
19
20// Shitty hacky filtering, not in any way robust or mathematically sound.
21void filterGradient(v2f i, inout float2 g)
22{
23  float3 normal = normalize(float3(-g.x, 1.0f, -g.y));
24  float dn = length(fwidth(normal));
25  g *= saturate(0.05 / dn);
26}
27
28#if defined(_GRADIENT_NORMALS)
29void applyGradientNormals(v2f i, inout YumPbr pbr) {
30  float2 uv = i.uv01.xy;
31
32  // Math lifted from "Ocean waves simulation with Fast Fourier transform" by
33  // Jump Trajectory.
34  float2 gradient = 0;
35
36#if defined(_GRADIENT_NORMALS_0_VERTICAL)
37  float2 g0_uv = uv * _Gradient_Normals_0_Vertical_ST.xy;
38  float2 g0_dfy = _Gradient_Normals_0_Vertical.SampleLevel(bilinear_repeat_s, g0_uv, 0).rg;
39  float2 g0 = g0_dfy;
40#if defined(_GRADIENT_NORMALS_0_HORIZONTAL)
41  float2 g0_dfxz = _Gradient_Normals_0_Horizontal.SampleLevel(bilinear_repeat_s, g0_uv, 0).rg;
42  g0 = float2(
43      g0_dfy[0] / (1 + g0_dfxz[0]),
44      g0_dfy[1] / (1 + g0_dfxz[1])
45      );
46  filterGradient(i, g0);
47#endif  // _GRADIENT_NORMALS_0_HORIZONTAL
48  gradient += g0;
49#endif  // _GRADIENT_NORMALS_0_VERTICAL
50
51#if defined(_GRADIENT_NORMALS_1_VERTICAL)
52  float2 g1_uv = uv * _Gradient_Normals_1_Vertical_ST.xy;
53  float2 g1_dfy = _Gradient_Normals_1_Vertical.SampleLevel(bilinear_repeat_s, g1_uv, 0).rg;
54  float2 g1 = g1_dfy;
55#if defined(_GRADIENT_NORMALS_1_HORIZONTAL)
56  float2 g1_dfxz = _Gradient_Normals_1_Horizontal.SampleLevel(bilinear_repeat_s, g1_uv, 0).rg;
57  g1 = float2(
58      g1_dfy[0] / (1 + g1_dfxz[0]),
59      g1_dfy[1] / (1 + g1_dfxz[1])
60      );
61  filterGradient(i, g1);
62#endif  // _GRADIENT_NORMALS_1_HORIZONTAL
63  gradient += g1;
64#endif  // _GRADIENT_NORMALS_1_VERTICAL
65
66#if defined(_GRADIENT_NORMALS_2_VERTICAL)
67  float2 g2_uv = uv * _Gradient_Normals_2_Vertical_ST.xy;
68  float2 g2_dfy = _Gradient_Normals_2_Vertical.SampleLevel(bilinear_repeat_s, g2_uv, 0).rg;
69  float2 g2 = g2_dfy;
70#if defined(_GRADIENT_NORMALS_2_HORIZONTAL)
71  float2 g2_dfxz = _Gradient_Normals_2_Horizontal.SampleLevel(bilinear_repeat_s, g2_uv, 0).rg;
72  g2 = float2(
73      g2_dfy[0] / (1 + g2_dfxz[0]),
74      g2_dfy[1] / (1 + g2_dfxz[1])
75      );
76#endif  // _GRADIENT_NORMALS_2_HORIZONTAL
77  gradient += g2;
78#endif  // _GRADIENT_NORMALS_2_VERTICAL
79
80#if defined(_GRADIENT_NORMALS_3_VERTICAL)
81  float2 g3_uv = uv * _Gradient_Normals_3_Vertical_ST.xy;
82  float2 g3_dfy = _Gradient_Normals_3_Vertical.SampleLevel(bilinear_repeat_s, g3_uv, 0).rg;
83  float2 g3 = g3_dfy;
84#if defined(_GRADIENT_NORMALS_3_HORIZONTAL)
85  float2 g3_dfxz = _Gradient_Normals_3_Horizontal.SampleLevel(bilinear_repeat_s, g3_uv, 0).rg;
86  g3 = float2(
87      g3_dfy[0] / (1 + g3_dfxz[0]),
88      g3_dfy[1] / (1 + g3_dfxz[1])
89      );
90  filterGradient(i, g2);
91#endif  // _GRADIENT_NORMALS_3_HORIZONTAL
92
93  gradient += g3;
94#endif  // _GRADIENT_NORMALS_3_VERTICAL
95
96  float3 gradient_normal = normalize(float3(-gradient.x, 1.0f, -gradient.y));
97
98  pbr.normal = gradient_normal;
99}
100#endif
101
102#if defined(_SEA_FOAM)
103void applySeaFoam(v2f i, inout YumPbr pbr) {
104  float2 uv = i.uv01.xy;
105
106  float4 slope = 0;
107
108  #if defined(_SEA_FOAM_0)
109    slope += _Sea_Foam_0_Slope.SampleLevel(bilinear_repeat_s, uv * _Sea_Foam_0_Slope_ST.xy, 0);
110  #endif
111  #if defined(_SEA_FOAM_1)
112    slope += _Sea_Foam_1_Slope.SampleLevel(bilinear_repeat_s, uv * _Sea_Foam_1_Slope_ST.xy, 0);
113  #endif
114  #if defined(_SEA_FOAM_2)
115    slope += _Sea_Foam_2_Slope.SampleLevel(bilinear_repeat_s, uv * _Sea_Foam_2_Slope_ST.xy, 0);
116  #endif
117  #if defined(_SEA_FOAM_3)
118    slope += _Sea_Foam_3_Slope.SampleLevel(bilinear_repeat_s, uv * _Sea_Foam_3_Slope_ST.xy, 0);
119  #endif
120
121  float dfx_dx = slope[0];
122  float dfy_dy = slope[1];
123  float dfx_dy = slope[3];
124
125  float Jxx = 1 + dfx_dx * _Sea_Foam_Lambda;
126  float Jyy = 1 + dfy_dy * _Sea_Foam_Lambda;
127  float Jxy = dfx_dy * _Sea_Foam_Lambda;
128
129  float det = Jxx * Jyy - Jxy * Jxy;
130  float foam_contribution = det;
131  foam_contribution += _Sea_Foam_Bias;
132  foam_contribution = saturate(foam_contribution);
133
134  pbr.albedo.rgb = lerp(pbr.albedo.rgb, _Sea_Foam_Color.rgb, foam_contribution * _Sea_Foam_Color.a);
135  pbr.smoothness = lerp(pbr.smoothness, 1.0f - _Sea_Foam_Roughness, foam_contribution);
136  propagateRoughness(pbr.smoothness, pbr.roughness_perceptual, pbr.roughness);
137}
138#endif
139
140// Returns fur thickness on [0, 1], 0 = no fur, 1 = max fur.
141float FurClip(v2f i, f2f f, inout YumPbr result) {
142#if defined(_FUR)
143  float fur_layer = i.vertexLight.w;
144  float2 fur_uv = i.uv01.xy * _Fur_Heightmap_ST.xy;
145
146#if defined(_FUR_WARPING)
147  float2 vnoise = valueNoise3D(i.objPos * _Fur_Warping_Frequency) * 2 - 1;
148  float3 vnoise_tbn = mul(vnoise, f.tbn);
149  fur_uv += vnoise_tbn.xy * (_Fur_Warping_Strength / _Fur_Warping_Frequency);
150#endif
151
152  float fur_thickness = _Fur_Heightmap.SampleBias(
153      trilinear_aniso4_repeat_s, fur_uv,
154      _Fur_Heightmap_Mip_Bias).r;
155  fur_thickness = tone(fur_thickness, _Fur_Thickness_Power);
156  clip(fur_thickness - fur_layer);
157  return fur_thickness;
158#else
159  return 0;
160#endif
161}
162
163YumPbr GetYumPbr(v2f i, f2f f) {
164  YumPbr result = (YumPbr)0;
165
166  float fur_thickness = FurClip(i, f, result);
167
168  float2 raw_uv = i.uv01.xy;
169#if defined(_UV_DOMAIN_WARPING)
170  {
171    float2 warped_uv = raw_uv;
172    float amplitude = _UV_Domain_Warping_Spatial_Strength;
173    float frequency = _UV_Domain_Warping_Spatial_Scale;
174
175    float2 speed_direction = _UV_Domain_Warping_Spatial_Direction;
176    float2 time_offset = speed_direction * _Time.y * _UV_Domain_Warping_Spatial_Speed;
177
178    const float lacunarity = 2.0;
179    const float persistence = 0.5;
180
181    [loop]
182    for (uint ii = 0; ii < _UV_Domain_Warping_Spatial_Octaves; ii++) {
183      float2 noise_uv = warped_uv * frequency + time_offset;
184      float2 offset_sample = _UV_Domain_Warping_Noise.SampleLevel(trilinear_repeat_s, noise_uv, 0).rg;
185      offset_sample = (offset_sample * 2.0 - 1.0);
186      warped_uv += offset_sample * amplitude;
187      frequency *= lacunarity;
188      amplitude *= persistence;
189    }
190    i.uv01.xy = warped_uv;
191  }
192#endif
193
194#if defined(OUTLINE_PASS)
195  result.albedo = _Outline_Color;
196  result.albedo.a *= tex2D(_MainTex,
197      UV_SCOFF(i, _MainTex_ST, /*which_channel=*/0)).a;
198#else
199  result.albedo = tex2D(_MainTex,
200      UV_SCOFF(i, _MainTex_ST, /*which_channel=*/0)) * _Color;
201#endif
202
203#if defined(_3D_SDF)
204  {
205    float2 sdf_uv_raw = get_uv_by_channel(i, _3D_SDF_UV_Channel);
206    float3 sdf_uv = float3(sdf_uv_raw, _3D_SDF_Z + _Time.y * _3D_SDF_Z_Speed);
207    sdf_uv.xy = saturate((sdf_uv.xy - (_3D_SDF_ST.zw + 0.5)) * _3D_SDF_ST.xy + (_3D_SDF_ST.zw + 0.5));
208    float sdf_value = _3D_SDF_Texture.SampleLevel(trilinear_repeat_s, sdf_uv, 0).r;
209    float eps = 1E-4;
210    float4 is_lit = sdf_value < _3D_SDF_Thresholds && sdf_uv.x > eps && sdf_uv.x < 1 - eps && sdf_uv.y > eps && sdf_uv.y < 1 - eps;
211    float4 skin_albedo = result.albedo;
212    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_3.rgb, _3D_SDF_Color_3.a), is_lit.w);
213    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_2.rgb, _3D_SDF_Color_2.a), is_lit.z);
214    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_1.rgb, _3D_SDF_Color_1.a), is_lit.y);
215    result.albedo.rgb = lerp(result.albedo.rgb, lerp(skin_albedo.rgb, _3D_SDF_Color_0.rgb, _3D_SDF_Color_0.a), is_lit.x);
216  }
217#endif
218
219  float3 normal_tangent = UnpackScaleNormal(
220      tex2D(_BumpMap, UV_SCOFF_IMPL(raw_uv, _BumpMap_ST)), _BumpScale);
221
222#if defined(_DETAIL_MAPS)
223  float2 detail_uv = get_uv_by_channel(i, _Detail_Maps_UV_Channel);
224  float detail_mask = _DetailMask.SampleLevel(point_repeat_s, detail_uv, 0);
225  float4 detail_albedo = tex2D(_DetailAlbedoMap,
226      UV_SCOFF_IMPL(detail_uv, _DetailAlbedoMap_ST));
227  float3 detail_normal = UnpackScaleNormal(
228      tex2D(_DetailNormalMap,
229          UV_SCOFF_IMPL(detail_uv, _DetailNormalMap_ST)),
230      _DetailNormalMapScale);
231  result.albedo = lerp(result.albedo, result.albedo * detail_albedo, detail_mask);
232  //result.albedo.a *= detail_albedo.a;
233  normal_tangent = lerp(normal_tangent, blendNormalsHill12(normal_tangent, detail_normal), detail_mask);
234#endif
235
236#if defined(_ALPHA_MULTIPLIER)
237  result.albedo.a = saturate(result.albedo.a * _Alpha_Multiplier);
238#endif
239
240#if defined(FORWARD_BASE_PASS)
241#if defined(_EMISSION)
242  result.emission = tex2D(_EmissionMap, UV_SCOFF(i, _EmissionMap_ST, /*which_channel=*/0)) * _EmissionColor;
243#endif
244#if defined(OUTLINE_PASS)
245  result.emission += _Outline_Color * _Outline_Emission;
246#endif
247#endif  // FORWARD_BASE_PASS
248
249#if defined(_METALLICS)
250  float4 metallic_gloss = tex2D(_MetallicGlossMap, UV_SCOFF(i, _MetallicGlossMap_ST, /*which_channel=*/0));
251  float metallic = metallic_gloss.r * _Metallic;
252  float smoothness = metallic_gloss.a * _Smoothness;
253
254  result.smoothness = smoothness;
255  result.metallic = metallic;
256#else
257  result.smoothness = 0.2;
258  result.metallic = 0;
259#endif
260
261#if defined(_AMBIENT_OCCLUSION)
262  result.ao = lerp(1, tex2D(_OcclusionMap, i.uv01), _OcclusionStrength);
263  result.ao = saturate(result.ao);
264#else
265  result.ao = 1;
266#endif
267
268#if defined(_FUR)
269  result.ao = lerp(result.ao, result.ao * fur_thickness, _Fur_AO_Strength);
270#endif
271
272  applyDecals(i, result.albedo, normal_tangent, result.metallic, result.smoothness, result.emission);
273  const float min_roughness_perceptual = 0.045f;
274  result.smoothness = min(1.0f - min_roughness_perceptual, result.smoothness);
275  propagateRoughness(result.smoothness, result.roughness_perceptual, result.roughness);
276
277#if defined(_OKLCH_CORRECTION)
278  float3 lch = LRGBtoOKLCH(result.albedo.rgb);
279  lch.x = lch.x * _Oklch_Correction_L;
280  lch.y = lch.y * _Oklch_Correction_C;
281  lch.z = lch.z * _Oklch_Correction_H;
282  result.albedo.rgb = OKLCHtoLRGB(lch);
283#endif
284
285#if defined(_OKLAB_BRIGHTNESS_CLAMP)
286  float3 lab = LRGBtoOKLAB(result.albedo.rgb);
287  lab.x = clamp(lab.x, _Oklab_Brightness_Clamp_Min, _Oklab_Brightness_Clamp_Max);
288  result.albedo.rgb = OKLABtoLRGB(lab);
289#endif
290
291  result.normal = normalize(mul(normal_tangent, f.tbn));
292
293#if defined(_GRADIENT_NORMALS)
294  applyGradientNormals(i, result);
295#endif
296#if defined(_SEA_FOAM)
297  applySeaFoam(i, result);
298#endif
299
300#if (defined(FORWARD_BASE_PASS) || defined(FORWARD_ADD_PASS)) && defined(_GLITTER)
301  GlitterParams glitter_p;
302  glitter_p.color = _Glitter_Color;
303  glitter_p.uv_channel = _Glitter_UV_Channel;
304  glitter_p.layers = _Glitter_Layers;
305  glitter_p.cell_size = _Glitter_Grid_Size;
306  glitter_p.size = _Glitter_Size;
307  glitter_p.major_minor_ratio = _Glitter_Major_Minor_Ratio;
308  glitter_p.angle_randomization_range = _Glitter_Angle_Randomization_Range;
309  glitter_p.center_randomization_range = _Glitter_Center_Randomization_Range;
310  glitter_p.size_randomization_range = _Glitter_Size_Randomization_Range;
311  glitter_p.existence_chance = _Glitter_Existence_Chance;
312#if defined(_FUR)
313  glitter_p.seed = floor(i.vertexLight.w * _Fur_Layers);
314#else
315  glitter_p.seed = 0;
316#endif
317#if defined(_GLITTER_ANGLE_LIMIT)
318  glitter_p.angle_limit = _Glitter_Angle_Limit;
319  glitter_p.angle_limit_transition_width = _Glitter_Angle_Limit_Transition_Width;
320#endif
321#if defined(_GLITTER_MASK)
322  glitter_p.mask = _Glitter_Mask.SampleLevel(linear_repeat_s, i.uv01.xy, 0);
323#endif
324  float4 glitter_albedo = getGlitter(i, f, glitter_p, result.normal);
325  result.albedo = alphaBlend(result.albedo, glitter_albedo);
326
327  result.emission += glitter_albedo.rgb * glitter_albedo.a * _Glitter_Emission;
328#endif
329
330#if defined(_ANISOTROPY)
331  result.binormal = normalize(cross(result.normal, i.tangent.xyz) * i.tangent.w);
332#endif
333
334  return result;
335}
336
337#endif
338