summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-01-14 21:01:26 -0800
committeryum <yum.food.vr@gmail.com>2025-01-14 21:01:28 -0800
commit333562544ef1b71a7a4d7ce1ece533bef98ce0da (patch)
treec9620943f8a772db0da777e1aa759b30adb17925
parentab441140208d6dd8317f328f40a25c6054f1a304 (diff)
im going to kill myself
attempt to fix hypotrochoid normals key insight is that multiplying normal by transpose(invert(jacobian)) of transform should work, but it fucking doesn't
-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
+