yum-archive/2ner

A toon shader for Unity's BIRP.

git clone https://git.yummers.dev/yum-archive/2ner

yumOrganize scripts9e5f80c

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