yum-archive/Tooner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/Tooner
07b1aca
master
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