diff options
| -rw-r--r-- | Editor/tooner.cs | 10 | ||||
| -rw-r--r-- | clones.cginc | 92 | ||||
| -rw-r--r-- | fog.cginc | 2 | ||||
| -rw-r--r-- | gerstner.cginc | 4 | ||||
| -rw-r--r-- | globals.cginc | 3 | ||||
| -rw-r--r-- | tooner.shader | 7 | ||||
| -rw-r--r-- | tooner_lighting.cginc | 34 | ||||
| -rw-r--r-- | tooner_outline_pass.cginc | 31 |
8 files changed, 134 insertions, 49 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs index deb2357..116fb4f 100644 --- a/Editor/tooner.cs +++ b/Editor/tooner.cs @@ -1136,9 +1136,13 @@ public class ToonerGUI : ShaderGUI { bc, "Number of clones"); bc = FindProperty("_Clones_dx"); - RangeProperty( - bc, - "x offset"); + RangeProperty(bc, "x offset"); + bc = FindProperty("_Clones_dy"); + RangeProperty(bc, "y offset"); + bc = FindProperty("_Clones_dz"); + RangeProperty(bc, "z offset"); + bc = FindProperty("_Clones_Scale"); + VectorProperty(bc, "Scale"); } EditorGUI.indentLevel -= 1; show_ui.RemoveAt(show_ui.Count - 1); diff --git a/clones.cginc b/clones.cginc index 9b43b80..140e7d1 100644 --- a/clones.cginc +++ b/clones.cginc @@ -1,14 +1,70 @@ #include "interpolators.cginc" #include "globals.cginc" +#include "math.cginc" #ifndef __CLONES_INC #define __CLONES_INC #if defined(_CLONES) -void add_clones(in v2f clone_verts[3], inout TriangleStream<v2f> tri_out) +void rotate_triangle(inout v2f tri_in[3], const float pid_rand, const float phase) { - if (_Clones_dx < 1E-6) { + if (phase < 1E-6) { + return; + } + + float3 avg_pos = (tri_in[0].worldPos + tri_in[1].worldPos + tri_in[2].worldPos) * .33333333; + tri_in[0].worldPos -= avg_pos; + tri_in[1].worldPos -= avg_pos; + tri_in[2].worldPos -= avg_pos; + + if (phase > 1E-6) { + float theta = phase * 3.14159 * 4 + phase * (sin(_Time[1] * (1 + pid_rand) * 0.5 + pid_rand) + cos(_Time[1] * (1 + pid_rand) * .16393442 + pid_rand) * 2) * pid_rand * 2; + float3 axis = normalize(float3( + rand((int) ((tri_in[0].uv0.x + tri_in[0].uv0.y + pid_rand) * 1E9)) * 2 - 1, + rand((int) ((tri_in[1].uv0.x + tri_in[1].uv0.y + pid_rand) * 1E9)) * 2 - 1, + rand((int) ((tri_in[2].uv0.x + tri_in[2].uv0.y + pid_rand) * 1E9)) * 2 - 1)); + float4 quat = get_quaternion(axis, theta); + tri_in[0].worldPos = rotate_vector(tri_in[0].worldPos, quat); + tri_in[1].worldPos = rotate_vector(tri_in[1].worldPos, quat); + tri_in[2].worldPos = rotate_vector(tri_in[2].worldPos, quat); + } + + tri_in[0].worldPos *= _Clones_Scale.xyz; + tri_in[1].worldPos *= _Clones_Scale.xyz; + tri_in[2].worldPos *= _Clones_Scale.xyz; + + tri_in[0].worldPos += avg_pos; + tri_in[1].worldPos += avg_pos; + tri_in[2].worldPos += avg_pos; + + float3 v0_objPos = mul(unity_WorldToObject, float4(tri_in[0].worldPos, 1)); + float3 v1_objPos = mul(unity_WorldToObject, float4(tri_in[1].worldPos, 1)); + float3 v2_objPos = mul(unity_WorldToObject, float4(tri_in[2].worldPos, 1)); + + // Perf hack: Normal gets normalized in fragment shader anyway xdd + // TODO add a toggle to normalize in fragment or not; and use it to gate this + // optimization. + float3 n = cross(tri_in[1].worldPos - tri_in[0].worldPos, tri_in[2].worldPos - tri_in[0].worldPos); + tri_in[0].normal = n; + tri_in[1].normal = n; + tri_in[2].normal = n; + + tri_in[0].pos = UnityObjectToClipPos(v0_objPos); + tri_in[1].pos = UnityObjectToClipPos(v1_objPos); + tri_in[2].pos = UnityObjectToClipPos(v2_objPos); + + tri_in[0].objPos = v0_objPos; + tri_in[1].objPos = v1_objPos; + tri_in[2].objPos = v2_objPos; +} + +void add_clones(in v2f clone_verts[3], inout TriangleStream<v2f> tri_out, + float pid_rand, float explode_phase) +{ + if (_Clones_dx < 1E-6 && + _Clones_dy < 1E-6 && + _Clones_dz < 1E-6) { return; } @@ -21,16 +77,32 @@ void add_clones(in v2f clone_verts[3], inout TriangleStream<v2f> tri_out) uint n_clones = (uint) round(_Clones_Count); for (uint i = 0; i < (uint) n_clones; i++) { + v2f mod_verts[3] = clone_verts; + float3 offset = i; + offset = ((offset % 2) * 2 - 1) * (((offset) * 0.5) + 1) * + float3(_Clones_dx, _Clones_dy, _Clones_dz); for (uint j = 0; j < 3; j++) { - v2f ii = clone_verts[j]; - float3 objPos = mul(unity_WorldToObject, float4(ii.worldPos, 1)).xyz; - float offset = i; - offset = ((offset % 2) * 2 - 1) * (((offset) / 2) + 1) * _Clones_dx; - objPos.x += offset; - ii.worldPos = mul(unity_ObjectToWorld, float4(objPos, 1)).xyz; - ii.pos = UnityObjectToClipPos(objPos); - tri_out.Append(ii); +#if 0 + float3 objPos = mul(unity_WorldToObject, float4(mod_verts[j].worldPos, 1)).xyz; + objPos += offset; + mod_verts[j].worldPos = mul(unity_ObjectToWorld, float4(objPos, 1)).xyz; +#else + mod_verts[j].worldPos += offset; +#endif } +#if 1 + rotate_triangle(mod_verts, rand(pid_rand+i), /*phase=*/1); +#else + mod_verts[0].objPos = mul(unity_WorldToObject, float4(mod_verts[0].worldPos, 1)); + mod_verts[1].objPos = mul(unity_WorldToObject, float4(mod_verts[1].worldPos, 1)); + mod_verts[2].objPos = mul(unity_WorldToObject, float4(mod_verts[2].worldPos, 1)); + mod_verts[0].pos = UnityObjectToClipPos(mod_verts[0].objPos); + mod_verts[1].pos = UnityObjectToClipPos(mod_verts[1].objPos); + mod_verts[2].pos = UnityObjectToClipPos(mod_verts[2].objPos); +#endif + tri_out.Append(mod_verts[0]); + tri_out.Append(mod_verts[1]); + tri_out.Append(mod_verts[2]); tri_out.RestartStrip(); } } @@ -33,7 +33,7 @@ float perlin_noise_3d_tex(float3 p) } float map(float3 p, float lod) { - float3 t = _Time[1] * .5 * FOG_PERLIN_NOISE_SCALE; + float3 t = _Time[1] * _Gimmick_Fog_00_Noise_Scale * FOG_PERLIN_NOISE_SCALE; #define RADIUS_TRANS_WIDTH 100 #define RADIUS_TRANS_WIDTH_RCP (1.0 / RADIUS_TRANS_WIDTH) // Try to create a smooth transition without doing any length() or other diff --git a/gerstner.cginc b/gerstner.cginc index 47843a7..a5f7db2 100644 --- a/gerstner.cginc +++ b/gerstner.cginc @@ -148,9 +148,9 @@ GerstnerInternalResult compute_gerstner(float3 pp, GerstnerParams p) float3 result_obj = mul(unity_WorldToObject, float4(result_world, 1)).xyz; result_obj = lerp(result_obj, raw_result, - // If within 3m cylindrical distance, apply 100m wide damping. + // If within cylindrical distance, apply damping. // TODO parameterize this! - dsaturate((length(raw_result_world.xz) - 20), 1) * + dsaturate((length(raw_result_world.xz) - 15), 1) * // Only enable if mesh is on the wrong side of the damping vector. // TODO make this differentiable. As is, there's a visible seam. dsaturate(-(raw_result_world.y - _Gimmick_Gerstner_Water_Origin_Damping_Direction) * sign(_Gimmick_Gerstner_Water_Origin_Damping_Direction), 1)); diff --git a/globals.cginc b/globals.cginc index f1a7fc3..764b9f8 100644 --- a/globals.cginc +++ b/globals.cginc @@ -562,6 +562,9 @@ float _HSV1_Val_Shift; float _Clones_Enabled; float _Clones_Count; float _Clones_dx; +float _Clones_dy; +float _Clones_dz; +float3 _Clones_Scale; float _Clones_Dist_Cutoff; #endif diff --git a/tooner.shader b/tooner.shader index db54d6e..39f13ba 100644 --- a/tooner.shader +++ b/tooner.shader @@ -450,8 +450,11 @@ Shader "yum_food/tooner" _Clones_Enabled("Enable clones", Float) = 0.0 _Clones_Count("Clones count", Range(0,16)) = 0.0 - _Clones_Dist_Cutoff("Clones distance cutoff", Float) = -1.0 - _Clones_dx("Clones dx", Range(0, 1)) = 1.0 + _Clones_Dist_Cutoff("distance cutoff", Float) = -1.0 + _Clones_dx("dx", Range(0, 10)) = 1.0 + _Clones_dy("dy", Range(0, 10)) = 1.0 + _Clones_dz("dz", Range(0, 10)) = 1.0 + _Clones_Scale("scale", Vector) = (1, 1, 1, 1) _UVScroll_Enabled("Enable UV scrolling", Float) = 0.0 _UVScroll_Mask("UV scroll mask", 2D) = "white" diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc index 1b306ce..6e4e2ac 100644 --- a/tooner_lighting.cginc +++ b/tooner_lighting.cginc @@ -219,7 +219,7 @@ v2f vert(appdata v) // maxvertexcount == the number of vertices we create #if defined(_CLONES) -[maxvertexcount(15)] +[maxvertexcount(21)] #else [maxvertexcount(3)] #endif @@ -235,6 +235,9 @@ void geom(triangle v2f tri_in[3], float3 v1_objPos; float3 v2_objPos; + const float pid_rand = rand((int) pid); + + float explode_phase = 0; #if defined(_EXPLODE) float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); float3 avg_pos; @@ -243,22 +246,21 @@ void geom(triangle v2f tri_in[3], float3 n1 = v1.normal; float3 n2 = v2.normal; - float phase = _Explode_Phase; - phase = smoothstep(0, 1, phase); - phase *= phase; - phase *= 4; - const float pid_rand = rand((int) pid); + explode_phase = _Explode_Phase; + explode_phase = smoothstep(0, 1, explode_phase); + explode_phase *= explode_phase; + explode_phase *= 4; - if (phase > 1E-6) { + if (explode_phase > 1E-6) { float3 axis = normalize(float3( rand((int) ((v0.uv0.x + v0.uv0.y) * 1E9)) * 2 - 1, rand((int) ((v1.uv0.x + v1.uv0.y) * 1E9)) * 2 - 1, rand((int) ((v2.uv0.x + v2.uv0.y) * 1E9)) * 2 - 1)); - float3 np = BlendNormals(n, axis * phase); + float3 np = BlendNormals(n, axis * explode_phase); - v0.worldPos += np * phase * pid_rand; - v1.worldPos += np * phase * pid_rand; - v2.worldPos += np * phase * pid_rand; + v0.worldPos += np * explode_phase * pid_rand; + v1.worldPos += np * explode_phase * pid_rand; + v2.worldPos += np * explode_phase * pid_rand; v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1)); v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1)); @@ -270,16 +272,16 @@ void geom(triangle v2f tri_in[3], chrono = (AudioLinkDecodeDataAsUInt( ALPASS_CHRONOTENSITY + uint2( 2, 1 ) ) % 1000000) / 1000000.0; } #endif - v0.worldPos += n * phase * sin(_Time[2] + length(v0_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; - v1.worldPos += n * phase * sin(_Time[2] + length(v1_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; - v2.worldPos += n * phase * sin(_Time[2] + length(v2_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; + v0.worldPos += n * explode_phase * sin(_Time[2] + length(v0_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; + v1.worldPos += n * explode_phase * sin(_Time[2] + length(v1_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; + v2.worldPos += n * explode_phase * sin(_Time[2] + length(v2_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; v0.worldPos -= avg_pos; v1.worldPos -= avg_pos; v2.worldPos -= avg_pos; - float theta = phase * 3.14159 * 4 + phase * (sin(_Time[1] * (1 + pid_rand) / 2.0 + pid_rand) + cos(_Time[1] * (1 + pid_rand) / 6.1 + pid_rand) * 2) * pid_rand * 2; + float theta = explode_phase * 3.14159 * 4 + explode_phase * (sin(_Time[1] * (1 + pid_rand) / 2.0 + pid_rand) + cos(_Time[1] * (1 + pid_rand) / 6.1 + pid_rand) * 2) * pid_rand * 2; float4 quat = get_quaternion(axis, theta); v0.worldPos = rotate_vector(v0.worldPos, quat); v1.worldPos = rotate_vector(v1.worldPos, quat); @@ -369,7 +371,7 @@ void geom(triangle v2f tri_in[3], #endif #if defined(_CLONES) v2f clone_verts[3] = {v0, v1, v2}; - add_clones(clone_verts, tri_out); + add_clones(clone_verts, tri_out, pid_rand, explode_phase); #endif // _CLONES // Output transformed geometry. diff --git a/tooner_outline_pass.cginc b/tooner_outline_pass.cginc index 46a03f0..c68c57b 100644 --- a/tooner_outline_pass.cginc +++ b/tooner_outline_pass.cginc @@ -127,6 +127,8 @@ void geom(triangle v2f tri_in[3], float3 v1_objPos; float3 v2_objPos; + const float pid_rand = rand((int) pid); + float explode_phase = 0; #if defined(_EXPLODE) float3 n = normalize(cross(v1.worldPos - v0.worldPos, v2.worldPos - v0.worldPos)); float3 avg_pos; @@ -135,22 +137,21 @@ void geom(triangle v2f tri_in[3], float3 n1 = v1.normal; float3 n2 = v2.normal; - float phase = _Explode_Phase; - phase = smoothstep(0, 1, phase); - phase *= phase; - phase *= 4; - const float pid_rand = rand((int) pid); + explode_phase = _Explode_Phase; + explode_phase = smoothstep(0, 1, explode_phase); + explode_phase *= explode_phase; + explode_phase *= 4; - if (phase > 1E-6) { + if (explode_phase > 1E-6) { float3 axis = normalize(float3( rand((int) ((v0.uv0.x + v0.uv0.y) * 1E9)) * 2 - 1, rand((int) ((v1.uv0.x + v1.uv0.y) * 1E9)) * 2 - 1, rand((int) ((v2.uv0.x + v2.uv0.y) * 1E9)) * 2 - 1)); - float3 np = BlendNormals(n, axis * phase); + float3 np = BlendNormals(n, axis * explode_phase); - v0.worldPos += np * phase * pid_rand; - v1.worldPos += np * phase * pid_rand; - v2.worldPos += np * phase * pid_rand; + v0.worldPos += np * explode_phase * pid_rand; + v1.worldPos += np * explode_phase * pid_rand; + v2.worldPos += np * explode_phase * pid_rand; v0_objPos = mul(unity_WorldToObject, float4(v0.worldPos, 1)); v1_objPos = mul(unity_WorldToObject, float4(v1.worldPos, 1)); @@ -162,16 +163,16 @@ void geom(triangle v2f tri_in[3], chrono = (AudioLinkDecodeDataAsUInt( ALPASS_CHRONOTENSITY + uint2( 2, 1 ) ) % 1000000) / 1000000.0; } #endif - v0.worldPos += n * phase * sin(_Time[2] + length(v0_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; - v1.worldPos += n * phase * sin(_Time[2] + length(v1_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; - v2.worldPos += n * phase * sin(_Time[2] + length(v2_objPos)*6 + chrono) * .01 + chrono * n * phase * .2; + v0.worldPos += n * explode_phase * sin(_Time[2] + length(v0_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; + v1.worldPos += n * explode_phase * sin(_Time[2] + length(v1_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; + v2.worldPos += n * explode_phase * sin(_Time[2] + length(v2_objPos)*6 + chrono) * .01 + chrono * n * explode_phase * .2; avg_pos = (v0.worldPos + v1.worldPos + v2.worldPos) / 3; v0.worldPos -= avg_pos; v1.worldPos -= avg_pos; v2.worldPos -= avg_pos; - float theta = phase * 3.14159 * 4 + phase * (sin(_Time[1] * (1 + pid_rand) / 2.0 + pid_rand) + cos(_Time[1] * (1 + pid_rand) / 6.1 + pid_rand) * 2) * pid_rand * 2; + float theta = explode_phase * 3.14159 * 4 + explode_phase * (sin(_Time[1] * (1 + pid_rand) / 2.0 + pid_rand) + cos(_Time[1] * (1 + pid_rand) / 6.1 + pid_rand) * 2) * pid_rand * 2; float4 quat = get_quaternion(axis, theta); v0.worldPos = rotate_vector(v0.worldPos, quat); v1.worldPos = rotate_vector(v1.worldPos, quat); @@ -261,7 +262,7 @@ void geom(triangle v2f tri_in[3], #endif #if defined(_CLONES) v2f clone_verts[3] = {v0, v1, v2}; - add_clones(clone_verts, tri_out); + add_clones(clone_verts, tri_out, pid_rand, explode_phase); #endif // _CLONES // Output transformed geometry. |
