yum-archive/Tooner

A toon shader for Unity's BIRP.

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

yumAdd shader inlining toolingb904835

master
3.4 KiB141 linesraw
1#include "globals.cginc"
2#include "interpolators.cginc"
3#include "math.cginc"
4
5#ifndef __HALOS_INC
6#define __HALOS_INC
7
8#if defined(_GIMMICK_HALO_00)
9struct Halo00Params {
10  float3 period;
11  float3 count;
12  float2 uv;
13};
14struct Halo00PBR {
15  float4 albedo;
16  float3 normal;
17};
18
19float halo00_map(float3 p, float2 e)
20{
21  return length(p) - 0.1;
22}
23
24float halo00_map_dr(
25    float3 p,
26    Halo00Params params,
27    out float3 which
28    )
29{
30  which = round(p / params.period);
31  // Direction to nearest neighboring cell.
32  float3 min_d = p - params.period * which;
33  float3 o = sign(min_d);
34
35  float d = 1E9;
36  float3 which_tmp = which;
37  for (int xi = 0; xi < 1; xi++)
38  for (int yi = 0; yi < 1; yi++)
39  {
40    float3 rid = which + float3(xi, yi, 0) * o;
41    rid = clamp(rid, ceil(-(params.count)*0.5), floor((params.count-1)*0.5));
42    float3 r = p - params.period * rid;
43    float2 e = 0;
44    /*
45    float2 e = float2(
46        rand3(rid / 100.0),
47        rand3(rid / 100.0 + 1));
48    */
49    float cur_d = halo00_map(r, e);
50    which_tmp = 
51        (cur_d < d ? rid : which_tmp);
52    d = min(d, cur_d);
53  }
54
55  which = which_tmp;
56  return d;
57}
58
59float3 halo00_calc_normal(float3 p, Halo00Params params)
60{
61    const float3 small_step = float3(0.0001, 0.0, 0.0);
62
63    // TODO do we need full central differences?
64    float3 which;
65    float gradient_x = halo00_map_dr(p + small_step.xyy, params, which) -
66      halo00_map_dr(p - small_step.xyy, params, which);
67    float gradient_y = halo00_map_dr(p + small_step.yxy, params, which) -
68      halo00_map_dr(p - small_step.yxy, params, which);
69    float gradient_z = halo00_map_dr(p + small_step.yyx, params, which) -
70      halo00_map_dr(p - small_step.yyx, params, which);
71
72    float3 normal = float3(gradient_x, gradient_y, gradient_z);
73
74    return normalize(normal);
75}
76
77void __halo00_march(float3 ro, float3 rd, Halo00Params params, out Halo00PBR result)
78{
79  float total_distance_traveled = 0.0;
80  const float MINIMUM_HIT_DISTANCE = 0.0001;
81  const float MAXIMUM_TRACE_DISTANCE = 10.0;
82  
83  ro -= (1 - (params.count % 2)) * params.period * 0.5;
84
85#define HALO00_MARCH_STEPS 30
86  float distance_to_closest;
87  float3 current_position;
88  float3 which;
89  for (int i = 0; i < HALO00_MARCH_STEPS; i++)
90  {
91    current_position = ro + total_distance_traveled * rd;
92
93    distance_to_closest = halo00_map_dr(current_position, params, which);
94
95    if (distance_to_closest < MINIMUM_HIT_DISTANCE) 
96    {
97      break;
98    }
99
100    if (total_distance_traveled > MAXIMUM_TRACE_DISTANCE)
101    {
102      break;
103    }
104    total_distance_traveled += distance_to_closest;
105  }
106
107  if (distance_to_closest < MINIMUM_HIT_DISTANCE) {
108    result.albedo = 1;
109    result.normal = halo00_calc_normal(current_position, params);
110    return;
111  }
112
113  result.albedo = 0;
114  result.normal = 0;
115  return;
116}
117
118Halo00PBR halo00_march(float3 worldPos, float2 uv)
119{
120  Halo00PBR result;
121  Halo00Params params;
122  params.period = 0.2;
123  params.count = 5;
124  params.uv = uv;
125
126#define COORD_SCALE 2
127#define SCALEF4(f4, scale) float4((f4).x * (scale), (f4).y * (scale), (f4).z * (scale), (f4).w)
128#define F42OBJ(f4) mul(unity_WorldToObject, (SCALEF4(f4, COORD_SCALE))).xyz
129  float3 cam_pos = F42OBJ(float4(_WorldSpaceCameraPos, 1)).xyz;
130  float3 mesh_pos = F42OBJ(float4(worldPos, 1)).xyz;
131  float3 ro = cam_pos;
132  float3 rd = normalize((mesh_pos - cam_pos).xyz);
133
134  __halo00_march(ro, rd, params, result);
135
136  return result;
137}
138
139#endif  // _GIMMICK_HALO_00
140
141#endif  // _HALOS_INC