yum-archive/2ner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/2ner
9e5f80c
master
1using UnityEngine ; 2using System . Collections . Generic ; 3using System . Linq ; 4 5public class DecodeVertexVectors : MonoBehaviour 6{ 7[ Header ( "Display Settings" )] 8[ SerializeField ] private int maxVertices = 100 ; 9[ SerializeField ] private float vectorScale = 0.3f ; 10 11[ Header ( "Edge Visualization" )] 12[ SerializeField ] private bool showEdges = true ; 13[ SerializeField ] private int edgeSubdivisions = 2 ; 14 15[ Header ( "Orientation" )] 16[ SerializeField ] private bool showOrientations = true ; 17[ SerializeField ] private float orientationScale = 1.0f ; 18 19[ Header ( "UV Channels" )] 20[ SerializeField ] private int quaternionXYChannel = 1 ; 21[ SerializeField ] private int quaternionZWChannel = 2 ; 22 23[ Header ( "Colors" )] 24[ SerializeField ] private Color vectorColor = new Color ( 0.5f , 0.8f , 1f ); 25[ SerializeField ] private Color correctedVectorColor = new Color ( 1f , 0.5f , 0.2f ); 26[ SerializeField ] private Color forwardColor = Color . blue ; 27 28private void OnDrawGizmos () 29{ 30var meshFilter = GetComponent < MeshFilter > (); 31if ( ! meshFilter || ! meshFilter . sharedMesh ) return ; 32 33var mesh = meshFilter . sharedMesh ; 34var vertices = mesh . vertices ; 35var colors = mesh . colors ; 36 37// Draw vertex vectors from colors 38if ( colors != null && colors . Length > 0 ) 39{ 40DrawVertexVectors ( mesh , vertices , colors ); 41} 42 43// Draw orientations from UVs 44if ( showOrientations ) 45{ 46DrawOrientations ( mesh , vertices ); 47} 48} 49 50void DrawVertexVectors ( Mesh mesh , Vector3 [] vertices , Color [] colors ) 51{ 52Vector2 [] uvXY = GetUVData ( mesh , quaternionXYChannel ); 53Vector2 [] uvZW = GetUVData ( mesh , quaternionZWChannel ); 54bool hasQuaternions = uvXY != null && uvZW != null ; 55 56int vertexStep = Mathf . Max ( 1 , vertices . Length / maxVertices ); 57 58// Draw vectors at vertices 59for ( int i = 0 ; i < vertices . Length ; i += vertexStep ) 60{ 61if ( i >= colors . Length ) break ; 62 63Vector3 worldPos = transform . TransformPoint ( vertices [ i ]); 64Vector3 decodedVector = DecodeVectorFromColor ( colors [ i ]); 65 66// Basic vector 67Gizmos . color = vectorColor ; 68DrawVector ( worldPos , transform . TransformDirection ( decodedVector ), vectorScale ); 69 70// Quaternion-corrected vector 71if ( hasQuaternions && i < uvXY . Length && i < uvZW . Length ) 72{ 73Quaternion quat = GetQuaternionFromUV ( uvXY [ i ], uvZW [ i ]); 74Vector3 corrected = quat * decodedVector ; 75 76Gizmos . color = correctedVectorColor ; 77DrawVector ( worldPos , transform . TransformDirection ( corrected ), vectorScale ); 78} 79} 80 81// Draw edge interpolations 82if ( showEdges && edgeSubdivisions > 0 ) 83{ 84DrawEdgeInterpolations ( mesh , vertices , colors , uvXY , uvZW ); 85} 86} 87 88void DrawEdgeInterpolations ( Mesh mesh , Vector3 [] vertices , Color [] colors , Vector2 [] uvXY , Vector2 [] uvZW ) 89{ 90var triangles = mesh . triangles ; 91HashSet < ( int , int ) > drawnEdges = new HashSet < ( int , int ) > (); 92bool hasQuaternions = uvXY != null && uvZW != null ; 93 94for ( int i = 0 ; i < triangles . Length && drawnEdges . Count < maxVertices / 2 ; i += 3 ) 95{ 96for ( int j = 0 ; j < 3 ; j ++ ) 97{ 98int v1 = triangles [ i + j ]; 99int v2 = triangles [ i + (( j + 1 ) % 3 )]; 100 101var edge = v1 < v2 ? ( v1 , v2 ) : ( v2 , v1 ); 102if ( ! drawnEdges . Add ( edge )) continue ; 103 104if ( v1 >= vertices . Length || v2 >= vertices . Length || 105v1 >= colors . Length || v2 >= colors . Length ) continue ; 106 107// Draw subdivisions along edge 108for ( int k = 1 ; k < edgeSubdivisions ; k ++ ) 109{ 110float t = k / ( float ) edgeSubdivisions ; 111Vector3 pos = Vector3 . Lerp ( vertices [ v1 ], vertices [ v2 ], t ); 112Color col = Color . Lerp ( colors [ v1 ], colors [ v2 ], t ); 113 114Vector3 worldPos = transform . TransformPoint ( pos ); 115Vector3 vec = DecodeVectorFromColor ( col ); 116 117// Basic vector 118Gizmos . color = vectorColor * 0.7f ; // Slightly dimmer for edge points 119DrawVector ( worldPos , transform . TransformDirection ( vec ), vectorScale * 0.8f ); 120 121// Quaternion-corrected vector 122if ( hasQuaternions && v1 < uvXY . Length && v2 < uvXY . Length && 123v1 < uvZW . Length && v2 < uvZW . Length ) 124{ 125Vector2 interpXY = Vector2 . Lerp ( uvXY [ v1 ], uvXY [ v2 ], t ); 126Vector2 interpZW = Vector2 . Lerp ( uvZW [ v1 ], uvZW [ v2 ], t ); 127Quaternion interpQuat = GetQuaternionFromUV ( interpXY , interpZW ); 128Vector3 corrected = interpQuat * vec ; 129 130Gizmos . color = correctedVectorColor * 0.7f ; // Slightly dimmer for edge points 131DrawVector ( worldPos , transform . TransformDirection ( corrected ), vectorScale * 0.8f ); 132} 133} 134} 135} 136} 137 138void DrawOrientations ( Mesh mesh , Vector3 [] vertices ) 139{ 140Vector2 [] uvXY = GetUVData ( mesh , quaternionXYChannel ); 141Vector2 [] uvZW = GetUVData ( mesh , quaternionZWChannel ); 142 143if ( uvXY == null || uvZW == null ) return ; 144 145int vertexStep = Mathf . Max ( 1 , vertices . Length / maxVertices ); 146 147for ( int i = 0 ; i < vertices . Length ; i += vertexStep ) 148{ 149if ( i >= uvXY . Length || i >= uvZW . Length ) break ; 150 151Vector3 worldPos = transform . TransformPoint ( vertices [ i ]); 152Quaternion quat = GetQuaternionFromUV ( uvXY [ i ], uvZW [ i ]); 153 154// Draw forward direction 155Gizmos . color = forwardColor ; 156Vector3 forward = transform . TransformDirection ( quat * Vector3 . forward ); 157DrawArrow ( worldPos , forward , orientationScale ); 158} 159} 160 161void DrawVector ( Vector3 origin , Vector3 direction , float scale ) 162{ 163Vector3 end = origin + direction * scale ; 164Gizmos . DrawLine ( origin , end ); 165Gizmos . DrawSphere ( end , 0.02f ); 166} 167 168void DrawArrow ( Vector3 origin , Vector3 direction , float length ) 169{ 170Vector3 end = origin + direction * length ; 171Gizmos . DrawLine ( origin , end ); 172 173// Simple arrowhead 174Vector3 right = Vector3 . Cross ( direction , Vector3 . up ). normalized ; 175if ( right . magnitude < 0.01f ) 176right = Vector3 . Cross ( direction , Vector3 . right ). normalized ; 177 178Vector3 arrowBack = - direction * length * 0.2f ; 179Vector3 arrowSide = right * length * 0.1f ; 180 181Gizmos . DrawLine ( end , end + arrowBack + arrowSide ); 182Gizmos . DrawLine ( end , end + arrowBack - arrowSide ); 183} 184 185Quaternion GetQuaternionFromUV ( Vector2 xy , Vector2 zw ) 186{ 187return new Quaternion ( xy . x , xy . y , zw . x , zw . y ). normalized ; 188} 189 190Vector3 DecodeVectorFromColor ( Color color ) 191{ 192return new Vector3 ( 193color . r * 2.0f - 1.0f , 194color . g * 2.0f - 1.0f , 195color . b * 2.0f - 1.0f ) / color . a ; 196} 197 198Vector2 [] GetUVData ( Mesh mesh , int channel ) 199{ 200switch ( channel ) 201{ 202case 0 : return mesh . uv ; 203case 1 : return mesh . uv2 ; 204case 2 : return mesh . uv3 ; 205case 3 : return mesh . uv4 ; 206case 4 : return mesh . uv5 ; 207case 5 : return mesh . uv6 ; 208case 6 : return mesh . uv7 ; 209case 7 : return mesh . uv8 ; 210default : return null ; 211} 212} 213}