diff options
| -rw-r--r-- | Editor/tooner.cs | 65 | ||||
| -rw-r--r-- | feature_macros.cginc | 2 | ||||
| -rw-r--r-- | filament_math.cginc | 4 | ||||
| -rw-r--r-- | gerstner.cginc | 133 | ||||
| -rw-r--r-- | globals.cginc | 19 | ||||
| -rw-r--r-- | math.cginc | 3 | ||||
| -rw-r--r-- | tooner.shader | 19 | ||||
| -rw-r--r-- | tooner_lighting.cginc | 17 | ||||
| -rw-r--r-- | tooner_outline_pass.cginc | 12 | ||||
| -rw-r--r-- | trochoid_math.cginc | 4 |
10 files changed, 266 insertions, 12 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs index 7007f30..62d0032 100644 --- a/Editor/tooner.cs +++ b/Editor/tooner.cs @@ -1130,7 +1130,7 @@ public class ToonerGUI : ShaderGUI { RangeProperty( bc, "Outline width"); - SetKeyword("_OUTLINES", bc.floatValue > 1E-6); + SetKeyword("_OUTLINES", bc.floatValue > 1E-9); if (bc.floatValue > 1E-6) { bc = FindProperty("_Outline_Color"); @@ -2115,6 +2115,68 @@ public class ToonerGUI : ShaderGUI { EditorGUI.indentLevel -= 1; } + void DoGimmickGerstnerWater() { + MaterialProperty bc; + + bc = FindProperty("_Gimmick_Gerstner_Water_Enable_Static"); + bool enabled = (bc.floatValue != 0.0); + EditorGUI.BeginChangeCheck(); + enabled = Toggle("Water (gerstner)", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + SetKeyword("_GIMMICK_GERSTNER_WATER", enabled); + + if (!enabled) { + return; + } + EditorGUI.indentLevel += 1; + + bc = FindProperty("_Gimmick_Gerstner_Water_M"); + FloatProperty(bc, "M"); + int num_octaves = (int) Math.Floor((bc.floatValue-1)/4); + SetKeyword("_GIMMICK_GERSTNER_WATER_OCTAVE_1", num_octaves >= 1); + + { + LabelField("Octave 0", EditorStyles.boldLabel); + EditorGUI.indentLevel += 1; + bc = FindProperty("_Gimmick_Gerstner_Water_a"); + VectorProperty(bc, "a"); + bc = FindProperty("_Gimmick_Gerstner_Water_p"); + VectorProperty(bc, "p"); + bc = FindProperty("_Gimmick_Gerstner_Water_k_x"); + VectorProperty(bc, "k_x"); + bc = FindProperty("_Gimmick_Gerstner_Water_k_y"); + VectorProperty(bc, "k_y"); + bc = FindProperty("_Gimmick_Gerstner_Water_t_f"); + VectorProperty(bc, "Time speed"); + EditorGUI.indentLevel -= 1; + } + if (num_octaves > 0) { + LabelField("Octave 1", EditorStyles.boldLabel); + EditorGUI.indentLevel += 1; + bc = FindProperty("_Gimmick_Gerstner_Water_a1"); + VectorProperty(bc, "a"); + bc = FindProperty("_Gimmick_Gerstner_Water_p1"); + VectorProperty(bc, "p"); + bc = FindProperty("_Gimmick_Gerstner_Water_k_x1"); + VectorProperty(bc, "k_x"); + bc = FindProperty("_Gimmick_Gerstner_Water_k_y1"); + VectorProperty(bc, "k_y"); + bc = FindProperty("_Gimmick_Gerstner_Water_t_f1"); + VectorProperty(bc, "Time speed"); + EditorGUI.indentLevel -= 1; + } + + bc = FindProperty("_Gimmick_Gerstner_Water_h"); + FloatProperty(bc, "h"); + bc = FindProperty("_Gimmick_Gerstner_Water_g"); + FloatProperty(bc, "g"); + bc = FindProperty("_Gimmick_Gerstner_Water_Scale"); + VectorProperty(bc, "Scale"); + + EditorGUI.indentLevel -= 1; + } + void DoGimmicks() { show_ui.Add(AddCollapsibleMenu("Gimmicks", "_Gimmicks")); EditorGUI.indentLevel += 1; @@ -2136,6 +2198,7 @@ public class ToonerGUI : ShaderGUI { DoGimmickAudiolinkChroma00(); DoGimmickFog0(); DoGimmickAurora(); + DoGimmickGerstnerWater(); DoClones(); DoExplosion(); DoGeoScroll(); diff --git a/feature_macros.cginc b/feature_macros.cginc index df65e71..7c826aa 100644 --- a/feature_macros.cginc +++ b/feature_macros.cginc @@ -172,6 +172,8 @@ #pragma shader_feature_local _ _GIMMICK_FOG_00_EMITTER_2 #pragma shader_feature_local _ _UNITY_FOG #pragma shader_feature_local _ _GIMMICK_AURORA +#pragma shader_feature_local _ _GIMMICK_GERSTNER_WATER +#pragma shader_feature_local _ _GIMMICK_GERSTNER_WATER_OCTAVE_1 #endif // __FEATURE_MACROS_INC diff --git a/filament_math.cginc b/filament_math.cginc index 5d088ee..e9dcb70 100644 --- a/filament_math.cginc +++ b/filament_math.cginc @@ -1,8 +1,8 @@ +#include "math.cginc" + #ifndef __FILAMENT_MATH_INC #define __FILAMENT_MATH_INC -#define PI 3.1415926535897932384626433832795028841971 - // THIS SOURCE CODE HAS BEEN MODIFIED! // The only modifications are for compatibility with HLSL, for example: // * Replacing normalizeMediump() with normalize() diff --git a/gerstner.cginc b/gerstner.cginc new file mode 100644 index 0000000..da7d2f5 --- /dev/null +++ b/gerstner.cginc @@ -0,0 +1,133 @@ +#include "pema99.cginc" + +#ifndef __GERSTNER_INC +#define __GERSTNER_INC + +#if defined(_GIMMICK_GERSTNER_WATER) + +struct GerstnerParams { + // # of components considered + uint M; + // amplitudes + float4 a; + // phases + float4 p; + // wavenumbers + float4 k_x; + float4 k_y; + // time factor + float4 t_f; +#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1) + float4 a1; + float4 p1; + float4 k_x1; + float4 k_y1; + float4 t_f1; +#endif + // mean water depth + float h; + // gravity + float g; + float3 scale; +}; + +GerstnerParams getGerstnerParams() { + GerstnerParams p; + p.M = _Gimmick_Gerstner_Water_M; + p.a = _Gimmick_Gerstner_Water_a; + p.p = _Gimmick_Gerstner_Water_p; + // Dumb artistic shit + float k_x_time_distortion = _SinTime[2] * .0002; + p.k_x = _Gimmick_Gerstner_Water_k_x + k_x_time_distortion; + p.k_y = _Gimmick_Gerstner_Water_k_y; + p.h = _Gimmick_Gerstner_Water_h; + p.g = _Gimmick_Gerstner_Water_g; + p.scale = _Gimmick_Gerstner_Water_Scale; + p.t_f = _Gimmick_Gerstner_Water_t_f; +#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1) + p.a1 = _Gimmick_Gerstner_Water_a1; + p.p1 = _Gimmick_Gerstner_Water_p1; + p.k_x1 = _Gimmick_Gerstner_Water_k_x1; + p.k_x1 += k_x_time_distortion; + p.k_y1 = _Gimmick_Gerstner_Water_k_y1; + p.t_f1 = _Gimmick_Gerstner_Water_t_f1; +#endif + return p; +} + +float3 compute_gerstner(float3 pp, GerstnerParams p) +{ + const float g_alpha = pp.x * p.scale.x; + const float g_beta = pp.y * p.scale.y; + float g_xi = g_alpha; + float g_eta = g_beta; + float g_zeta = 0; + + for (uint i = 0; i < p.M; i++) { + uint i_mod_4 = glsl_mod(i, 4); + switch (floor(i/4)) { + case 0: + { + const float g_t = _Time[1] * p.t_f[i]; + // wavenumber + const float g_k = length(float2(p.k_x[i], p.k_y[i])); + // angular frequency + const float g_w = sqrt(p.g * g_k * tanh(g_k * p.h)); + // angular frequency + const float g_theta = p.k_x[i] * g_alpha + p.k_y[i] * g_beta - g_w * g_t - p.p[i]; + + g_xi -= (p.k_x[i] / g_k) * (p.a[i] / tanh(g_k * p.h)) * sin(g_theta); + g_eta -= (p.k_y[i] / g_k) * (p.a[i] / tanh(g_k * p.h)) * sin(g_theta); + g_zeta += p.a[i] * cos(g_theta); + break; + } +#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1) + case 1: + { + const float g_t = _Time[1] * p.t_f1[i_mod_4]; + // wavenumber + const float g_k = length(float2(p.k_x1[i_mod_4], p.k_y1[i_mod_4])); + // angular frequency + const float g_w = sqrt(p.g * g_k * tanh(g_k * p.h)); + 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]; + + g_xi -= (p.k_x1[i_mod_4] / g_k) * (p.a1[i_mod_4] / tanh(g_k * p.h)) * sin(g_theta); + g_eta -= (p.k_y1[i_mod_4] / g_k) * (p.a1[i_mod_4] / tanh(g_k * p.h)) * sin(g_theta); + g_zeta += p.a1[i_mod_4] * cos(g_theta); + break; + } +#endif + } + + } + + const float3 raw_result = float3(g_xi / p.scale.x, g_eta / p.scale.y, g_zeta * p.scale.z); + const float origin_damping_factor = 1 - pow(0.5, max(0, length(raw_result)*5000-2)); + + float3 result = raw_result; + result.z *= origin_damping_factor; + return result; +} + +float3 gerstner_vert(float3 pp, GerstnerParams p) +{ + return compute_gerstner(pp, p); +} + +float3 gerstner_frag(float3 pp, GerstnerParams p) +{ + const float3 g0 = compute_gerstner(pp, p); + const float3 e = float3(.001, 0, 0); + const float3 g0_da = compute_gerstner(pp + e.xyz, p); + const float3 g0_db = compute_gerstner(pp + e.yxz, p); + const float3 ds_da = g0_da - g0; + const float3 ds_db = g0_db - g0; + + const float3 n = normalize(cross( + ds_da, ds_db)); + return n; +} + +#endif // _GIMMICK_GERSTNER_WATER +#endif // __GERSTNER_INC + diff --git a/globals.cginc b/globals.cginc index 7c76853..044d9fe 100644 --- a/globals.cginc +++ b/globals.cginc @@ -742,5 +742,24 @@ float _Gimmick_Fog_00_Emitter2_Scale_Y; #endif #endif +#if defined(_GIMMICK_GERSTNER_WATER) +float _Gimmick_Gerstner_Water_M; +float _Gimmick_Gerstner_Water_h; +float _Gimmick_Gerstner_Water_g; +float3 _Gimmick_Gerstner_Water_Scale; +float4 _Gimmick_Gerstner_Water_a; +float4 _Gimmick_Gerstner_Water_p; +float4 _Gimmick_Gerstner_Water_k_x; +float4 _Gimmick_Gerstner_Water_k_y; +float4 _Gimmick_Gerstner_Water_t_f; +#if defined(_GIMMICK_GERSTNER_WATER_OCTAVE_1) +float4 _Gimmick_Gerstner_Water_a1; +float4 _Gimmick_Gerstner_Water_p1; +float4 _Gimmick_Gerstner_Water_k_x1; +float4 _Gimmick_Gerstner_Water_k_y1; +float4 _Gimmick_Gerstner_Water_t_f1; +#endif +#endif + #endif @@ -3,6 +3,9 @@ #ifndef __MATH_INC #define __MATH_INC +#define PI 3.14159265 +#define TAU PI * 2.0 + // Hacky parameterizable whiteout blending. Probably some big mistakes but it // passes the eyeball test. // At w=0.5, this looks kinda like whiteout blending. diff --git a/tooner.shader b/tooner.shader index a7ccba6..bb9a65a 100644 --- a/tooner.shader +++ b/tooner.shader @@ -654,6 +654,25 @@ Shader "yum_food/tooner" _Gimmick_Fog_00_Emitter2_Scale_Y("fog", Float) = 1 _Gimmick_Aurora_Enable_Static("Enable aurora", Float) = 0 + + _Gimmick_Gerstner_Water_Enable_Static("Enable water (gerstner)", Float) = 0 + _Gimmick_Gerstner_Water_M("# of components considered", Float) = 4 + + _Gimmick_Gerstner_Water_a("Amplitudes", Vector) = (.001, .0005, .00025, .000125) + _Gimmick_Gerstner_Water_p("Phases", Vector) = (0, 0, 0, 0) + _Gimmick_Gerstner_Water_k_x("Wavenumbers (x)", Vector) = (1, 1, 1, 1) + _Gimmick_Gerstner_Water_k_y("Wavenumbers (y)", Vector) = (1, 1, 1, 1) + _Gimmick_Gerstner_Water_t_f("Time factor", Vector) = (1, 1, 1, 1) + + _Gimmick_Gerstner_Water_a1("Amplitudes", Vector) = (0, 0, 0, 0) + _Gimmick_Gerstner_Water_p1("Phases", Vector) = (0, 0, 0, 0) + _Gimmick_Gerstner_Water_k_x1("Wavenumbers (x)", Vector) = (1, 1, 1, 1) + _Gimmick_Gerstner_Water_k_y1("Wavenumbers (y)", Vector) = (1, 1, 1, 1) + _Gimmick_Gerstner_Water_t_f1("Time factor", Vector) = (1, 1, 1, 1) + + _Gimmick_Gerstner_Water_h("Mean water depth", Float) = 10 + _Gimmick_Gerstner_Water_g("Gravity", Float) = 9.8 + _Gimmick_Gerstner_Water_Scale("Scale", Vector) = (1000, 1000, .1) } SubShader { diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc index 63cd69d..5d055c0 100644 --- a/tooner_lighting.cginc +++ b/tooner_lighting.cginc @@ -9,6 +9,7 @@ #include "disinfo.cginc" #include "eyes.cginc" #include "fog.cginc" +#include "gerstner.cginc" #include "globals.cginc" #include "halos.cginc" #include "interpolators.cginc" @@ -91,8 +92,6 @@ v2f vert(appdata v) #if defined(_TROCHOID) { -#define PI 3.14159265 -#define TAU PI * 2.0 float theta = v.uv0.x * TAU; float r0 = length(v.vertex.xyz); v.vertex.xyz = trochoid_map(theta, r0, v.vertex.z); @@ -159,6 +158,12 @@ v2f vert(appdata v) v.vertex.xyz = p; } #endif +#if defined(_GIMMICK_GERSTNER_WATER) + { + GerstnerParams p = getGerstnerParams(); + v.vertex.xyz = gerstner_vert(v.vertex.xyz, p); + } +#endif o.pos = UnityObjectToClipPos(v.vertex); o.worldPos = mul(unity_ObjectToWorld, v.vertex); @@ -1291,6 +1296,12 @@ float4 effect(inout v2f i, out float depth) i.objPos.xyz = trochoid_map(theta, r0, z); } #endif +#if defined(_GIMMICK_GERSTNER_WATER) + { + GerstnerParams p = getGerstnerParams(); + i.normal = UnityObjectToWorldNormal(gerstner_frag(i.objPos.xyz, p)); + } +#endif #if defined(_UVSCROLL) float2 orig_uv = i.uv0; @@ -1684,8 +1695,6 @@ float4 effect(inout v2f i, out float depth) #if defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1) || defined(_RIM_LIGHTING2) || defined(_RIM_LIGHTING3) { -#define PI 3.14159265 - #if defined(_RIM_LIGHTING0) { float3 rl_view_dir = VIEW_DIR(_Rim_Lighting0_Center_Eye_Fix); diff --git a/tooner_outline_pass.cginc b/tooner_outline_pass.cginc index 9c10999..93ba73c 100644 --- a/tooner_outline_pass.cginc +++ b/tooner_outline_pass.cginc @@ -5,6 +5,7 @@ #include "audiolink.cginc" #include "clones.cginc" #include "cnlohr.cginc" +#include "gerstner.cginc" #include "globals.cginc" #include "interpolators.cginc" #include "math.cginc" @@ -35,7 +36,6 @@ v2f vert(appdata v) #if defined(_TROCHOID) { -#define PI 3.14159265 #define TAU PI * 2.0 float theta = v.uv0.x * TAU; float r0 = length(v.vertex.xyz); @@ -50,9 +50,17 @@ v2f vert(appdata v) float4 objPos = v.vertex; +#if !defined(_SCROLL) && defined(_GIMMICK_GERSTNER_WATER) + { + GerstnerParams p = getGerstnerParams(); + objPos.xyz = gerstner_vert(objPos.xyz, p); + v.normal = gerstner_frag(objPos.xyz, p); + } +#endif + #if defined(_OUTLINES) float outline_mask = _Outline_Mask.SampleLevel(linear_repeat_s, v.uv0.xy, /*lod=*/0); - outline_mask = _Outline_Mask_Invert > 1E-6 ? 1 - outline_mask : outline_mask; + outline_mask = _Outline_Mask_Invert > 1E-9 ? 1 - outline_mask : outline_mask; objPos.xyz += v.normal * _Outline_Width * outline_mask * _Outline_Width_Multiplier; #endif diff --git a/trochoid_math.cginc b/trochoid_math.cginc index 334b14e..7a4e7e2 100644 --- a/trochoid_math.cginc +++ b/trochoid_math.cginc @@ -1,13 +1,11 @@ #include "globals.cginc" +#include "math.cginc" #ifndef __TROCHOID_MATH #define __TROCHOID_MATH #if defined(_TROCHOID) -#define PI 3.14159265 -#define TAU PI * 2.0 - float3 trochoid_map(float theta, float r0, float3 vert_z) { r0 *= r0; |
