yum-archive/2ner

A toon shader for Unity's BIRP.

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

yumwork on fog & custom30 stuff715bf39

master
11.1 KiB402 linesraw
1#ifndef __CUSTOM30_INC
2#define __CUSTOM30_INC
3
4#include "globals.cginc"
5#include "math.cginc"
6#include "pema99.cginc"
7#include "quilez.cginc"
8#include "interpolators.cginc"
9#include "texture_utils.cginc"
10
11#if defined(_CUSTOM30)
12
13#if defined(_DEPTH_PREPASS)
14#define CUSTOM30_MAX_STEPS 10
15#else
16#define CUSTOM30_MAX_STEPS 30
17#endif
18
19struct Custom30Output {
20  float3 objPos;
21  float3 normal;
22  float depth;
23};
24
25float3 GetFragToOrigin(v2f i) {
26  return (i.color * 2.0f - 1.0f) / i.color.a;
27}
28
29float4 GetRotation(v2f i, float2 uv_channels) {
30  float4 quat;
31  quat.xy = get_uv_by_channel(i, uv_channels.x);
32  quat.zw = get_uv_by_channel(i, uv_channels.y);
33  return quat;
34}
35
36float cut_with_box(float3 p, float d, float3 box_size) {
37  float2 pp_xy = p.xy;
38  float2 pp_xz = p.xz;
39  float2 pp_yz = p.yz;
40
41  // Rotate by 45 degrees
42  pp_xy = rot45(pp_xy);
43  d = max(d, distance_from_box(float3(pp_xy, p.z), box_size));
44
45  pp_xz = rot45(pp_xz);
46  d = max(d, distance_from_box(float3(pp_xz, p.y), box_size));
47
48  pp_yz = rot45(pp_yz);
49  d = max(d, distance_from_box(float3(pp_yz, p.x), box_size));
50
51  return d;
52}
53
54float distance_from_hex_comb(
55    float3 p,
56    float3 period,
57    float hex_sc,
58    float zoff,
59    float count) {
60  float3 p_hex = cart_to_hex(p.xy);
61
62  float half_period = period * 0.5;
63  float3 which = abs(floor((p_hex + half_period) / period));
64
65  // The original code here was this:
66  //   p_hex = glsl_mod(p_hex + half_period, period) - half_period;
67  //
68  // But you can simplify it. Given the definition of glsl_mod:
69  //   #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y))))
70  //
71  // You can plug in terms:
72  //  (p_hex + half_period) - (period) * floor((p_hex + half_period) / period)
73  //  = p_hex + half_period - period * floor(p_hex/period + 0.5)
74  //
75  // For all x,
76  //  round(x) = floor(x + 0.5)
77  //
78  // Continuing to simplify:
79  //  (p_hex + half_period - period * round(p_hex/period)) - half_period
80  //  = p_hex - period * round(p_hex / period)
81  p_hex = p_hex - period * round(p_hex / period);
82
83  p.xy = hex_to_cart(p_hex);
84
85  float hex_d = distance_from_hex_prism(p -
86      float3(0, 0, zoff), hex_sc);
87  hex_d = any(which > count) ? 1E9 : hex_d;
88  return hex_d;
89}
90
91float distance_from_hex_grid(
92    float3 p,
93    float2 period,
94    float hex_sc,
95    float zoff,
96    float count) {
97  float half_period = period * 0.5;
98  float2 which = abs(floor((p.xy + half_period) / period));
99  p.xy = glsl_mod(p.xy + half_period, period) - half_period;
100
101  float hex_d = distance_from_hex_prism(p -
102      float3(0, 0, zoff), hex_sc);
103  hex_d = any(which > count) ? 1E9 : hex_d;
104  hex_d = any(which % 2 == 0) ? 1E9 : hex_d;
105  return hex_d;
106}
107
108#if defined(_CUSTOM30_BASICCUBE)
109float BasicCube_map(float3 p) {
110  float box_d = distance_from_box_frame(p, .995, .15);
111  float core_dim = 0.95;
112  float core_d = distance_from_box(p, core_dim);
113  float d = min(box_d, core_d);
114
115#if defined(_CUSTOM30_BASICCUBE_CHAMFER)
116  d = cut_with_box(p, d, 1.3);
117#endif
118
119#if defined(_CUSTOM30_BASICCUBE_HEX_GRIP)
120  [branch]
121  {
122    float period = 0.1;
123    float hex_sc = period * 0.2;
124    float count = 13;
125
126    float zoff = core_dim - (hex_sc * 0.2);
127
128    float3 pp = abs(p);
129    pp = pp.z > pp.x && pp.z > pp.y ? pp.xyz : pp;
130    pp = pp.y > pp.x && pp.y > pp.z ? pp.zxy : pp;
131    pp = pp.x > pp.y && pp.x > pp.z ? pp.yzx : pp;
132
133    float hex_d = distance_from_hex_comb(pp, period, hex_sc, zoff, count);
134    hex_d = any(pp.xy > 0.85) ? 1E9 : hex_d;
135    d = min(d, hex_d);
136  }
137#endif
138
139#if defined(_CUSTOM30_BASICCUBE_HEX_BOLTS)
140  {
141    float period = 0.83;
142    float hex_sc = period * 0.1;
143    float count = 3;
144
145    float zoff = core_dim;
146
147    float3 pp = abs(p);
148    pp = pp.z > pp.x && pp.z > pp.y ? pp.xyz : pp;
149    pp = pp.y > pp.x && pp.y > pp.z ? pp.zxy : pp;
150    pp = pp.x > pp.y && pp.x > pp.z ? pp.yzx : pp;
151    d = min(d, distance_from_hex_grid(pp, period, hex_sc, zoff, count));
152  }
153#endif
154
155  return d;
156}
157
158float3 BasicCube_normal(float3 p) {
159  float3 fw = fwidth(p);
160  float epsilon = length(fw) * 0.5f;
161  float center_d = BasicCube_map(p);
162  float3 n = float3(
163    BasicCube_map(p + float3(epsilon, 0, 0)) - center_d,
164    BasicCube_map(p + float3(0, epsilon, 0)) - center_d,
165    BasicCube_map(p + float3(0, 0, epsilon)) - center_d);
166  return normalize(n);
167}
168
169Custom30Output BasicCube(v2f i) {
170  float3 obj_space_camera_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
171  float3 frag_to_origin = GetFragToOrigin(i);
172
173	float2 uv_channels = float2(_Custom30_Quaternion_UV_Channel_0, _Custom30_Quaternion_UV_Channel_1);
174  float4 quat = GetRotation(i, uv_channels);
175  float4 iquat = float4(-quat.xyz, quat.w);
176
177  float3 ro = -frag_to_origin;
178  float3 rd = normalize(i.objPos - obj_space_camera_pos);
179  rd = rotate_vector(rd, iquat);
180
181#if defined(_CUSTOM30_BASICCUBE_HEX_BOLTS)
182  float3 n = rotate_vector(normalize(mul(unity_WorldToObject, i.normal)), iquat);
183  // Get projected length of rd on normal.
184  float rd_proj_len = dot(rd, n);
185  // Move ray enough to give us `ro_Offset` gap.
186  ro += rd * _Custom30_ro_Offset / rd_proj_len;
187#endif
188
189  float epsilon = 5e-3f;
190  float d;
191  float d_acc = 0;
192  // 1.73... = sqrt(3)
193  // our cube has an edge length of 2, so mult by 2
194  float max_d = 1.73205081f * 2.0f;
195
196  uint ii = 0;
197
198  [loop]
199  for (; ii < CUSTOM30_MAX_STEPS; ++ii) {
200    float3 p = ro + rd * d_acc;
201    d = BasicCube_map(p);
202    d_acc += d;
203    if (d < epsilon) break;
204    if (d_acc > max_d) break;
205  }
206
207  float3 localHit = ro + rd * d_acc;
208
209  Custom30Output o;
210#if !defined(_DEPTH_PREPASS)
211  clip(epsilon - d);
212#endif
213  float3 objHit = rotate_vector(localHit, quat);
214  float3 objCenterOffset = rotate_vector(frag_to_origin, quat);
215
216  o.objPos = objHit + (i.objPos + objCenterOffset);
217  float4 clipPos = UnityObjectToClipPos(o.objPos);
218  o.depth = clipPos.z / clipPos.w;
219
220  float3 sdfNormal = BasicCube_normal(localHit);
221  float3 objNormal = rotate_vector(sdfNormal, quat);
222  o.normal = UnityObjectToWorldNormal(objNormal);
223
224  return o;
225}
226#endif
227
228#if defined(_CUSTOM30_BASICWEDGE)
229float BasicWedge_map(float3 p) {
230  float box_d = distance_from_box(p, float3(1, 1, 1));
231  float cut_plane_d = distance_from_plane(p - float3(0, 0, 0), -normalize(float3(1, 0, 1)), 0);
232
233  float d = op_sub(box_d, cut_plane_d);
234
235  return d;
236}
237
238float3 BasicWedge_normal(float3 p) {
239  float3 fw = fwidth(p);
240  float epsilon = max((fw.x+fw.y+fw.z) * 0.5f, 5e-3f);
241  float center_d = BasicWedge_map(p);
242  float3 n = float3(
243    BasicWedge_map(p + float3(epsilon, 0, 0)) - center_d,
244    BasicWedge_map(p + float3(0, epsilon, 0)) - center_d,
245    BasicWedge_map(p + float3(0, 0, epsilon)) - center_d);
246  return normalize(n);
247}
248
249Custom30Output BasicWedge(v2f i) {
250  float3 obj_space_camera_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
251  float3 frag_to_origin = GetFragToOrigin(i);
252
253	float2 uv_channels = float2(_Custom30_Quaternion_UV_Channel_0, _Custom30_Quaternion_UV_Channel_1);
254  float4 quat = GetRotation(i, uv_channels);
255  float4 iquat = float4(-quat.xyz, quat.w);
256
257  float3 frag_to_origin_obj = rotate_vector(frag_to_origin, iquat);
258  float3 origin = i.objPos + frag_to_origin_obj;
259  float3 objSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
260  float distance_from_camera_obj = length(objSpaceCameraPos - origin);
261
262  float3 ro = -frag_to_origin;
263  float3 rd = normalize(i.objPos - obj_space_camera_pos);
264  rd = rotate_vector(rd, iquat);
265
266  ro -= rd * _Custom30_ro_Offset;
267
268  float d;
269  float d_acc = 0;
270  float epsilon = 5e-3f;
271  // 1.73... = sqrt(3)
272  // our cube has an edge length of 2, so mult by 2
273  float max_d = 1.73205081f * 2.0f;
274
275  uint ii = 0;
276
277  [loop]
278  for (; ii < CUSTOM30_MAX_STEPS; ++ii) {
279    float3 p = ro + rd * d_acc;
280    d = BasicWedge_map(p);
281    d_acc += d;
282    if (d < epsilon) break;
283    if (d_acc > max_d) break;
284  }
285
286  Custom30Output o;
287#if !defined(_DEPTH_PREPASS)
288  clip(epsilon - d);
289#endif
290  float3 localHit = ro + rd * d_acc;
291  float3 objHit = rotate_vector(localHit, quat);
292  float3 objCenterOffset = rotate_vector(frag_to_origin, quat);
293
294  o.objPos = objHit + (i.objPos + objCenterOffset);
295  float4 clipPos = UnityObjectToClipPos(o.objPos);
296  o.depth = clipPos.z / clipPos.w;
297
298  float3 sdfNormal = BasicWedge_normal(localHit);
299  float3 objNormal = rotate_vector(sdfNormal, quat);
300  o.normal = UnityObjectToWorldNormal(objNormal);
301
302  return o;
303}
304#endif
305
306#if defined(_CUSTOM30_BASICPLATFORM)
307float BasicPlatform_map(float3 p) {
308  p = abs(p.zyx);
309
310  float3 platform_size = _Custom30_BasicPlatform_Size;
311  float box_d = distance_from_box_frame(p, platform_size, _Custom30_BasicPlatform_Frame_D);
312  float core_d = distance_from_box(p, platform_size - _Custom30_BasicPlatform_Core_D);
313  float d = min(box_d, core_d);
314
315#if defined(_CUSTOM30_BASICPLATFORM_CHAMFER)
316  {
317    float3 pp = p;
318    pp.yz = float2(RCP_SQRT_2 * p.y - RCP_SQRT_2 * p.z, RCP_SQRT_2 * p.y + RCP_SQRT_2 * p.z);
319    float c = _Custom30_BasicPlatform_Chamfer_Size.x;
320    d = max(d, distance_from_box(pp, float3(1.0, c, c)));
321  }
322  {
323    float3 pp = p;
324    pp.xz = float2(RCP_SQRT_2 * p.x - RCP_SQRT_2 * p.z, RCP_SQRT_2 * p.x + RCP_SQRT_2 * p.z);
325    float c = _Custom30_BasicPlatform_Chamfer_Size.y;
326    d = max(d, distance_from_box(pp, float3(c, 1.0, c)));
327  }
328  {
329    float3 pp = p;
330    pp.xy = float2(RCP_SQRT_2 * p.x - RCP_SQRT_2 * p.y, RCP_SQRT_2 * p.x + RCP_SQRT_2 * p.y);
331    float c = _Custom30_BasicPlatform_Chamfer_Size.z;
332    d = max(d, distance_from_box(pp, float3(c, c, 1.0)));
333  }
334#endif
335
336  return d;
337}
338
339float3 BasicPlatform_normal(float3 p) {
340  float3 fw = fwidth(p);
341  float epsilon = max((fw.x+fw.y+fw.z) * 0.5f, 5e-3f);
342  float center_d = BasicPlatform_map(p);
343  float3 n = float3(
344    BasicPlatform_map(p + float3(epsilon, 0, 0)) - center_d,
345    BasicPlatform_map(p + float3(0, epsilon, 0)) - center_d,
346    BasicPlatform_map(p + float3(0, 0, epsilon)) - center_d);
347  return normalize(n);
348}
349
350Custom30Output BasicPlatform(v2f i) {
351  float3 obj_space_camera_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1.0));
352  float3 frag_to_origin = GetFragToOrigin(i);
353
354	float2 uv_channels = float2(_Custom30_Quaternion_UV_Channel_0, _Custom30_Quaternion_UV_Channel_1);
355  float4 quat = GetRotation(i, uv_channels);
356  float4 iquat = float4(-quat.xyz, quat.w);
357
358  float3 ro = -frag_to_origin;
359  float3 rd = normalize(i.objPos - obj_space_camera_pos);
360  rd = rotate_vector(rd, iquat);
361
362  ro -= rd * _Custom30_ro_Offset;
363
364  float d;
365  float d_acc = 0;
366  float epsilon = 5e-3;
367  // Max distance for platform bounding sphere
368  float max_d = length(float3(1.0, 0.4, 0.2)) * 2.0f;
369
370  uint ii = 0;
371
372  [loop]
373  for (; ii < CUSTOM30_MAX_STEPS; ++ii) {
374    float3 p = ro + rd * d_acc;
375    d = BasicPlatform_map(p);
376    d_acc += d;
377    if (d < epsilon) break;
378    if (d_acc > max_d) break;
379  }
380
381  Custom30Output o;
382#if !defined(_DEPTH_PREPASS)
383  clip(epsilon - d);
384#endif
385  float3 localHit = ro + rd * d_acc;
386  float3 objHit = rotate_vector(localHit, quat);
387  float3 objCenterOffset = rotate_vector(frag_to_origin, quat);
388
389  o.objPos = objHit + (i.objPos + objCenterOffset);
390  float4 clipPos = UnityObjectToClipPos(o.objPos);
391  o.depth = clipPos.z / clipPos.w;
392
393  float3 sdfNormal = BasicPlatform_normal(localHit);
394  float3 objNormal = rotate_vector(sdfNormal, quat);
395  o.normal = UnityObjectToWorldNormal(objNormal);
396
397  return o;
398}
399#endif
400
401#endif  // _CUSTOM30
402#endif  // __CUSTOM30_INC