summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-01-28 08:48:27 -0800
committeryum <yum.food.vr@gmail.com>2025-01-28 08:48:27 -0800
commit2e506cd621f3d8e7448128a7a93066f68fc37087 (patch)
treeee4fc3bef468bae650bb8e964eabf102266c8135
parentdfe6371283f2415804b4341dbac71f79188ea890 (diff)
Yellow abomination now faces camera and grows as it gets farther
-rw-r--r--Editor/tooner.cs2
-rw-r--r--globals.cginc1
-rw-r--r--tooner.shader1
-rw-r--r--tooner_lighting.cginc3
-rw-r--r--zwrite_abomination.cginc65
5 files changed, 67 insertions, 5 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index 041e096..5431c3e 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -2918,6 +2918,8 @@ public class ToonerGUI : ShaderGUI {
FloatProperty(bc, "Initial step size");
bc = FindProperty("_Gimmick_ZWrite_Abomination_Global_Scale");
FloatProperty(bc, "Global scale");
+ bc = FindProperty("_Gimmick_ZWrite_Abomination_Vertex_Expansion_Factor");
+ FloatProperty(bc, "Vertex expansion factor");
bc = FindProperty("_Gimmick_ZWrite_Abomination_Body_Half_Height");
FloatProperty(bc, "Body half height");
diff --git a/globals.cginc b/globals.cginc
index 35a56d5..4f8e6dd 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -1016,6 +1016,7 @@ float _Gimmick_ZWrite_Abomination_March_Steps;
float _Gimmick_ZWrite_Abomination_Normal_Epsilon;
float _Gimmick_ZWrite_Abomination_Initial_Step_Size;
float _Gimmick_ZWrite_Abomination_Global_Scale;
+float _Gimmick_ZWrite_Abomination_Vertex_Expansion_Factor;
float _Gimmick_ZWrite_Abomination_Body_Half_Height;
float _Gimmick_ZWrite_Abomination_Body_Radius;
diff --git a/tooner.shader b/tooner.shader
index 811cbff..9c21f7b 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -1094,6 +1094,7 @@ Shader "yum_food/tooner"
_Gimmick_ZWrite_Abomination_Normal_Epsilon("Normal epsilon", Float) = 0.001
_Gimmick_ZWrite_Abomination_Initial_Step_Size("Initial step size", Float) = 0.001
_Gimmick_ZWrite_Abomination_Global_Scale("Global scale", Float) = 1
+ _Gimmick_ZWrite_Abomination_Vertex_Expansion_Factor("Vertex expansion factor", Float) = 1
_Gimmick_ZWrite_Abomination_Body_Half_Height("Body half height", Float) = 0.1
_Gimmick_ZWrite_Abomination_Body_Radius("Body radius", Float) = 0.1
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index 2e2a254..7338d70 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -153,6 +153,9 @@ v2f vert(appdata v)
v.vertex.xyz = cart_to_troch_map(v.vertex.xyz);
}
#endif // _TROCHOID
+#if defined(_GIMMICK_ZWRITE_ABOMINATION)
+ v.vertex.xyz *= _Gimmick_ZWrite_Abomination_Vertex_Expansion_Factor;
+#endif
#if defined(_FACE_ME_WORLD_Y)
if (_FaceMeWorldY_Enable_Dynamic) {
// Undo object coordinate system rotation.
diff --git a/zwrite_abomination.cginc b/zwrite_abomination.cginc
index bba03e1..ae171c3 100644
--- a/zwrite_abomination.cginc
+++ b/zwrite_abomination.cginc
@@ -32,6 +32,8 @@ struct ZWriteAbominationPBR {
float zwrite_abomination_map(float3 p, out uint body_part) {
float epsilon = 1E-4;
float d;
+ float s = _Gimmick_ZWrite_Abomination_Global_Scale;
+ p = p / s; // Scale all positions first
// Capsule representing body
{
@@ -59,7 +61,6 @@ float zwrite_abomination_map(float3 p, out uint body_part) {
float3 pp = p;
pp.x = abs(pp.x);
pp -= strap_center;
- // Rotate about z axis
float theta = _Gimmick_ZWrite_Abomination_Denim_Strap_Z_Theta;
float2x2 rot = float2x2(float2(cos(theta), -sin(theta)), float2(sin(theta), cos(theta)));
pp.xy = mul(rot, pp.xy);
@@ -81,7 +82,6 @@ float zwrite_abomination_map(float3 p, out uint body_part) {
float lens_depth = _Gimmick_ZWrite_Abomination_Lens_Depth;
float lens_thickness = _Gimmick_ZWrite_Abomination_Lens_Thickness;
float lens_d0 = distance_from_capped_cylinder(pp, lens_depth, lens_radius);
- // TODO do we need a capped cylinder? Can we use a more efficient SDF to cut out the middle?
float lens_d1 = distance_from_capped_cylinder(pp, lens_depth + 0.1, lens_radius - lens_thickness);
float lens_d = op_sub(lens_d1, lens_d0);
body_part = lens_d < d ? BODY_PART_LENS : body_part;
@@ -147,7 +147,7 @@ float zwrite_abomination_map(float3 p, out uint body_part) {
d = min(d, leg_d);
}
- return d;
+ return d * s;
}
// TODO tetrahedral normals
@@ -166,8 +166,60 @@ ZWriteAbominationPBR zwrite_abomination(in v2f i)
float3 cam_pos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
float3 rd = normalize(i.objPos - cam_pos);
float3 ro = cam_pos + rd * _Gimmick_ZWrite_Abomination_Initial_Step_Size;
+ float l = length(ro);
+ float scale_factor = pow(l, 1.5);
+ ro /= scale_factor;
- // TODO raytrace ro near the object
+ float3 forward_axis = float3(0, 0, 1);
+ // We apply a factor of -1 to shift the result forward by a phase shift of pi.
+ float cos_t = -dot(normalize(rd.xz), forward_axis.xz);
+ // We want to get sin(t) using the identity:
+ // || a x b || = || a || || b || sin(t)
+ // For normal vectors, this simplifies to:
+ // || a x b || = sin(t)
+ // The issue is that the norm operator loses the sign.
+ // We can estimate the sign by assuming that `rd` and `forward_axis` are on
+ // the xz plane.
+ // If that's the case, then the cross product is necessarily constrained to
+ // the y axis.
+ float sin_t_sign = sign(cross(rd, forward_axis).y);
+ // Here we use the identity:
+ // sin(t) = sqrt(1 - cos(t)^2)
+ // We simply apply the sign correction `sin_t_sign` to the result.
+ // We then invert it, since the goal is not to amplify the rotation, but
+ // to negate it.
+ // Finally, we add a phase correction to make the abomination face us.
+ float sin_t = sqrt(1 - cos_t * cos_t) * sin_t_sign;
+ float2x2 face_me_rot = float2x2(cos_t, -sin_t, sin_t, cos_t);
+ float2x2 face_me_rot_inv = float2x2(cos_t, sin_t, -sin_t, cos_t);
+ ro.xz = mul(face_me_rot, ro.xz);
+ rd.xz = mul(face_me_rot, rd.xz);
+
+ // Raytrace ro onto sphere containing sim
+
+#if 0
+ {
+ bool no_intersection = false;
+ float distance_to_sphere = 1E6;
+ float circle_radius = 0.5 * scale_factor;
+ {
+ float3 l = ro;
+ float a = 1;
+ float b = 2 * dot(rd, l);
+ float c = dot(l, l) - circle_radius * circle_radius;
+ float t0, t1;
+ if (solveQuadratic(a, b, c, t0, t1)) {
+ no_intersection = (t0 < 0) * (t1 < 0);
+ const bool inside_sphere = (t0 < 0) * (t1 > 0);
+ if (!inside_sphere) {
+ distance_to_sphere = no_intersection ? distance_to_sphere : min(max(t0, 0), max(t1, 0));
+ ro += distance_to_sphere * rd;
+ }
+ }
+ }
+ clip(no_intersection ? -1 : 1);
+ }
+#endif
const float MIN_HIT_DIST = _Gimmick_ZWrite_Abomination_Min_Hit_Dist;
const float MAX_DIST = 1;
@@ -228,7 +280,10 @@ ZWriteAbominationPBR zwrite_abomination(in v2f i)
pbr.albedo = float4(c, 1);
pbr.metallic = metallic;
pbr.roughness = roughness;
- pbr.normal = UnityObjectToWorldNormal(zwrite_abomination_normal(p));
+ float3 normal = zwrite_abomination_normal(p);
+ // TODO inverse of this matrix?
+ normal.xz = mul(face_me_rot_inv, normal.xz);
+ pbr.normal = UnityObjectToWorldNormal(normal);
float4 clip_pos = mul(UNITY_MATRIX_VP, float4(mul(unity_ObjectToWorld, float4(p, 1.0))));
pbr.depth = clip_pos.z / clip_pos.w;
} else {