yum/3ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum/3ner

yumrandom touchups idk i just got hereecd59e8

master
13.2 KiB354 linesraw
1#ifndef __PBR_INC
2#define __PBR_INC
3
4#include "aperiodic_tiling.cginc"
5#include "burley.cginc"
6#include "custom31.cginc"
7#include "data.cginc"
8#include "decal.cginc"
9#include "filamented.cginc"
10#include "instancing.cginc"
11#include "interpolators.cginc"
12#include "letter_grid.cginc"
13#include "texture_utils.cginc"
14#include "triplanar.cginc"
15
16#if defined(_PARALLAX_HEIGHTMAP_TEXTURE) || defined(_BURLEY_TILING_HEIGHTMAP)
17float heightmap_sample(float2 uv) {
18  #if defined(_BURLEY_TILING_HEIGHTMAP)
19  float2 delta = (uv - _burley_ctx.base_uv) * _burley_ctx.uv_scale;
20  float4 s0 = _Burley_Tiling_Heightmap.SampleGrad(aniso4_trilinear_repeat_s,
21      _burley_ctx.patch_0.uv + mul(_burley_ctx.patch_0.uv_to_patch, delta),
22      _burley_ctx.patch_0.dx, _burley_ctx.patch_0.dy);
23  float4 s1 = _Burley_Tiling_Heightmap.SampleGrad(aniso4_trilinear_repeat_s,
24      _burley_ctx.patch_1.uv + mul(_burley_ctx.patch_1.uv_to_patch, delta),
25      _burley_ctx.patch_1.dx, _burley_ctx.patch_1.dy);
26  float4 s2 = _Burley_Tiling_Heightmap.SampleGrad(aniso4_trilinear_repeat_s,
27      _burley_ctx.patch_2.uv + mul(_burley_ctx.patch_2.uv_to_patch, delta),
28      _burley_ctx.patch_2.dx, _burley_ctx.patch_2.dy);
29  float4 blend = s0 * _burley_ctx.weights.x + s1 * _burley_ctx.weights.y + s2 * _burley_ctx.weights.z;
30  return burley_degaussianize(
31      _Burley_Tiling_Heightmap_LUT,
32      burley_apply_soft_clipping(blend.rgb, _burley_ctx.weights),
33      false).r;
34  #elif defined(_PARALLAX_HEIGHTMAP_TEXTURE)
35  return _Parallax_Heightmap.Sample(linear_repeat_s, uv * _Parallax_Heightmap_ST.xy + _Parallax_Heightmap_ST.zw).r;
36  #endif
37}
38#endif  // _PARALLAX_HEIGHTMAP_TEXTURE || _BURLEY_TILING_HEIGHTMAP
39
40#if defined(_PARALLAX_HEIGHTMAP)
41float2 parallax_offset(float2 uv, float3 view_dir_world, float3x3 tbn) {
42  float3 view_dir_tangent = mul(tbn, view_dir_world);
43  float view_z = max(view_dir_tangent.z, 1e-3f);
44  float2 uv_step = view_dir_tangent.xy / view_z * _Parallax_Heightmap_Scale;
45
46#if defined(_PARALLAX_HEIGHTMAP_RAY_MARCHING)
47  // Adapt steps by angle to keep cost down while preserving glancing detail.
48  float angle = saturate(view_z);
49  float base_steps = _Parallax_Heightmap_Ray_Marching_Steps;
50  float step_count = lerp(base_steps * 1.5, base_steps * 0.75, angle);
51  int step_count_i = (int)ceil(clamp(step_count, 2.0, max(base_steps, 2.0)));
52  float inv_step_count = rcp((float)step_count_i);
53
54  float2 delta_uv = uv_step * inv_step_count;
55  float delta_layer = inv_step_count;
56
57  float2 cur_uv = uv - uv_step * _Parallax_Heightmap_Bias;
58  float2 prev_uv = cur_uv;
59  float cur_layer = 0.0;
60  float sampled_height = heightmap_sample(cur_uv);
61
62  float prev_layer = cur_layer;
63
64  [loop]
65  for (int i = 0; i < step_count_i; i++) {
66    if (cur_layer >= sampled_height) break;
67
68    prev_layer = cur_layer;
69    prev_uv = cur_uv;
70
71    cur_uv += delta_uv;
72    cur_layer += delta_layer;
73    sampled_height = heightmap_sample(cur_uv);
74  }
75
76  // Short binary refine between last two samples to tighten the hit
77  float2 low_uv = prev_uv;
78  float low_layer = prev_layer;
79  float2 high_uv = cur_uv;
80  float high_layer = cur_layer;
81
82  [unroll(2)]
83  for (int j = 0; j < 2; j++) {
84    float2 mid_uv = 0.5 * (low_uv + high_uv);
85    float mid_layer = 0.5 * (low_layer + high_layer);
86    float mid_height = heightmap_sample(mid_uv);
87    if (mid_layer < mid_height) {
88      low_uv = mid_uv;
89      low_layer = mid_layer;
90    } else {
91      high_uv = mid_uv;
92      high_layer = mid_layer;
93    }
94  }
95
96  float2 refine_uv = 0.5 * (low_uv + high_uv);
97  return refine_uv - uv;
98#else
99  float height = heightmap_sample(uv) - _Parallax_Heightmap_Bias;
100  return uv_step * height;
101#endif
102}
103#endif  // _PARALLAX_HEIGHTMAP
104
105// Tokuyoshi and Kaplanyan 2019 "Improved Geometric Specular Antialiasing"
106float normalFiltering(float3 geometric_normal, float perceptual_roughness) {
107  float3 du = ddx(geometric_normal);
108  float3 dv = ddy(geometric_normal);
109
110  float variance = _Specular_AA_Variance * (dot(du, du) + dot(dv, dv));
111  float roughness = perceptual_roughness * perceptual_roughness;
112  float kernel_roughness = min(2.0f * variance, _Specular_AA_Threshold);
113  float square_roughness = saturate(roughness * roughness + kernel_roughness);
114
115  return saturate(sqrt(sqrt(square_roughness)));
116}
117
118void propagateSmoothness(inout Pbr pbr) {
119  pbr.smoothness = 1.0f - normalFiltering(pbr.normal, 1.0f - pbr.smoothness);
120
121  pbr.roughness_perceptual = clamp(1.0f - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1);
122  pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1);
123#if defined(_CLEARCOAT)
124  pbr.cc_roughness_perceptual = clamp(pbr.cc_roughness_perceptual, MIN_PERCEPTUAL_ROUGHNESS, 1);
125  pbr.cc_roughness_perceptual = normalFiltering(pbr.geometric_normal, pbr.cc_roughness_perceptual);
126  pbr.cc_roughness = max(MIN_ROUGHNESS, pbr.cc_roughness_perceptual * pbr.cc_roughness_perceptual);
127#endif
128}
129
130void apply_marble(float3 world_pos, inout float3 albedo) {
131#if defined(_MARBLE)
132  float3 uvw = world_pos * _Marble_Scale;
133
134  float3 offset = 0;
135#if defined(_MARBLE_TIME)
136  offset += _Time[0] * _Marble_Speed * _Marble_Direction;
137#endif
138#if defined(_MARBLE_OFFSET)
139  offset += _Marble_Offset;
140#endif
141
142  uvw += offset;
143
144  float3 noise = domain_warp_procedural(uvw, _Marble_Strength,
145      _Marble_Octaves, _Marble_Lacunarity, _Marble_Gain);
146
147  noise = _Marble_Post_Ramp.Sample(linear_clamp_s, float2(noise.x, 0));
148
149  albedo = noise;
150#endif
151}
152
153void apply_kintsugi(float3 world_pos, inout float3 albedo, inout float smoothness, inout float metallic) {
154#if defined(_KINTSUGI)
155  float3 uvw = world_pos * _Kintsugi_Scale;
156
157#if defined(_KINTSUGI_DOMAIN_WARPING)
158  float3 warp = domain_warp_procedural(
159      world_pos * _Kintsugi_Domain_Warping_Scale,
160      _Kintsugi_Domain_Warping_Strength, _Kintsugi_Domain_Warping_Octaves,
161      _Kintsugi_Domain_Warping_Lacunarity, _Kintsugi_Domain_Warping_Gain);
162  uvw += warp;
163#endif
164
165  float mask = 1.0f - voronoi_d_3d(uvw);
166  float width = max(fwidth(mask) * 0.5f, _Kintsugi_Width);
167  float threshold = _Kintsugi_Threshold;
168  mask = smoothstep(threshold - width, threshold + width, mask);
169
170#if defined(_KINTSUGI_NOISE_INVERT)
171  mask = 1.0f - mask;
172#endif  // _KINTSUGI_NOISE_INVERT
173
174  albedo = lerp(albedo, _Kintsugi_Color, mask);
175  smoothness = lerp(smoothness, _Kintsugi_Smoothness, mask);
176  metallic = lerp(metallic, _Kintsugi_Metallic, mask);
177#endif  // _KINTSUGI
178}
179
180void apply_letter_grid(v2f i, inout Pbr pbr) {
181#if defined(_LETTER_GRID)
182  LetterGridOutput lg = LetterGrid(i);
183  pbr.albedo.rgb = lerp(pbr.albedo.rgb, lg.albedo, lg.albedo.a);
184  pbr.metallic = lerp(pbr.metallic, lg.metallic, lg.albedo.a);
185  pbr.roughness = lerp(pbr.roughness, lg.roughness, lg.albedo.a);
186#if defined(FORWARD_BASE_PASS)
187  pbr.emission += lg.emission * lg.albedo.a;
188#endif
189#endif
190}
191
192void apply_burley_tiling(inout Pbr pbr, inout float3 normal_tangent) {
193#if defined(_BURLEY_TILING)
194  float3 weights = _burley_ctx.weights;
195
196#if defined(_BURLEY_TILING_MAINTEX)
197  float4 patch_0 = burley_sample_patch(_Burley_Tiling_Maintex, _burley_ctx.patch_0);
198  float4 patch_1 = burley_sample_patch(_Burley_Tiling_Maintex, _burley_ctx.patch_1);
199  float4 patch_2 = burley_sample_patch(_Burley_Tiling_Maintex, _burley_ctx.patch_2);
200  float4 gaussian_blend = patch_0 * weights.x + patch_1 * weights.y + patch_2 * weights.z;
201  pbr.albedo.xyz = burley_degaussianize(_Burley_Tiling_Maintex_LUT, burley_apply_soft_clipping(gaussian_blend.rgb, weights));
202#endif  // _BURLEY_TILING_MAINTEX
203
204#if defined(_BURLEY_TILING_SMOOTHNESS)
205  float4 patch_0_smoothness = burley_sample_patch(_Burley_Tiling_Smoothness_Map, _burley_ctx.patch_0);
206  float4 patch_1_smoothness = burley_sample_patch(_Burley_Tiling_Smoothness_Map, _burley_ctx.patch_1);
207  float4 patch_2_smoothness = burley_sample_patch(_Burley_Tiling_Smoothness_Map, _burley_ctx.patch_2);
208  float4 smoothness_blend = patch_0_smoothness * weights.x + patch_1_smoothness * weights.y + patch_2_smoothness * weights.z;
209  pbr.smoothness = burley_degaussianize(_Burley_Tiling_Smoothness_Map_LUT, burley_apply_soft_clipping(smoothness_blend, weights)).r;
210#if defined(_BURLEY_TILING_SMOOTHNESS_INVERT)
211  pbr.smoothness = 1.0f - pbr.smoothness;
212#endif  // _BURLEY_TILING_SMOOTHNESS_INVERT
213#endif  // _BURLEY_TILING_SMOOTHNESS
214
215#if defined(_BURLEY_TILING_NORMAL)
216  // TODO whiteout blending?
217  float4 patch_0_normal = burley_sample_patch(_Burley_Tiling_Normal_Map, _burley_ctx.patch_0);
218  float4 patch_1_normal = burley_sample_patch(_Burley_Tiling_Normal_Map, _burley_ctx.patch_1);
219  float4 patch_2_normal = burley_sample_patch(_Burley_Tiling_Normal_Map, _burley_ctx.patch_2);
220  float4 normal_blend = patch_0_normal * weights.x + patch_1_normal * weights.y + patch_2_normal * weights.z;
221  normal_tangent = burley_degaussianize(_Burley_Tiling_Normal_Map_LUT, burley_apply_soft_clipping(normal_blend.rgb, weights), false);
222  normal_tangent.xy = normal_tangent.xy * 2 - 1;
223  normal_tangent.xy *= _Burley_Tiling_Normal_Strength;
224  normal_tangent = normalize(normal_tangent);
225#endif  // _BURLEY_TILING_NORMAL
226#endif  // _BURLEY_TILING
227}
228
229void apply_zebra(float2 uv, inout float3 albedo, inout float3 normal_tangent) {
230#if defined(_ZEBRA)
231  //float theta = 0.25 * PI;
232  float theta = _Time[0] * 4;
233  //float theta = _Zebra_Angle * TAU;
234  uv.x *= _Zebra_X_Scale;
235  float st, ct;
236  sincos(theta, st, ct);
237  float4 phacelle = phacelle_noise_2d(uv * _Zebra_Scale, float2(ct, st));
238  float2 dir = phacelle.xy;
239  float mask = dot(dir, float2(0, 1));
240  float mask_fw = fwidth(mask);
241  albedo = smoothstep(-mask_fw * 0.5, mask_fw * 0.5, mask);
242  normal_tangent = normalize(float3(
243      mask * phacelle.zw * _Zebra_Normal_Strength, 1.0));
244#endif
245}
246
247Pbr getPbr(v2f i) {
248  Pbr pbr = (Pbr) 0;
249
250  float3 n = i.normal;
251  pbr.geometric_normal = n;
252  float3 t = i.tangent.xyz;
253  t = normalize(t - n * dot(n, t));  // Gram-Schmidt to avoid skew
254  float3 b = normalize(cross(n, t)) * i.tangent.w;
255  pbr.tbn = float3x3(t, b, n);
256
257#if defined(_UV_SCROLL)
258  i.uv01.xy += getTime() * _UV_Scroll_Speed;
259#endif  // _UV_SCROLL
260
261#if defined(_BURLEY_TILING)
262  burley_tiling_setup(i.uv01.xy);
263#endif
264
265#if defined(_PARALLAX_HEIGHTMAP)
266  float2 uv_parallax = i.uv01.xy + parallax_offset(i.uv01.xy, normalize(-i.eyeVec.xyz), pbr.tbn);
267#else
268  float2 uv_parallax = i.uv01.xy;
269#endif  // _PARALLAX_HEIGHTMAP
270
271#if defined(_BURLEY_TILING)
272  burley_tiling_setup(uv_parallax);
273#endif
274
275#if defined(_PARALLAX_HEIGHTMAP) || defined(_BURLEY_TILING_HEIGHTMAP)
276  pbr.height = heightmap_sample(uv_parallax);
277#endif
278
279#if defined(OUTLINES_PASS) && defined(_OUTLINES)
280  pbr.albedo = _Outlines_Color;
281#else
282  pbr.albedo = _MainTex.Sample(aniso4_trilinear_repeat_s, uv_parallax * _MainTex_ST.xy + _MainTex_ST.zw);
283  pbr.albedo *= _Color;
284#endif
285
286  float3 normal_tangent = UnpackNormal(_BumpMap.Sample(aniso4_trilinear_repeat_s, uv_parallax * _BumpMap_ST.xy));
287  normal_tangent.xy *= _BumpScale;
288
289#if defined(_DETAILS)
290  float2 detail_uv = get_uv_by_channel(i, _Details_UV_Channel);
291  float3 detail_normal = UnpackNormal(_DetailNormalMap.Sample(aniso4_trilinear_repeat_s, detail_uv * _DetailNormalMap_ST.xy));
292  detail_normal.xy *= _DetailNormalMapScale;
293  float detail_mask = _DetailMask.Sample(aniso4_trilinear_repeat_s, detail_uv * _DetailMask_ST.xy).r;
294  detail_normal.xy *= detail_mask;
295  normal_tangent = blendNormalsHill12(normal_tangent, detail_normal);
296#endif
297
298  float4 metallic_gloss = _MetallicGlossMap.Sample(aniso4_trilinear_repeat_s, uv_parallax * _MetallicGlossMap_ST.xy);
299  pbr.smoothness = metallic_gloss.a * _Glossiness;
300  pbr.metallic = metallic_gloss.r * _Metallic;
301
302  apply_marble(i.worldPos, pbr.albedo.xyz);
303  apply_kintsugi(i.worldPos, pbr.albedo.xyz, pbr.smoothness, pbr.metallic);
304  apply_letter_grid(i, pbr);
305  apply_burley_tiling(pbr, normal_tangent);
306  apply_triplanar_layers(i.worldPos, i.normal, pbr, normal_tangent);
307  apply_custom31_world(i, pbr, normal_tangent);
308  apply_aperiodic_tiling(i.uv01.xy, pbr.albedo.xyz, pbr.smoothness, normal_tangent);
309  apply_zebra(i.uv01.xy, pbr.albedo.xyz, normal_tangent);
310
311  applyDecals(i, pbr, normal_tangent);
312
313  pbr.normal = normalize(mul(normal_tangent, pbr.tbn));
314
315#if defined(_DEBUG_VIEW_TANGENT_SPACE_NORMALS)
316  pbr.tangent_normal = normal_tangent;
317#endif
318
319#if defined(_BENT_NORMALS)
320  float3 bent_ts = UnpackNormal(_Bent_Normals_Map.Sample(
321        aniso4_trilinear_repeat_s, uv_parallax * _Bent_Normals_Map_ST.xy +
322        _Bent_Normals_Map_ST.zw));
323  pbr.bent_normal = normalize(mul(bent_ts, pbr.tbn));
324#endif
325
326#if defined(_CLEARCOAT)
327  pbr.cc_roughness = _Clearcoat_Roughness;
328  pbr.cc_roughness_perceptual = sqrt(pbr.cc_roughness);
329  pbr.cc_strength = _Clearcoat_Strength;
330#if defined(_CLEARCOAT_NORMALS)
331  float3 cc_normal_ts = UnpackNormal(_Clearcoat_Normals.Sample(
332        aniso4_trilinear_repeat_s, uv_parallax * _Clearcoat_Normals_ST.xy +
333        _Clearcoat_Normals_ST.zw));
334  cc_normal_ts.xy *= _Clearcoat_Normals_Strength;
335  pbr.cc_normal = normalize(mul(cc_normal_ts, pbr.tbn));
336#else
337  pbr.cc_normal = i.normal;
338#endif  // _CLEARCOAT_NORMALS
339#endif  // _CLEARCOAT
340  propagateSmoothness(pbr);
341
342#if defined(_EMISSIONS) && defined(FORWARD_BASE_PASS)
343  float3 emission_tint = _EmissionColor;
344  float3 emission_color = _EmissionMap.Sample(trilinear_repeat_s,
345      i.uv01.xy * _EmissionMap_ST.xy + _EmissionMap_ST.zw);
346  float emission_mask = _EmissionMask.Sample(trilinear_repeat_s,
347      i.uv01.xy * _EmissionMask_ST.xy + _EmissionMask_ST.zw).r;
348  pbr.emission = emission_tint * emission_color * emission_mask;
349#endif
350
351  return pbr;
352}
353
354#endif  // __PBR_INC