yum/3ner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum/3ner
c09509e
master
1using System ; 2using System . Collections . Generic ; 3using UnityEditor ; 4using UnityEngine ; 5 6public class FoldSlot 7{ 8public int opcode ; 9public float float0 , float1 , float2 , float3 ; 10public Vector4 vec0 , vec1 , vec2 , vec3 ; 11 12static string Prefix ( int i ) => $"_Vertex_Deformation_Slot_ { i } _" ; 13 14void ApplyToTarget ( string pfx , Action < string , float > sf , Action < string , int > si , Action < string , Vector4 > sv ) 15{ 16sf ( pfx + "Enabled" , 1f ); 17si ( pfx + "Opcode" , opcode ); 18sf ( pfx + "Float_0" , float0 ); 19sf ( pfx + "Float_1" , float1 ); 20sf ( pfx + "Float_2" , float2 ); 21sf ( pfx + "Float_3" , float3 ); 22sv ( pfx + "Vector_0" , vec0 ); 23sv ( pfx + "Vector_1" , vec1 ); 24sv ( pfx + "Vector_2" , vec2 ); 25sv ( pfx + "Vector_3" , vec3 ); 26} 27 28static void ClearTarget ( string pfx , Action < string , float > sf , Action < string , int > si , Action < string , Vector4 > sv ) 29{ 30sf ( pfx + "Enabled" , 0f ); 31si ( pfx + "Opcode" , 0 ); 32sf ( pfx + "Float_0" , 0f ); 33sf ( pfx + "Float_1" , 0f ); 34sf ( pfx + "Float_2" , 0f ); 35sf ( pfx + "Float_3" , 0f ); 36sv ( pfx + "Vector_0" , Vector4 . zero ); 37sv ( pfx + "Vector_1" , Vector4 . zero ); 38sv ( pfx + "Vector_2" , Vector4 . zero ); 39sv ( pfx + "Vector_3" , Vector4 . zero ); 40} 41 42public void ApplyToMaterial ( Material mat , int i ) => 43ApplyToTarget ( Prefix ( i ), mat . SetFloat , mat . SetInteger , ( k , v ) => mat . SetVector ( k , v )); 44 45public void ApplyToPropertyBlock ( MaterialPropertyBlock mpb , int i ) => 46ApplyToTarget ( Prefix ( i ), mpb . SetFloat , mpb . SetInteger , ( k , v ) => mpb . SetVector ( k , v )); 47 48public static void ClearSlot ( Material mat , int i ) => 49ClearTarget ( Prefix ( i ), mat . SetFloat , mat . SetInteger , ( k , v ) => mat . SetVector ( k , v )); 50 51public static void ClearInPropertyBlock ( MaterialPropertyBlock mpb , int i ) => 52ClearTarget ( Prefix ( i ), mpb . SetFloat , mpb . SetInteger , ( k , v ) => mpb . SetVector ( k , v )); 53} 54 55public class FoldPipelineBuilder 56{ 57readonly List < FoldSlot > slots = new (); 58Material targetMaterial ; 59 60FoldPipelineBuilder () { } 61 62public static FoldPipelineBuilder Create () => new (); 63 64public FoldPipelineBuilder For ( Material material ) { targetMaterial = material ; return this ; } 65 66FoldPipelineBuilder AddSlot ( FoldSlot slot ) { slots . Add ( slot ); return this ; } 67 68FoldPipelineBuilder Prs ( int opcode , Vector3 p , Vector3 r , Vector3 s , float t ) => 69AddSlot ( new FoldSlot { opcode = opcode , vec0 = p , vec1 = r , vec2 = s , float0 = t }); 70 71FoldPipelineBuilder Vec1t ( int opcode , Vector3 v , float t ) => 72AddSlot ( new FoldSlot { opcode = opcode , vec0 = v , float0 = t }); 73 74public FoldPipelineBuilder TubeToPlane ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( TubeToPlaneOp . Opcode , p , r , s , t ); 75public FoldPipelineBuilder PlaneToTube ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( PlaneToTubeOp . Opcode , p , r , s , t ); 76public FoldPipelineBuilder PlaneToHemiOctahedron ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( PlaneToHemiOctahedronOp . Opcode , p , r , s , t ); 77public FoldPipelineBuilder HemiOctahedronToPlane ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( HemiOctahedronToPlaneOp . Opcode , p , r , s , t ); 78public FoldPipelineBuilder PlaneToOctahedron ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( PlaneToOctahedronOp . Opcode , p , r , s , t ); 79public FoldPipelineBuilder OctahedronToPlane ( Vector3 p , Vector3 r , Vector3 s , float t ) => Prs ( OctahedronToPlaneOp . Opcode , p , r , s , t ); 80public FoldPipelineBuilder PointAlign ( Vector3 po , Vector3 pp , Vector3 r , float t ) => Prs ( PointAlignOp . Opcode , po , pp , r , t ); 81public FoldPipelineBuilder AxisAlign ( Vector3 po , Vector3 pp , Vector3 r , float t ) => Prs ( AxisAlignOp . Opcode , po , pp , r , t ); 82public FoldPipelineBuilder Scale ( Vector3 k , float t ) => Vec1t ( ScaleOp . Opcode , k , t ); 83public FoldPipelineBuilder Translate ( Vector3 offset , float t ) => Vec1t ( TranslateOp . Opcode , offset , t ); 84 85public FoldPipelineBuilder Rotate ( Vector3 center , Vector3 axis , float angle , float t ) => 86AddSlot ( new FoldSlot { opcode = RotateOp . Opcode , vec0 = center , vec1 = axis , float0 = angle , float1 = t }); 87 88public FoldPipelineBuilder NormConversion ( float inputK , float outputK , float t ) => 89AddSlot ( new FoldSlot { opcode = NormConversionOp . Opcode , float0 = inputK , float1 = outputK , float2 = t }); 90 91public FoldPipelineBuilder Seal ( float A , float k , float st , float t ) => 92AddSlot ( new FoldSlot { opcode = SealOp . Opcode , float0 = A , float1 = k , float2 = st , float3 = t }); 93 94public FoldPipelineBuilder SineWaves () => AddSlot ( new FoldSlot { opcode = SineWavesOp . Opcode }); 95public FoldPipelineBuilder FBM () => AddSlot ( new FoldSlot { opcode = FBMOp . Opcode }); 96 97public FoldPipelineBuilder Custom ( int opcode , 98float f0 = 0 , float f1 = 0 , float f2 = 0 , float f3 = 0 , 99Vector4 ? v0 = null , Vector4 ? v1 = null , Vector4 ? v2 = null , Vector4 ? v3 = null ) => 100AddSlot ( new FoldSlot 101{ 102opcode = opcode , 103float0 = f0 , float1 = f1 , float2 = f2 , float3 = f3 , 104vec0 = v0 ?? Vector4 . zero , 105vec1 = v1 ?? Vector4 . zero , 106vec2 = v2 ?? Vector4 . zero , 107vec3 = v3 ?? Vector4 . zero 108}); 109 110public void Apply () 111{ 112if ( targetMaterial == null ) 113{ 114Debug . LogError ( "No target material set. Use .For(material) before .Apply()" ); 115return ; 116} 117 118if ( slots . Count > 16 ) 119Debug . LogWarning ( $"Too many operations ( { slots . Count } ). Only the first 16 will be applied." ); 120 121Undo . RecordObject ( targetMaterial , "Apply Vertex Deformation" ); 122 123targetMaterial . SetFloat ( "_Vertex_Deformation_Enabled" , 1f ); 124 125for ( int i = 0 ; i < 16 ; i ++ ) 126FoldSlot . ClearSlot ( targetMaterial , i ); 127 128for ( int i = 0 ; i < slots . Count && i < 16 ; i ++ ) 129slots [ i ]. ApplyToMaterial ( targetMaterial , i ); 130 131EditorUtility . SetDirty ( targetMaterial ); 132} 133 134public void Clear () => slots . Clear (); 135public int Count => slots . Count ; 136public FoldSlot GetSlot ( int index ) => index < slots . Count ? slots [ index ] : null ; 137}