yum/3ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum/3ner

yumFold: move operations into separate filec09509e

master
12.1 KiB285 linesraw
1using UnityEditor;
2using UnityEngine;
3
4// ─── Operation base class ─────────────────────────────────────────────────────
5
6[System.Serializable]
7public abstract class DeformOperation
8{
9    public abstract string GetDisplayName();
10    public virtual void DrawParameters() { }
11    public abstract void ApplyTo(FoldPipelineBuilder builder);
12
13    public static DeformOperation Create(FoldSlot slot) =>
14        slot.opcode switch
15        {
16            TubeToPlaneOp.Opcode           => new TubeToPlaneOp(slot),
17            PlaneToTubeOp.Opcode           => new PlaneToTubeOp(slot),
18            PlaneToHemiOctahedronOp.Opcode => new PlaneToHemiOctahedronOp(slot),
19            HemiOctahedronToPlaneOp.Opcode => new HemiOctahedronToPlaneOp(slot),
20            ScaleOp.Opcode                 => new ScaleOp(slot),
21            TranslateOp.Opcode             => new TranslateOp(slot),
22            PlaneToOctahedronOp.Opcode     => new PlaneToOctahedronOp(slot),
23            OctahedronToPlaneOp.Opcode     => new OctahedronToPlaneOp(slot),
24            RotateOp.Opcode                => new RotateOp(slot),
25            PointAlignOp.Opcode            => new PointAlignOp(slot),
26            AxisAlignOp.Opcode             => new AxisAlignOp(slot),
27            NormConversionOp.Opcode        => new NormConversionOp(slot),
28            SealOp.Opcode                  => new SealOp(slot),
29            SineWavesOp.Opcode             => new SineWavesOp(),
30            FBMOp.Opcode                   => new FBMOp(),
31            _                              => null
32        };
33
34    protected static void DrawPrsParams(ref Vector3 p, ref Vector3 r, ref Vector3 s, ref float t)
35    {
36        p = EditorGUILayout.Vector3Field("Origin (p)", p);
37        r = EditorGUILayout.Vector3Field("R Axis", r);
38        s = EditorGUILayout.Vector3Field("S Axis", s);
39        t = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
40    }
41
42    protected static void DrawAlignParams(ref Vector3 po, ref Vector3 pp, ref Vector3 r, ref float t)
43    {
44        po = EditorGUILayout.Vector3Field("Origin Point (po)", po);
45        pp = EditorGUILayout.Vector3Field("Target Point (pp)", pp);
46        r  = EditorGUILayout.Vector3Field("Rotation Axis (r)", r);
47        t  = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
48    }
49}
50
51// ─── Concrete operations ──────────────────────────────────────────────────────
52
53[System.Serializable]
54public class TubeToPlaneOp : DeformOperation
55{
56    public const int Opcode = 1;
57    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
58    public float t = 1f;
59    public TubeToPlaneOp() { }
60    public TubeToPlaneOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
61    public override string GetDisplayName() => "Tube to Plane";
62    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
63    public override void ApplyTo(FoldPipelineBuilder b) => b.TubeToPlane(p, r, s, t);
64}
65
66[System.Serializable]
67public class PlaneToTubeOp : DeformOperation
68{
69    public const int Opcode = 2;
70    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
71    public float t = 1f;
72    public PlaneToTubeOp() { }
73    public PlaneToTubeOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
74    public override string GetDisplayName() => "Plane to Tube";
75    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
76    public override void ApplyTo(FoldPipelineBuilder b) => b.PlaneToTube(p, r, s, t);
77}
78
79[System.Serializable]
80public class PlaneToHemiOctahedronOp : DeformOperation
81{
82    public const int Opcode = 9;
83    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
84    public float t = 1f;
85    public PlaneToHemiOctahedronOp() { }
86    public PlaneToHemiOctahedronOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
87    public override string GetDisplayName() => "Plane to Hemi-Octahedron";
88    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
89    public override void ApplyTo(FoldPipelineBuilder b) => b.PlaneToHemiOctahedron(p, r, s, t);
90}
91
92[System.Serializable]
93public class HemiOctahedronToPlaneOp : DeformOperation
94{
95    public const int Opcode = 10;
96    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
97    public float t = 1f;
98    public HemiOctahedronToPlaneOp() { }
99    public HemiOctahedronToPlaneOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
100    public override string GetDisplayName() => "Hemi-Octahedron to Plane";
101    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
102    public override void ApplyTo(FoldPipelineBuilder b) => b.HemiOctahedronToPlane(p, r, s, t);
103}
104
105[System.Serializable]
106public class PlaneToOctahedronOp : DeformOperation
107{
108    public const int Opcode = 13;
109    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
110    public float t = 1f;
111    public PlaneToOctahedronOp() { }
112    public PlaneToOctahedronOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
113    public override string GetDisplayName() => "Plane to Octahedron";
114    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
115    public override void ApplyTo(FoldPipelineBuilder b) => b.PlaneToOctahedron(p, r, s, t);
116}
117
118[System.Serializable]
119public class OctahedronToPlaneOp : DeformOperation
120{
121    public const int Opcode = 14;
122    public Vector3 p = Vector3.zero, r = Vector3.right, s = Vector3.forward;
123    public float t = 1f;
124    public OctahedronToPlaneOp() { }
125    public OctahedronToPlaneOp(FoldSlot slot) { p = slot.vec0; r = slot.vec1; s = slot.vec2; t = slot.float0; }
126    public override string GetDisplayName() => "Octahedron to Plane";
127    public override void DrawParameters() => DrawPrsParams(ref p, ref r, ref s, ref t);
128    public override void ApplyTo(FoldPipelineBuilder b) => b.OctahedronToPlane(p, r, s, t);
129}
130
131[System.Serializable]
132public class PointAlignOp : DeformOperation
133{
134    public const int Opcode = 3;
135    public Vector3 po = Vector3.zero, pp = Vector3.up, r = Vector3.right;
136    public float t = 1f;
137    public PointAlignOp() { }
138    public PointAlignOp(FoldSlot slot) { po = slot.vec0; pp = slot.vec1; r = slot.vec2; t = slot.float0; }
139    public override string GetDisplayName() => "Point Align";
140    public override void DrawParameters() => DrawAlignParams(ref po, ref pp, ref r, ref t);
141    public override void ApplyTo(FoldPipelineBuilder b) => b.PointAlign(po, pp, r, t);
142}
143
144[System.Serializable]
145public class AxisAlignOp : DeformOperation
146{
147    public const int Opcode = 4;
148    public Vector3 po = Vector3.zero, pp = Vector3.up, r = Vector3.right;
149    public float t = 1f;
150    public AxisAlignOp() { }
151    public AxisAlignOp(FoldSlot slot) { po = slot.vec0; pp = slot.vec1; r = slot.vec2; t = slot.float0; }
152    public override string GetDisplayName() => "Axis Align";
153    public override void DrawParameters() => DrawAlignParams(ref po, ref pp, ref r, ref t);
154    public override void ApplyTo(FoldPipelineBuilder b) => b.AxisAlign(po, pp, r, t);
155}
156
157[System.Serializable]
158public class ScaleOp : DeformOperation
159{
160    public const int Opcode = 11;
161    public Vector3 k = Vector3.one;
162    public float t = 1f;
163
164    public ScaleOp() { }
165    public ScaleOp(FoldSlot slot) { k = slot.vec0; t = slot.float0; }
166
167    public override string GetDisplayName() => "Scale";
168    public override void DrawParameters()
169    {
170        k = EditorGUILayout.Vector3Field("Scale", k);
171        t = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
172    }
173    public override void ApplyTo(FoldPipelineBuilder b) => b.Scale(k, t);
174}
175
176[System.Serializable]
177public class TranslateOp : DeformOperation
178{
179    public const int Opcode = 12;
180    public Vector3 offset = Vector3.zero;
181    public float t = 1f;
182
183    public TranslateOp() { }
184    public TranslateOp(FoldSlot slot) { offset = slot.vec0; t = slot.float0; }
185
186    public override string GetDisplayName() => "Translate";
187    public override void DrawParameters()
188    {
189        offset = EditorGUILayout.Vector3Field("Offset", offset);
190        t = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
191    }
192    public override void ApplyTo(FoldPipelineBuilder b) => b.Translate(offset, t);
193}
194
195[System.Serializable]
196public class RotateOp : DeformOperation
197{
198    public const int Opcode = 15;
199    public Vector3 center = Vector3.zero, axis = Vector3.up;
200    public float angleDeg = 90f, t = 1f;
201
202    public RotateOp() { }
203    public RotateOp(FoldSlot slot) { center = slot.vec0; axis = slot.vec1; angleDeg = slot.float0 * Mathf.Rad2Deg; t = slot.float1; }
204
205    public override string GetDisplayName() => "Rotate";
206    public override void DrawParameters()
207    {
208        center   = EditorGUILayout.Vector3Field("Center", center);
209        axis     = EditorGUILayout.Vector3Field("Axis", axis);
210        angleDeg = EditorGUILayout.Slider("Angle", angleDeg, 0f, 360f);
211        t        = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
212    }
213    public override void ApplyTo(FoldPipelineBuilder b) => b.Rotate(center, axis, angleDeg * Mathf.Deg2Rad, t);
214}
215
216[System.Serializable]
217public class NormConversionOp : DeformOperation
218{
219    public const int Opcode = 5;
220    public float inputK = 2f, outputK = 1f, t = 1f;
221
222    public NormConversionOp() { }
223    public NormConversionOp(FoldSlot slot) { inputK = slot.float0; outputK = slot.float1; t = slot.float2; }
224
225    public override string GetDisplayName() => $"Norm Conversion (L{FormatNorm(inputK)}→L{FormatNorm(outputK)})";
226    string FormatNorm(float k) => float.IsPositiveInfinity(k) ? "∞" : k.ToString("F1");
227
228    public override void DrawParameters()
229    {
230        EditorGUILayout.BeginHorizontal();
231        EditorGUILayout.LabelField("Input Norm (k)", GUILayout.Width(120));
232        inputK = EditorGUILayout.FloatField(inputK);
233        if (GUILayout.Button("L∞", GUILayout.Width(30))) inputK = float.PositiveInfinity;
234        EditorGUILayout.EndHorizontal();
235
236        EditorGUILayout.BeginHorizontal();
237        EditorGUILayout.LabelField("Output Norm (k)", GUILayout.Width(120));
238        outputK = EditorGUILayout.FloatField(outputK);
239        if (GUILayout.Button("L∞", GUILayout.Width(30))) outputK = float.PositiveInfinity;
240        EditorGUILayout.EndHorizontal();
241
242        t = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
243        EditorGUILayout.HelpBox("Common: L1=diamond, L2=sphere, L∞=cube", MessageType.Info);
244    }
245
246    public override void ApplyTo(FoldPipelineBuilder b) => b.NormConversion(inputK, outputK, t);
247}
248
249[System.Serializable]
250public class SealOp : DeformOperation
251{
252    public const int Opcode = 6;
253    public float A = 0.1f, k = 2f, st = 0.8f, t = 1f;
254
255    public SealOp() { }
256    public SealOp(FoldSlot slot) { A = slot.float0; k = slot.float1; st = slot.float2; t = slot.float3; }
257
258    public override string GetDisplayName() => "Seal";
259    public override void DrawParameters()
260    {
261        A  = EditorGUILayout.FloatField("Amplitude (A)", A);
262        k  = EditorGUILayout.FloatField("Smoothness (k)", k);
263        st = EditorGUILayout.FloatField("Scale (st)", st);
264        t  = EditorGUILayout.Slider("Interpolation (t)", t, 0f, 1f);
265    }
266    public override void ApplyTo(FoldPipelineBuilder b) => b.Seal(A, k, st, t);
267}
268
269[System.Serializable]
270public class SineWavesOp : DeformOperation
271{
272    public const int Opcode = 7;
273    public override string GetDisplayName() => "Sine Waves";
274    public override void DrawParameters() => EditorGUILayout.HelpBox("Uses shader-side parameters", MessageType.Info);
275    public override void ApplyTo(FoldPipelineBuilder b) => b.SineWaves();
276}
277
278[System.Serializable]
279public class FBMOp : DeformOperation
280{
281    public const int Opcode = 8;
282    public override string GetDisplayName() => "FBM (Fractal Brownian Motion)";
283    public override void DrawParameters() => EditorGUILayout.HelpBox("Uses shader-side parameters", MessageType.Info);
284    public override void ApplyTo(FoldPipelineBuilder b) => b.FBM();
285}