summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Editor/tooner.cs8
-rw-r--r--fog.cginc15
-rw-r--r--globals.cginc4
-rw-r--r--interpolators.cginc8
-rw-r--r--mochie_shadow_caster.cginc8
-rw-r--r--tooner.shader4
-rw-r--r--tooner_lighting.cginc28
-rw-r--r--tooner_outline_pass.cginc10
-rw-r--r--trochoid_math.cginc195
9 files changed, 192 insertions, 88 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index 1f759c2..0d15a3a 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -1981,6 +1981,14 @@ public class ToonerGUI : ShaderGUI {
FloatProperty(bc, "r");
bc = FindProperty("_Trochoid_d");
FloatProperty(bc, "d");
+ bc = FindProperty("_Trochoid_Speed");
+ FloatProperty(bc, "Speed");
+ bc = FindProperty("_Trochoid_Radius_Power");
+ FloatProperty(bc, "Radius power");
+ bc = FindProperty("_Trochoid_Radius_Scale");
+ FloatProperty(bc, "Radius scale");
+ bc = FindProperty("_Trochoid_Height_Scale");
+ FloatProperty(bc, "Height scale");
EditorGUI.indentLevel -= 1;
}
diff --git a/fog.cginc b/fog.cginc
index a5ac588..fec9c47 100644
--- a/fog.cginc
+++ b/fog.cginc
@@ -257,10 +257,7 @@ Fog00PBR getFog00(v2f i, ToonerData tdata) {
if (solveQuadratic(a, b, c, t0, t1)) {
no_intersection = (t0 < 0) * (t1 < 0);
const bool inside_cylinder = (t0 < 0) * (t1 > 0);
- if (inside_cylinder) {
- distance_to_cylinder = no_intersection ? distance_to_cylinder : max(t0, t1);
- distance_to_cylinder = min(distance_to_cylinder, length(obj_pos_depth_hit - ro));
- } else {
+ if (!inside_cylinder) {
distance_to_cylinder = no_intersection ? distance_to_cylinder : min(max(t0, 0), max(t1, 0));
ro += distance_to_cylinder * rd;
}
@@ -306,7 +303,7 @@ Fog00PBR getFog00(v2f i, ToonerData tdata) {
float4 acc = 0;
uint step_count = floor(min(_Gimmick_Fog_00_Max_Ray, depth_hit_l) / step_size);
//step_count *= (1 - no_intersection);
-#define FOG_MAX_LOOP 10
+#define FOG_MAX_LOOP 20
step_count = min(step_count, FOG_MAX_LOOP);
#if defined(_GIMMICK_FOG_00_EMITTER_TEXTURE)
@@ -401,8 +398,7 @@ Fog00PBR getFog00(v2f i, ToonerData tdata) {
Fog00PBR pbr;
pbr.albedo = acc;
- pbr.albedo.a *= 1;
- pbr.albedo.a = smooth_min(pbr.albedo.a, .99, 1);
+ pbr.albedo.a = smooth_min(pbr.albedo.a, .999, 1);
// Add some dithering to lit color to break up banding
//const float frame = ((float) AudioLinkData(ALPASS_GENERALVU + int2(1, 0)).x);
@@ -419,6 +415,11 @@ Fog00PBR getFog00(v2f i, ToonerData tdata) {
float4 clip_pos = mul(UNITY_MATRIX_VP, float4(mul(unity_ObjectToWorld, float4(ro, 1.0))));
pbr.depth = clip_pos.z / clip_pos.w;
+#if 0
+ pbr.albedo.rgb = eye_depth_world / 100;
+ pbr.albedo.a = 1;
+#endif
+
return pbr;
}
diff --git a/globals.cginc b/globals.cginc
index 9574043..0b1308f 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -801,6 +801,10 @@ texture2D _Gimmick_Pixellate_Effect_Mask;
float _Trochoid_R;
float _Trochoid_r;
float _Trochoid_d;
+float _Trochoid_Speed;
+float _Trochoid_Radius_Power;
+float _Trochoid_Radius_Scale;
+float _Trochoid_Height_Scale;
#endif
#if defined(_FACE_ME_WORLD_Y)
diff --git a/interpolators.cginc b/interpolators.cginc
index 4955415..2193339 100644
--- a/interpolators.cginc
+++ b/interpolators.cginc
@@ -50,6 +50,10 @@ struct v2f
float2 screenPos : TEXCOORD14;
+#if defined(_TROCHOID)
+ float3 objPos_pre_trochoid : TEXCOORD15;
+#endif
+
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
@@ -108,6 +112,10 @@ struct v2f
float3 vertexLightColor : TEXCOORD16;
#endif
+#if defined(_TROCHOID)
+ float3 objPos_pre_trochoid : TEXCOORD17;
+#endif
+
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
diff --git a/mochie_shadow_caster.cginc b/mochie_shadow_caster.cginc
index 64f6350..0d15d41 100644
--- a/mochie_shadow_caster.cginc
+++ b/mochie_shadow_caster.cginc
@@ -1,5 +1,8 @@
+#include "UnityCG.cginc"
+
#include "atrix256.cginc"
#include "gerstner.cginc"
+#include "trochoid_math.cginc"
#ifndef __MOCHIE_SHADOW_CASTER_INC
#define __MOCHIE_SHADOW_CASTER_INC
@@ -60,6 +63,11 @@ v2f vert (appdata v){
return (v2f) (0.0 / 0.0);
}
#endif
+#if defined(_TROCHOID)
+ {
+ v.vertex.xyz = cyl2_to_troch_map(cyl_to_cyl2_map(cart_to_cyl_map(v.vertex.xyz)));
+ }
+#endif
#if !defined(_SCROLL) && defined(_GIMMICK_GERSTNER_WATER)
{
GerstnerParams p = getGerstnerParams();
diff --git a/tooner.shader b/tooner.shader
index e192644..b2bdedd 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -849,6 +849,10 @@ Shader "yum_food/tooner"
_Trochoid_R("R", Float) = 5.0
_Trochoid_r("r", Float) = 3.0
_Trochoid_d("d", Float) = 5.0
+ _Trochoid_Speed("Speed", Float) = 1.0
+ _Trochoid_Radius_Power("Radius power", Float) = 1.0
+ _Trochoid_Radius_Scale("Radius scale", Float) = 1.0
+ _Trochoid_Height_Scale("Height scale", Float) = 1.0
_FaceMeWorldY_Enable_Static("Enable face me gimmick", Float) = 0.0
_FaceMeWorldY_Enable_Dynamic("Enable face me gimmick", Float) = 0.0
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index e088c17..adf7890 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -137,9 +137,8 @@ v2f vert(appdata v)
#if defined(_TROCHOID)
{
- float theta = v.uv0.x * TAU;
- float r0 = length(v.vertex.xyz);
- v.vertex.xyz = trochoid_map(theta, r0, v.vertex.z);
+ o.objPos_pre_trochoid = v.vertex.xyz;
+ v.vertex.xyz = cyl2_to_troch_map(cyl_to_cyl2_map(cart_to_cyl_map(v.vertex.xyz)));
}
#endif
#if defined(_FACE_ME_WORLD_Y)
@@ -1598,12 +1597,23 @@ float4 effect(inout v2f i, out float depth)
#if defined(_TROCHOID)
{
- i.normal = trochoid_normal(i.objPos.xyz, i.uv0);
-
- float theta = i.uv0.x * TAU;
- float r0 = length(i.objPos.xyz);
- float z = i.objPos.z;
- i.objPos.xyz = trochoid_map(theta, r0, z);
+ // Let h(v) be the trochoid of the cartesian coordinates v.
+ // We evaluate h(v) by first mapping it to cylindrical coordinates, then applying a trochoid function defined on those coordinates:
+ // h(v) = h_cyl(g(v))
+ // g(v) maps v to cylindrical coordinates.
+ // h_cyl(v) evaluates the trochoid function on cylindrical coordinates.
+ // We want to compute h'(v), i.e. its Jacobian.
+ // By the chain rule:
+ // h'(v) = h_cyl'(g(v)) * g'(v)
+ // The reality is a little more complex: we also apply a distortion to the cylindrical coordinates:
+ // h(v) = h_cyl(f(g(v)))
+ // where f(v) is that distortion.
+ // Again, by the chain rule:
+ // h'(v) = h_cyl'(f(g(v))) * f'(g(v)) * g'(v)
+ float3x3 j0 = cart_to_cyl_jacobian(i.objPos_pre_trochoid);
+ float3x3 j1 = cyl_to_cyl2_jacobian(cart_to_cyl_map(i.objPos_pre_trochoid));
+ float3x3 j2 = cyl2_to_troch_jacobian(cyl_to_cyl2_map(cart_to_cyl_map(i.objPos_pre_trochoid)));
+ i.normal = normalize(mul(transpose(invert(mul(j0, mul(j1, j2)))), i.normal));
}
#endif
diff --git a/tooner_outline_pass.cginc b/tooner_outline_pass.cginc
index a318c5f..02b6497 100644
--- a/tooner_outline_pass.cginc
+++ b/tooner_outline_pass.cginc
@@ -36,15 +36,7 @@ v2f vert(appdata v)
#if defined(_TROCHOID)
{
-#define TAU PI * 2.0
- float theta = v.uv0.x * TAU;
- float r0 = length(v.vertex.xyz);
-
- float x = v.vertex.x;
- float y = v.vertex.y;
- float z = v.vertex.z;
-
- v.vertex.xyz = trochoid_map(theta, r0, z);
+ v.vertex.xyz = cyl2_to_troch_map(cyl_to_cyl2_map(cart_to_cyl_map(v.vertex.xyz)));
}
#endif
diff --git a/trochoid_math.cginc b/trochoid_math.cginc
index 7a4e7e2..dd6d69c 100644
--- a/trochoid_math.cginc
+++ b/trochoid_math.cginc
@@ -6,83 +6,152 @@
#if defined(_TROCHOID)
-float3 trochoid_map(float theta, float r0, float3 vert_z)
+#define TROCH_POSITION_SCALE 0.1
+#define TROCH_Z_THETA_SCALE 0.0002
+#define TROCH_EPSILON 1e-5
+
+float3 cyl2_to_troch_map(float3 pos)
{
- r0 *= r0;
- r0 *= 100;
+ float theta = pos.x;
float R = _Trochoid_R;
float r = _Trochoid_r;
float d = _Trochoid_d;
- theta *= max(R, r);
- float theta_t = theta + _Time[2];
+ float x = ((R - r) * cos(theta * R) + d * cos((R - r) * theta * R / r)) * pos.y * TROCH_POSITION_SCALE;
+ float y = ((R - r) * sin(theta * R) - d * sin((R - r) * theta * R / r)) * pos.y * TROCH_POSITION_SCALE;
+ float z = (pos.z + cos(theta * R * 5) * TROCH_POSITION_SCALE + theta * R * TROCH_Z_THETA_SCALE) * pos.y;
- float x = (R - r) * cos(theta_t) + d * cos((R - r) * theta_t / r);
- float y = (R - r) * sin(theta_t) - d * sin((R - r) * theta_t / r);
- float z = vert_z + cos(theta_t * 5) * .1 + theta * .0002;
+ return float3(x, y, z);
+}
- float3 result = float3(x, y, z) * r0;
- result.xy *= 0.1;
- return result;
+float3 cyl_to_cyl2_map(float3 v)
+{
+ return float3(v.x, pow(v.y, _Trochoid_Radius_Power) * _Trochoid_Radius_Scale, v.z * _Trochoid_Height_Scale);
}
-float trochoid_normal(float3 objPos, float2 uv)
+float3 cart_to_cyl_map(float3 v)
{
- float theta = uv.x * TAU;
- float r0 = length(objPos.xyz);
-
- float x = objPos.x;
- float y = objPos.y;
- float z = objPos.z;
-
- float e = 5E-2;
- float small_step = 1E-2 * e;
- float du_dt = (trochoid_map(theta + small_step, r0, z) - trochoid_map(theta - small_step, r0, z)) / small_step;
- small_step = 1E-4 * e;
- float du_dr = (trochoid_map(theta, r0 + small_step, z) - trochoid_map(theta, r0 - small_step, z)) / small_step;
- small_step = 1E-5 * e;
- float du_dz = (trochoid_map(theta, r0, z + small_step) - trochoid_map(theta, r0, z - small_step)) / small_step;
-
- // U(T(x, y, z), R(x, y, z), Z(x, y, z))
- // T(x, y, z) = atan2(y, x)
- // R(x, y, z) = length(float3(x, y, z))
- // Z(x, y, z) = z
- // U(a, b, c) = trochoid_map(a, b, c)
- // dU/dx = dU/dT dT/dx + dU/dR dR/dx + dU/dZ dZ/dx
- // dU/dy = dU/dT dT/dy + dU/dR dR/dy + dU/dZ dZ/dy
- // dU/dz = dU/dT dT/dz + dU/dR dR/dz + dU/dZ dZ/dz
- // dT/dx = d/dx atan2(y, x) = -y / (x**2 + y**2)
- // dT/dy = d/dx atan2(y, x) = x / (x**2 + y**2)
- // dT/dz = d/dz atan2(y, x) = 0
- // dR/dx = d/dx sqrt(x**2 + y**2 + z**2) = x / sqrt(x**2 + y**2 + z**2)
- // dR/dy = d/dy sqrt(x**2 + y**2 + z**2) = y / sqrt(x**2 + y**2 + z**2)
- // dR/dz = d/dy sqrt(x**2 + y**2 + z**2) = z / sqrt(x**2 + y**2 + z**2)
- // dZ/dx = 0
- // dZ/dy = 0
- // dZ/dz = 1
- float xy_norm = sqrt(x * x + y * y);
- float dt_dx = -y / xy_norm;
- float dt_dy = x / xy_norm;
- float dt_dz = 0;
- float xyz_norm = sqrt(x * x + y * y + z * z);
- float dr_dx = x / xyz_norm;
- float dr_dy = y / xyz_norm;
- float dr_dz = z / xyz_norm;
- float dz_dx = 0;
- float dz_dy = 0;
- float dz_dz = 1;
-
- float3 normal =
- normalize(
- float3(
- du_dt * dt_dx + du_dr * dr_dx + du_dz * dz_dx,
- du_dt * dt_dy + du_dr * dr_dy + du_dz * dz_dy,
- du_dt * dt_dz + du_dr * dr_dz + du_dz * dz_dz));
- return UnityObjectToWorldNormal(normal);
+ return float3(atan2(v.y, v.x), length(v.xy), v.z);
+}
+
+// Compute partial derivatives of trochoid function with respect to cylindrical coordinates
+float3x3 cyl2_to_troch_jacobian(float3 pos)
+{
+ float theta = pos.x;
+
+ float R = _Trochoid_R;
+ float r = _Trochoid_r;
+ float d = _Trochoid_d;
+
+#if 1
+ float3 df_dt = float3(
+ ((R * (r - R) * (d * sin(R * theta * (R - r) / r) + r * sin(R * theta))) / r) * pos.y * TROCH_POSITION_SCALE,
+ ((R * (r - R) * (-d * cos(R * theta * (R - r) / r) + r * cos(R * theta))) / r) * pos.y * TROCH_POSITION_SCALE,
+ (-R * 5 * sin(theta * R * 5) * TROCH_POSITION_SCALE + R * TROCH_Z_THETA_SCALE) * pos.y);
+ float3 df_dr = float3(
+ ((R - r) * cos(theta * R) + d * cos((R - r) * theta * R / r)) * TROCH_POSITION_SCALE,
+ ((R - r) * sin(theta * R) - d * sin((R - r) * theta * R / r)) * TROCH_POSITION_SCALE,
+ (pos.z + cos(theta * R * 5) * TROCH_POSITION_SCALE + theta * R * TROCH_Z_THETA_SCALE));
+ float3 df_dz = float3(
+ 0,
+ 0,
+ pos.y);
+#else
+ float3 df_dt = (cyl2_to_troch_map(pos + float3(TROCH_EPSILON, 0, 0)) - cyl2_to_troch_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dr = (cyl2_to_troch_map(pos + float3(0, TROCH_EPSILON, 0)) - cyl2_to_troch_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dz = (cyl2_to_troch_map(pos + float3(0, 0, TROCH_EPSILON)) - cyl2_to_troch_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cyl;
+ jacobian_cyl[0] = df_dt;
+ jacobian_cyl[1] = df_dr;
+ jacobian_cyl[2] = df_dz;
+ return transpose(jacobian_cyl);
+}
+
+float3x3 cyl_to_cyl2_jacobian(float3 pos)
+{
+ // f(x, y, z) = <x, (y^_Trochoid_Radius_Power) * _Trochoid_Radius_Scale, z * _Trochoid_Height_Scale>
+#if 1
+ float3 df_dx = float3(1, 0, 0);
+ float3 df_dy = float3(0, _Trochoid_Radius_Power * pow(pos.y, _Trochoid_Radius_Power - 1) * _Trochoid_Radius_Scale, 0);
+ float3 df_dz = float3(0, 0, _Trochoid_Height_Scale);
+#else
+ float3 df_dx = (cyl_to_cyl2_map(pos + float3(TROCH_EPSILON, 0, 0)) - cyl_to_cyl2_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dy = (cyl_to_cyl2_map(pos + float3(0, TROCH_EPSILON, 0)) - cyl_to_cyl2_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+ float3 df_dz = (cyl_to_cyl2_map(pos + float3(0, 0, TROCH_EPSILON)) - cyl_to_cyl2_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cyl_to_cyl2;
+ jacobian_cyl_to_cyl2[0] = df_dx;
+ jacobian_cyl_to_cyl2[1] = df_dy;
+ jacobian_cyl_to_cyl2[2] = df_dz;
+ return transpose(jacobian_cyl_to_cyl2);
+}
+
+// Compute partial derivatives of transform from cartesian to cylindrical coordinates
+float3x3 cart_to_cyl_jacobian(float3 pos)
+{
+ // Compute partial derivatives of transform from cartesian to cylindrical coordinates
+ // return float3(atan2(v.y, v.x), length(v.xy), v.z);
+ // theta = atan2(y, x)
+#if 1
+ float3 dtheta_dcart = float3(
+ -pos.y / dot(pos.xy, pos.xy),
+ pos.x / dot(pos.xy, pos.xy),
+ 0);
+#else
+ float3 dtheta_dcart = (cart_to_cyl_map(pos + float3(TROCH_EPSILON, 0, 0)) - cart_to_cyl_map(pos - float3(TROCH_EPSILON, 0, 0))) / (2 * TROCH_EPSILON);
+#endif
+
+ // radius = (x^2 + y^2)^(1/2)
+#if 1
+ float3 dr_dcart = float3(
+ pos.x / sqrt(pos.x * pos.x + pos.y * pos.y),
+ pos.y / sqrt(pos.x * pos.x + pos.y * pos.y),
+ 0);
+#else
+ float3 dr_dcart = (cart_to_cyl_map(pos + float3(0, TROCH_EPSILON, 0)) - cart_to_cyl_map(pos - float3(0, TROCH_EPSILON, 0))) / (2 * TROCH_EPSILON);
+#endif
+
+#if 1
+ float3 dz_dcart = float3(
+ 0,
+ 0,
+ 1);
+#else
+ float3 dz_dcart = (cart_to_cyl_map(pos + float3(0, 0, TROCH_EPSILON)) - cart_to_cyl_map(pos - float3(0, 0, TROCH_EPSILON))) / (2 * TROCH_EPSILON);
+#endif
+ float3x3 jacobian_cart_to_cyl;
+ jacobian_cart_to_cyl[0] = dtheta_dcart;
+ jacobian_cart_to_cyl[1] = dr_dcart;
+ jacobian_cart_to_cyl[2] = dz_dcart;
+ return transpose(jacobian_cart_to_cyl);
+}
+
+float3x3 invert(float3x3 m)
+{
+ float det = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1])
+ - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0])
+ + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+
+ float3x3 adj;
+ adj[0][0] = (m[1][1] * m[2][2] - m[1][2] * m[2][1]);
+ adj[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]);
+ adj[0][2] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]);
+
+ adj[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]);
+ adj[1][1] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]);
+ adj[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]);
+
+ adj[2][0] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]);
+ adj[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]);
+ adj[2][2] = (m[0][0] * m[1][1] - m[0][1] * m[1][0]);
+
+ return adj * (1.0 / det);
}
#endif // _TROCHOID
#endif // __TROCHOID_MATH
+