yum-archive/Tooner

A toon shader for Unity's BIRP.

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

yumUpdate cloning07b1aca

master
6.0 KiB198 linesraw
1#include "globals.cginc"
2#include "math.cginc"
3#include "pema99.cginc"
4
5#ifndef __GERSTNER_INC
6#define __GERSTNER_INC
7
8#if defined(_GIMMICK_GERSTNER_WATER)
9
10struct GerstnerParams {
11  // # of components considered
12  uint M;
13  // amplitudes
14  float4 a;
15  // phases
16  float4 p;
17  // wavenumbers
18  float4 k_x;
19  float4 k_y;
20  // time factor
21  float4 t_f;
22#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
23  float4 ramp_mask;
24#endif
25#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1)
26  float4 a1;
27  float4 p1;
28  float4 k_x1;
29  float4 k_y1;
30  float4 t_f1;
31#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
32  float4 ramp_mask1;
33#endif
34#endif
35  // mean water depth
36  float h;
37  // gravity
38  float g;
39  float3 scale;
40};
41
42struct GerstnerFragResult {
43  float4 tangent;
44  float3 normal;
45#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
46  float3 color;
47#endif
48};
49
50GerstnerParams getGerstnerParams() {
51  GerstnerParams p;
52  p.M = _Gimmick_Gerstner_Water_M;
53  p.a = _Gimmick_Gerstner_Water_a;
54  p.p = _Gimmick_Gerstner_Water_p;
55  // Dumb artistic shit
56  float k_x_time_distortion = _SinTime[2] * .0002;
57  p.k_x = _Gimmick_Gerstner_Water_k_x + k_x_time_distortion;
58  p.k_y = _Gimmick_Gerstner_Water_k_y;
59  p.h = _Gimmick_Gerstner_Water_h;
60  p.g = _Gimmick_Gerstner_Water_g;
61  p.scale = _Gimmick_Gerstner_Water_Scale;
62  p.t_f = _Gimmick_Gerstner_Water_t_f;
63#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
64  p.ramp_mask = _Gimmick_Gerstner_Water_Color_Ramp_Mask;
65#endif
66#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1)
67  p.a1 = _Gimmick_Gerstner_Water_a1;
68  p.p1 = _Gimmick_Gerstner_Water_p1;
69  p.k_x1 = _Gimmick_Gerstner_Water_k_x1;
70  p.k_x1 += k_x_time_distortion;
71  p.k_y1 = _Gimmick_Gerstner_Water_k_y1;
72  p.t_f1 = _Gimmick_Gerstner_Water_t_f1;
73#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
74  p.ramp_mask1 = _Gimmick_Gerstner_Water_Color_Ramp_Mask1;
75#endif
76#endif
77  return p;
78}
79
80struct GerstnerInternalResult {
81  float3 world_pos;
82  float color_ramp_pos;
83};
84
85GerstnerInternalResult compute_gerstner(float3 pp, GerstnerParams p)
86{
87  const float g_alpha = pp.x * p.scale.x;
88  const float g_beta = pp.y * p.scale.y;
89  float g_xi = g_alpha;
90  float g_eta = g_beta;
91  float g_zeta = 0;
92  float g_zeta_color_ramp = 0;
93
94  for (uint i = 0; i < p.M; i++) {
95    uint i_mod_4 = glsl_mod(i, 4);
96    switch (floor(i/4)) {
97      case 0:
98        {
99          const float g_t = _Time[1] * p.t_f[i];
100          // wavenumber
101          const float g_k = length(float2(p.k_x[i], p.k_y[i]));
102          // angular frequency
103          const float g_w = sqrt(p.g * g_k * tanh(g_k * p.h));
104          // angular frequency
105          const float g_theta = p.k_x[i] * g_alpha + p.k_y[i] * g_beta - g_w * g_t - p.p[i];
106
107          g_xi  -= (p.k_x[i] / g_k) * (p.a[i] / tanh(g_k * p.h)) * sin(g_theta);
108          g_eta -= (p.k_y[i] / g_k) * (p.a[i] / tanh(g_k * p.h)) * sin(g_theta);
109          g_zeta += p.a[i] * cos(g_theta);
110#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
111          g_zeta_color_ramp += p.a[i] * cos(g_theta) * p.ramp_mask[i];
112#endif
113          break;
114        }
115#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1)
116      case 1:
117        {
118          const float g_t = _Time[1] * p.t_f1[i_mod_4];
119          // wavenumber
120          const float g_k = length(float2(p.k_x1[i_mod_4], p.k_y1[i_mod_4]));
121          // angular frequency
122          const float g_w = sqrt(p.g * g_k * tanh(g_k * p.h));
123          const float g_theta = p.k_x1[i_mod_4] * g_alpha + p.k_y1[i_mod_4] * g_beta - g_w * g_t - p.p1[i_mod_4];
124
125          g_xi  -= (p.k_x1[i_mod_4] / g_k) * (p.a1[i_mod_4] / tanh(g_k * p.h)) * sin(g_theta);
126          g_eta -= (p.k_y1[i_mod_4] / g_k) * (p.a1[i_mod_4] / tanh(g_k * p.h)) * sin(g_theta);
127          g_zeta += p.a1[i_mod_4] * cos(g_theta);
128#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
129          g_zeta_color_ramp += p.a1[i_mod_4] * cos(g_theta) * p.ramp_mask1[i_mod_4];
130#endif
131          break;
132        }
133#endif
134    }
135  }
136
137  const float3 raw_result = float3(g_xi / p.scale.x, g_eta / p.scale.y, g_zeta * p.scale.z);
138  g_zeta_color_ramp *= p.scale.z;
139  const float3 raw_result_world = mul(unity_ObjectToWorld, float4(raw_result, 1)).xyz;
140  float3 result_world = raw_result_world;
141
142  if (_Gimmick_Gerstner_Water_Origin_Damping_Direction > 0) {
143    result_world.y = dmax(_Gimmick_Gerstner_Water_Origin_Damping_Direction, result_world.y, 1);
144  } else {
145    result_world.y = dmin(_Gimmick_Gerstner_Water_Origin_Damping_Direction, result_world.y, 1);
146  }
147
148  float3 result_obj = mul(unity_WorldToObject, float4(result_world, 1)).xyz;
149
150  result_obj = lerp(result_obj, raw_result,
151      // If within cylindrical distance, apply damping.
152      // TODO parameterize this!
153      dsaturate((length(raw_result_world.xz) - 15), 1) *
154      // Only enable if mesh is on the wrong side of the damping vector.
155      // TODO make this differentiable. As is, there's a visible seam.
156      dsaturate(-(raw_result_world.y - _Gimmick_Gerstner_Water_Origin_Damping_Direction) * sign(_Gimmick_Gerstner_Water_Origin_Damping_Direction), 1));
157
158  GerstnerInternalResult r;
159  r.world_pos = result_obj;
160  r.color_ramp_pos = g_zeta_color_ramp;
161  return r;
162}
163
164float3 gerstner_vert(float3 pp, GerstnerParams p)
165{
166  return compute_gerstner(pp, p).world_pos;
167}
168
169GerstnerFragResult gerstner_frag(float3 pp, GerstnerParams p)
170{
171  const GerstnerInternalResult r0 = compute_gerstner(pp, p);
172  const float3 g0 = r0.world_pos;
173  const float3 e = float3(1E-7, 0, 0);
174  const float3 g0_da = compute_gerstner(pp + e.xyz, p).world_pos;
175  const float3 g0_db = compute_gerstner(pp + e.yxz, p).world_pos;
176  const float3 ds_da = g0_da - g0;
177  const float3 ds_db = g0_db - g0;
178
179  GerstnerFragResult r;
180  r.normal = normalize(cross(
181        ds_da, ds_db));
182  r.tangent = float4(normalize(ds_da), 1);
183
184#if defined(_GIMMICK_GERSTNER_WATER_COLOR_RAMP)
185  float ramp_phase = r0.color_ramp_pos;
186  ramp_phase *= _Gimmick_Gerstner_Water_Color_Ramp_Scale;
187  ramp_phase += _Gimmick_Gerstner_Water_Color_Ramp_Offset;
188  float3 ramp_color = _Gimmick_Gerstner_Water_Color_Ramp.Sample(linear_clamp_s, float2(ramp_phase, 0.5));
189
190  r.color = ramp_color;
191#endif
192
193  return r;
194}
195
196#endif  // _GIMMICK_GERSTNER_WATER
197#endif  // __GERSTNER_INC
198