diff options
| -rw-r--r-- | 3ner.shader | 9 | ||||
| -rw-r--r-- | globals.cginc | 16 | ||||
| -rw-r--r-- | vertex.cginc | 27 | ||||
| -rw-r--r-- | vertex_deformation.slang | 87 |
4 files changed, 105 insertions, 34 deletions
diff --git a/3ner.shader b/3ner.shader index 1334699..249f02b 100644 --- a/3ner.shader +++ b/3ner.shader @@ -207,6 +207,9 @@ Shader "yum_food/3ner" //ifex _Vertex_Deformation_XZ_Tube_Enabled==0 [HideInInspector] m_start_Vertex_Deformation_XZ_Tube("XZ Tube", Float) = 0 [ThryToggle(_VERTEX_DEFORMATION_XZ_TUBE)] _Vertex_Deformation_XZ_Tube_Enabled("Enable", Float) = 0 + _Vertex_Deformation_XZ_Tube_p("p", Vector) = (0, 0, 1) + _Vertex_Deformation_XZ_Tube_r("r", Vector) = (0, 0, -1) + _Vertex_Deformation_XZ_Tube_r("s", Vector) = (0, 0, -1) _Vertex_Deformation_XZ_Tube_t("t", Range(-1,1)) = 0 [HideInInspector] m_end_Vertex_Deformation_XZ_Tube("XZ Tube", Float) = 0 //endex @@ -214,6 +217,9 @@ Shader "yum_food/3ner" //ifex _Vertex_Deformation_YZ_Tube_Enabled==0 [HideInInspector] m_start_Vertex_Deformation_YZ_Tube("YZ Tube", Float) = 0 [ThryToggle(_VERTEX_DEFORMATION_YZ_TUBE)] _Vertex_Deformation_YZ_Tube_Enabled("Enable", Float) = 0 + _Vertex_Deformation_YZ_Tube_p("p", Vector) = (0, 0, 1) + _Vertex_Deformation_YZ_Tube_r("r", Vector) = (0, 0, -1) + _Vertex_Deformation_YZ_Tube_s("s", Vector) = (0, 0, -1) _Vertex_Deformation_YZ_Tube_t("t", Range(-1,1)) = 0 [HideInInspector] m_end_Vertex_Deformation_YZ_Tube("YZ Tube", Float) = 0 //endex @@ -221,6 +227,9 @@ Shader "yum_food/3ner" //ifex _Vertex_Deformation_XY_Tube_Enabled==0 [HideInInspector] m_start_Vertex_Deformation_XY_Tube("XY Tube", Float) = 0 [ThryToggle(_VERTEX_DEFORMATION_XY_TUBE)] _Vertex_Deformation_XY_Tube_Enabled("Enable", Float) = 0 + _Vertex_Deformation_XY_Tube_p("p", Vector) = (0, 0, 1) + _Vertex_Deformation_XY_Tube_r("r", Vector) = (0, 0, -1) + _Vertex_Deformation_XY_Tube_s("s", Vector) = (0, 0, -1) _Vertex_Deformation_XY_Tube_t("t", Range(-1,1)) = 0 [HideInInspector] m_end_Vertex_Deformation_XY_Tube("XY Tube", Float) = 0 //endex diff --git a/globals.cginc b/globals.cginc index 4e03e0b..c838091 100644 --- a/globals.cginc +++ b/globals.cginc @@ -75,9 +75,6 @@ float3 _Cloth_Sheen_Color; texture2D _Cloth_Sheen_DFG_LUT; #endif // _CLOTH_SHEEN -#if defined(_VERTEX_DEFORMATION_XY_TUBE) -float _Vertex_Deformation_XY_Tube_t; -#endif // _VERTEX_DEFORMATION_XY_TUBE #if defined(_VERTEX_DEFORMATION_XY_UNTUBE) float _Vertex_Deformation_XY_Untube_t; #endif // _VERTEX_DEFORMATION_XY_UNTUBE @@ -87,10 +84,23 @@ float _Vertex_Deformation_XZ_Untube_t; #if defined(_VERTEX_DEFORMATION_YZ_UNTUBE) float _Vertex_Deformation_YZ_Untube_t; #endif // _VERTEX_DEFORMATION_YZ_UNTUBE + +#if defined(_VERTEX_DEFORMATION_XY_TUBE) +float3 _Vertex_Deformation_XY_Tube_p; +float3 _Vertex_Deformation_XY_Tube_r; +float3 _Vertex_Deformation_XY_Tube_s; +float _Vertex_Deformation_XY_Tube_t; +#endif // _VERTEX_DEFORMATION_XY_TUBE #if defined(_VERTEX_DEFORMATION_XZ_TUBE) +float3 _Vertex_Deformation_XZ_Tube_p; +float3 _Vertex_Deformation_XZ_Tube_r; +float3 _Vertex_Deformation_XZ_Tube_s; float _Vertex_Deformation_XZ_Tube_t; #endif // _VERTEX_DEFORMATION_XZ_TUBE #if defined(_VERTEX_DEFORMATION_YZ_TUBE) +float3 _Vertex_Deformation_YZ_Tube_p; +float3 _Vertex_Deformation_YZ_Tube_r; +float3 _Vertex_Deformation_YZ_Tube_s; float _Vertex_Deformation_YZ_Tube_t; #endif // _VERTEX_DEFORMATION_YZ_TUBE diff --git a/vertex.cginc b/vertex.cginc index f82fad6..daa5ce0 100644 --- a/vertex.cginc +++ b/vertex.cginc @@ -61,11 +61,14 @@ #if defined(_VERTEX_DEFORMATION_XZ_TUBE) #define VERTEX_DEFORM_XZ_TUBE_PREAMBLE \ + float3 p = _Vertex_Deformation_XZ_Tube_p; \ + float3 r = _Vertex_Deformation_XZ_Tube_r; \ + float3 s = _Vertex_Deformation_XZ_Tube_s; \ float t = _Vertex_Deformation_XZ_Tube_t #define VERTEX_DEFORM_XZ_TUBE_POS \ - objPos = plane_to_tube(objPos.xyz, t) + objPos = plane_to_tube(objPos.xyz, p, r, s, t) #define VERTEX_DEFORM_XZ_TUBE_NORM \ - plane_to_tube_normal(objPos, objNorm, objTan, t) + plane_to_tube_normal(objPos.xyz, objNorm, objTan, p, r, s, t) #else #define VERTEX_DEFORM_XZ_TUBE_PREAMBLE #define VERTEX_DEFORM_XZ_TUBE_POS @@ -74,15 +77,18 @@ #if defined(_VERTEX_DEFORMATION_YZ_TUBE) #define VERTEX_DEFORM_YZ_TUBE_PREAMBLE \ + float3 p = _Vertex_Deformation_YZ_Tube_p; \ + float3 r = _Vertex_Deformation_YZ_Tube_r; \ + float3 s = _Vertex_Deformation_YZ_Tube_s; \ float t = _Vertex_Deformation_YZ_Tube_t #define VERTEX_DEFORM_YZ_TUBE_POS \ - objPos = plane_to_tube(objPos.yxz, t); \ + objPos = plane_to_tube(objPos.yxz, p, r, s, t); \ objPos = objPos.yxz #define VERTEX_DEFORM_YZ_TUBE_NORM \ float3 yzPos = objPos.yxz; \ float3 yzNorm = objNorm.yxz; \ float3 yzTan = objTan.yxz; \ - plane_to_tube_normal(yzPos, yzNorm, yzTan, t); \ + plane_to_tube_normal(yzPos, yzNorm, yzTan, p, r, s, t); \ objPos = yzPos.yxz; \ objNorm = yzNorm.yxz; \ objTan = yzTan.yxz @@ -94,15 +100,18 @@ #if defined(_VERTEX_DEFORMATION_XY_TUBE) #define VERTEX_DEFORM_XY_TUBE_PREAMBLE \ + float3 p = _Vertex_Deformation_XY_Tube_p; \ + float3 r = _Vertex_Deformation_XY_Tube_r; \ + float3 s = _Vertex_Deformation_XY_Tube_s; \ float t = _Vertex_Deformation_XY_Tube_t #define VERTEX_DEFORM_XY_TUBE_POS \ - objPos = plane_to_tube(objPos.xzy, t); \ + objPos = plane_to_tube(objPos.xzy, p, r, s, t); \ objPos = objPos.xzy #define VERTEX_DEFORM_XY_TUBE_NORM \ float3 xyPos = objPos.xzy; \ float3 xyNorm = objNorm.xzy; \ float3 xyTan = objTan.xzy; \ - plane_to_tube_normal(xyPos, xyNorm, xyTan, t); \ + plane_to_tube_normal(xyPos, xyNorm, xyTan, p, r, s, t); \ objPos = xyPos.xzy; \ objNorm = xyNorm.xzy; \ objTan = xyTan.xzy @@ -406,7 +415,7 @@ void undeform_normal(inout float3 objPos, inout float3 objNorm, inout float3 obj float3 xyPos = stageInput.xzy; float3 xyNorm = objNorm.xzy; float3 xyTan = objTan.xzy; - plane_to_tube_undeform_normal(xyPos, xyNorm, xyTan, t); + plane_to_tube_undeform_normal(xyPos, xyNorm, xyTan, p, r, s, t); objNorm = xyNorm.xzy; objTan = xyTan.xzy; objPos = stageInput; @@ -420,7 +429,7 @@ void undeform_normal(inout float3 objPos, inout float3 objNorm, inout float3 obj float3 yzPos = stageInput.yxz; float3 yzNorm = objNorm.yxz; float3 yzTan = objTan.yxz; - plane_to_tube_undeform_normal(yzPos, yzNorm, yzTan, t); + plane_to_tube_undeform_normal(yzPos, yzNorm, yzTan, p, r, s, t); objNorm = yzNorm.yxz; objTan = yzTan.yxz; objPos = stageInput; @@ -431,7 +440,7 @@ void undeform_normal(inout float3 objPos, inout float3 objNorm, inout float3 obj if (cursor > 0) { VERTEX_DEFORM_XZ_TUBE_PREAMBLE; float3 stageInput = posHistory[cursor - 1]; - plane_to_tube_undeform_normal(stageInput, objNorm, objTan, t); + plane_to_tube_undeform_normal(stageInput, objNorm, objTan, p, r, s, t); objPos = stageInput; cursor -= 1; } diff --git a/vertex_deformation.slang b/vertex_deformation.slang index 577b0d2..f22e71f 100644 --- a/vertex_deformation.slang +++ b/vertex_deformation.slang @@ -5,6 +5,8 @@ #define PI_RCP 0.31830988f #define TAU (2.0f * PI) #define HALF_PI (0.5f * PI) +#define RCP_PI (1.0f / PI) +#define RCP_TAU (1.0f / TAU) #define glsl_mod(x,y) (((x)-(y)*floor((x)/(y)))) @@ -65,7 +67,8 @@ R3R3_DEFORM_NORMAL_AND_TANGENT(normal, tangent); \ xyz = fun(xyz, __VA_ARGS__) -float3x3 inverse(float3x3 m, float det) { +[Differentiable] +float3x3 inverse(no_diff float3x3 m, no_diff float det) { det = max(1e-6 * abs(det), abs(det)) * sign(det); float invDet = 1.0f / det; @@ -84,34 +87,70 @@ float3x3 inverse(float3x3 m, float det) { return inv; } +float2 project_x_onto_y(float2 x, float2 y) { + return (dot(x, y) / dot(y, y)) * y; +} + // Maps a 2x2 quad on the xy plane to a tube. The circular cross section // is on the xz plane. [Differentiable] -public float3 plane_to_tube(float3 xyz, no_diff float t) { - float x0 = xyz.x; - float y0 = xyz.y; - float z0 = xyz.z; - - float theta = x0 * PI; - - // Equivalent to (1 / (|t| + eps)) * sign(t) - float radius = 1.0f / (dabs(t) + 1e-4f) * sign(t); +public float3 plane_to_tube(float3 xyz, no_diff float3 p, no_diff float3 r, no_diff float3 s, no_diff float t) { + xyz = 0; + // Convert from cartesian to (r, s, r x s) space. + // Ensure orthonormal basis vectors. + // TODO remove normalize, do at higher level of stack. + r = normalize(r); + s = normalize(s); + float3 rxs = cross(r, s); + float3x3 to_rsrxs = transpose(float3x3(r, s, rxs)); + float3x3 to_cart = inverse(to_rsrxs, determinant(to_rsrxs)); + + // Translate origin to `p` then change into (r, s, r x s) basis. + xyz = mul(to_rsrxs, xyz - p); + + // Project onto (r, r x s) plane. + float2 v0 = xyz.xz; + + float2 v0_hat = normalize(v0); + float2 Lr = float2(v0.x, 0); + float2 Lv0 = float2(0, v0.y); + float Lr_norm = abs(Lr.x); + float Lv0_norm = abs(Lv0.y); + float epsilon = 1e-4; + float theta = Lv0_norm / (Lr_norm + epsilon); + float phi = atan2(Lv0_norm, Lr_norm); + float theta_p = lerp(theta, phi, t); + float2x2 rot = float2x2( + cos(theta_p), -sin(theta_p), + sin(theta_p), cos(theta_p)); + + // float2(1, 0) is written as `r` in (2) in the notes. We just rewrite it + // here since we're in the rotated frame. + // We also don't have to add p since again we're in the rotated and + // translated frame. + float2 v = mul(rot, dlerp(float2(1, 0) * Lv0_norm, Lr, t)); + + // Un-project. + xyz.xz = v.xy; + + // Move back into cartesian basis. + xyz = mul(to_cart, xyz); + + // Translate p back away from origin. + xyz += p; - float x = sin(theta / radius) * (radius * PI_RCP - z0); - float z = (1.0f - cos(theta / radius)) * (radius * PI_RCP) + cos(theta / radius) * z0; - - return float3(x, y0, z); + return xyz; } public void plane_to_tube_normal(inout float3 xyz, inout float3 normal, - inout float3 tangent, float t) { - R3R3_NORMALS(xyz, normal, tangent, plane_to_tube, t); + inout float3 tangent, float3 p, float3 r, float3 s, float t) { + R3R3_NORMALS(xyz, normal, tangent, plane_to_tube, p, r, s, t); } public void plane_to_tube_undeform_normal(float3 xyz, inout float3 normal, - inout float3 tangent, float t) { + inout float3 tangent, float3 p, float3 r, float3 s, float t) { R3R3_DECLARE_BASIS_VECTORS(xyz); - R3R3_AUTODIFF_BASIS_VECTORS(plane_to_tube, t); + R3R3_AUTODIFF_BASIS_VECTORS(plane_to_tube, p, r, s, t); R3R3_UNDEFORM_NORMAL_AND_TANGENT(normal, tangent); } @@ -123,10 +162,15 @@ public float3 tube_to_plane(float3 xyz, no_diff float t) { float y0 = xyz.y; float z0 = xyz.z; - float theta = atan2(z0, x0) - PI; + // Tube has 2m circumference. + // C = pi d = 2 pi r + // r = C / (2 pi) = 2 / 2 pi = 1 / pi + float ref_r = RCP_PI; + float theta = atan2(z0 - ref_r, x0 - ref_r) - PI; float r = length(float2(x0, z0)); - x0 = r * cos(theta); - z0 = r * sin(theta); + + x0 = x0 + r * cos(theta); + z0 = z0 - r * sin(theta); // Equivalent to (1 / (|t| + eps)) * sign(t) float radius = 1.0f / (dabs(t) + 1e-4f) * sign(t); @@ -245,7 +289,6 @@ float rand3_hash1(float3 p) // Calculate value noise and jacobian in one shot. // Based on https://iquilezles.org/articles/morenoise/ -[Differentiable] float3 value_noise(float3 xyz, out float3 dx, out float3 dy, out float3 dz) { float3 cell = floor(xyz); float3 f = xyz - cell; |
