yum-archive/2ner

A toon shader for Unity's BIRP.

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

yummore work on fog & c308b7ae8d

master
19.1 KiB500 linesraw
1// !! AI ARTIFACT !!
2// This code was originally generated by Claude 3.5 Sonnet.
3using UnityEngine;
4using UnityEditor;
5
6public enum NoiseType
7{
8    OneDimensional,
9    TwoDimensional,
10    ThreeDimensional,
11    FourDimensional,
12    NormalizedThreeDimensional
13}
14
15public class WhiteNoiseTextureGenerator : EditorWindow
16{
17    private int textureWidth = 32;
18    private int textureHeight = 32;
19    private int textureDepth = 32;
20    private string textureName = "WhiteNoiseTexture";
21    private NoiseType noiseType = NoiseType.ThreeDimensional;
22    
23    // Domain warping parameters
24    private bool enableDomainWarping = false;
25    private int domainWarpingOctaves = 2;
26    private float domainWarpingStrength = 0.1f;
27    private float domainWarpingScale = 0.5f;
28
29    // FBM parameters
30    private bool enableFBM = false;
31    private int fbmOctaves = 4;
32    private float fbmLacunarity = 2.0f;
33    private float fbmGain = 0.5f;
34
35    [MenuItem("Tools/yum_food/White Noise Texture Generator")]
36    public static void ShowWindow()
37    {
38        GetWindow<WhiteNoiseTextureGenerator>("White Noise Texture Generator");
39    }
40
41    private void OnGUI()
42    {
43        GUILayout.Label("White Noise Texture Generator", EditorStyles.boldLabel);
44
45        textureWidth = EditorGUILayout.IntField("Texture Width", textureWidth);
46        textureHeight = EditorGUILayout.IntField("Texture Height", textureHeight);
47        textureDepth = EditorGUILayout.IntField("Texture Depth", textureDepth);
48        textureName = EditorGUILayout.TextField("Texture Name", textureName);
49        noiseType = (NoiseType)EditorGUILayout.EnumPopup("Noise Type", noiseType);
50        
51        EditorGUILayout.Space();
52        GUILayout.Label("Domain Warping", EditorStyles.boldLabel);
53        enableDomainWarping = EditorGUILayout.Toggle("Enable Domain Warping", enableDomainWarping);
54        
55        if (enableDomainWarping)
56        {
57            EditorGUI.indentLevel++;
58            domainWarpingOctaves = EditorGUILayout.IntSlider("Octaves", domainWarpingOctaves, 1, 10);
59            domainWarpingStrength = EditorGUILayout.Slider("Strength", domainWarpingStrength, 0f, 10f);
60            domainWarpingScale = EditorGUILayout.Slider("Scale", domainWarpingScale, 0.1f, 10f);
61            EditorGUI.indentLevel--;
62        }
63
64        EditorGUILayout.Space();
65        GUILayout.Label("FBM (Fractal Brownian Motion)", EditorStyles.boldLabel);
66        enableFBM = EditorGUILayout.Toggle("Enable FBM", enableFBM);
67        
68        if (enableFBM)
69        {
70            EditorGUI.indentLevel++;
71            fbmOctaves = EditorGUILayout.IntSlider("Octaves", fbmOctaves, 1, 10);
72            fbmLacunarity = EditorGUILayout.Slider("Lacunarity", fbmLacunarity, 1.0f, 4.0f);
73            fbmGain = EditorGUILayout.Slider("Gain", fbmGain, 0.1f, 1.0f);
74            EditorGUI.indentLevel--;
75        }
76
77        if (GUILayout.Button("Generate Texture"))
78        {
79            if (textureWidth <= 0 || textureHeight <= 0 || textureDepth <= 0)
80            {
81                EditorUtility.DisplayDialog("Error", "Texture dimensions must be greater than zero.", "OK");
82                return;
83            }
84
85            GenerateWhiteNoiseTexture();
86        }
87    }
88
89    private void GenerateWhiteNoiseTexture()
90    {
91        TextureFormat format = GetTextureFormat();
92        Texture3D texture = new Texture3D(textureWidth, textureHeight, textureDepth, format, false);
93        
94        if (enableFBM)
95        {
96            GenerateWithFBM(texture);
97        }
98        else if (enableDomainWarping)
99        {
100            GenerateWithDomainWarping(texture);
101        }
102        else
103        {
104            GenerateSimpleNoise(texture);
105        }
106
107        texture.Apply();
108
109        string path = $"Assets/{textureName}.asset";
110        
111        // Check if asset already exists
112        Texture3D existingTexture = AssetDatabase.LoadAssetAtPath<Texture3D>(path);
113        if (existingTexture != null)
114        {
115            // Copy new texture data to existing asset to preserve GUID
116            EditorUtility.CopySerialized(texture, existingTexture);
117            EditorUtility.SetDirty(existingTexture);
118            AssetDatabase.SaveAssets();
119            AssetDatabase.Refresh();
120            EditorUtility.DisplayDialog("Success", $"White noise texture updated at {path}", "OK");
121        }
122        else
123        {
124            // Create new asset
125            AssetDatabase.CreateAsset(texture, path);
126            AssetDatabase.SaveAssets();
127            AssetDatabase.Refresh();
128            EditorUtility.DisplayDialog("Success", $"White noise texture generated and saved at {path}", "OK");
129        }
130    }
131    
132    private void GenerateSimpleNoise(Texture3D texture)
133    {
134        Color[] colors = new Color[textureWidth * textureHeight * textureDepth];
135
136        for (int z = 0; z < textureDepth; z++)
137        {
138            for (int y = 0; y < textureHeight; y++)
139            {
140                for (int x = 0; x < textureWidth; x++)
141                {
142                    int index = x + y * textureWidth + z * textureWidth * textureHeight;
143                    colors[index] = GenerateColor();
144                }
145            }
146        }
147
148        texture.SetPixels(colors);
149    }
150    
151    private void GenerateWithDomainWarping(Texture3D texture)
152    {
153        // First pass: generate base noise
154        Color[] baseColors = new Color[textureWidth * textureHeight * textureDepth];
155        for (int i = 0; i < baseColors.Length; i++)
156        {
157            baseColors[i] = GenerateColor();
158        }
159        
160        // Second pass: apply domain warping
161        Color[] warpedColors = new Color[textureWidth * textureHeight * textureDepth];
162        
163        for (int z = 0; z < textureDepth; z++)
164        {
165            for (int y = 0; y < textureHeight; y++)
166            {
167                for (int x = 0; x < textureWidth; x++)
168                {
169                    Vector3 coord = new Vector3(
170                        (float)x / textureWidth,
171                        (float)y / textureHeight,
172                        (float)z / textureDepth
173                    );
174                    
175                    // Apply domain warping
176                    for (int octave = 0; octave < domainWarpingOctaves; octave++)
177                    {
178                        Vector3 sampleCoord = coord * domainWarpingScale;
179                        Color warpValue = SampleTexture(baseColors, sampleCoord);
180                        
181                        // Convert color to offset vector
182                        Vector3 offset = new Vector3(
183                            warpValue.r * 2f - 1f,
184                            warpValue.g * 2f - 1f,
185                            warpValue.b * 2f - 1f
186                        ) * domainWarpingStrength;
187                        
188                        coord += offset;
189                    }
190                    
191                    // Sample final color at warped coordinate
192                    int index = x + y * textureWidth + z * textureWidth * textureHeight;
193                    warpedColors[index] = SampleTexture(baseColors, coord);
194                }
195            }
196        }
197        
198        texture.SetPixels(warpedColors);
199    }
200    
201    private Color SampleTexture(Color[] colors, Vector3 coord)
202    {
203        // Wrap coordinates
204        coord.x = Mathf.Repeat(coord.x, 1f);
205        coord.y = Mathf.Repeat(coord.y, 1f);
206        coord.z = Mathf.Repeat(coord.z, 1f);
207        
208        // Convert to texture space
209        float fx = coord.x * (textureWidth - 1);
210        float fy = coord.y * (textureHeight - 1);
211        float fz = coord.z * (textureDepth - 1);
212        
213        // Trilinear interpolation
214        int x0 = Mathf.FloorToInt(fx);
215        int y0 = Mathf.FloorToInt(fy);
216        int z0 = Mathf.FloorToInt(fz);
217        int x1 = (x0 + 1) % textureWidth;
218        int y1 = (y0 + 1) % textureHeight;
219        int z1 = (z0 + 1) % textureDepth;
220        
221        float dx = fx - x0;
222        float dy = fy - y0;
223        float dz = fz - z0;
224        
225        // Apply smoothstep to interpolation parameters
226        float sx = Mathf.SmoothStep(0, 1, dx);
227        float sy = Mathf.SmoothStep(0, 1, dy);
228        float sz = Mathf.SmoothStep(0, 1, dz);
229        
230        // Sample 8 corners
231        Color c000 = colors[x0 + y0 * textureWidth + z0 * textureWidth * textureHeight];
232        Color c001 = colors[x0 + y0 * textureWidth + z1 * textureWidth * textureHeight];
233        Color c010 = colors[x0 + y1 * textureWidth + z0 * textureWidth * textureHeight];
234        Color c011 = colors[x0 + y1 * textureWidth + z1 * textureWidth * textureHeight];
235        Color c100 = colors[x1 + y0 * textureWidth + z0 * textureWidth * textureHeight];
236        Color c101 = colors[x1 + y0 * textureWidth + z1 * textureWidth * textureHeight];
237        Color c110 = colors[x1 + y1 * textureWidth + z0 * textureWidth * textureHeight];
238        Color c111 = colors[x1 + y1 * textureWidth + z1 * textureWidth * textureHeight];
239        
240        // Interpolate with smoothstepped values
241        Color c00 = Color.Lerp(c000, c001, sz);
242        Color c01 = Color.Lerp(c010, c011, sz);
243        Color c10 = Color.Lerp(c100, c101, sz);
244        Color c11 = Color.Lerp(c110, c111, sz);
245        
246        Color c0 = Color.Lerp(c00, c01, sy);
247        Color c1 = Color.Lerp(c10, c11, sy);
248        
249        return Color.Lerp(c0, c1, sx);
250    }
251
252    private Color SampleTextureCustomSize(Color[] colors, Vector3 coord, int width, int height, int depth)
253    {
254        // Convert to texture space
255        float fx = coord.x * (width);
256        float fy = coord.y * (height);
257        float fz = coord.z * (depth);
258        
259        // Trilinear interpolation
260        int x0 = Mathf.FloorToInt(fx);
261        int y0 = Mathf.FloorToInt(fy);
262        int z0 = Mathf.FloorToInt(fz);
263        int x1 = (x0 + 1) % width;
264        int y1 = (y0 + 1) % height;
265        int z1 = (z0 + 1) % depth;
266        
267        float dx = fx - x0;
268        float dy = fy - y0;
269        float dz = fz - z0;
270        
271        // Apply smoothstep to interpolation parameters
272        float sx = Mathf.SmoothStep(0, 1, dx);
273        float sy = Mathf.SmoothStep(0, 1, dy);
274        float sz = Mathf.SmoothStep(0, 1, dz);
275        
276        // Sample 8 corners
277        Color c000 = colors[x0 + y0 * width + z0 * width * height];
278        Color c001 = colors[x0 + y0 * width + z1 * width * height];
279        Color c010 = colors[x0 + y1 * width + z0 * width * height];
280        Color c011 = colors[x0 + y1 * width + z1 * width * height];
281        Color c100 = colors[x1 + y0 * width + z0 * width * height];
282        Color c101 = colors[x1 + y0 * width + z1 * width * height];
283        Color c110 = colors[x1 + y1 * width + z0 * width * height];
284        Color c111 = colors[x1 + y1 * width + z1 * width * height];
285        
286        // Interpolate with smoothstepped values
287        Color c00 = Color.Lerp(c000, c001, sz);
288        Color c01 = Color.Lerp(c010, c011, sz);
289        Color c10 = Color.Lerp(c100, c101, sz);
290        Color c11 = Color.Lerp(c110, c111, sz);
291        
292        Color c0 = Color.Lerp(c00, c01, sy);
293        Color c1 = Color.Lerp(c10, c11, sy);
294        
295        return Color.Lerp(c0, c1, sx);
296    }
297
298    private Color[] ApplyDomainWarpingToColors(Color[] baseColors, int width, int height, int depth)
299    {
300        Color[] warpedColors = new Color[baseColors.Length];
301        
302        for (int z = 0; z < depth; z++)
303        {
304            for (int y = 0; y < height; y++)
305            {
306                for (int x = 0; x < width; x++)
307                {
308                    Vector3 coord = new Vector3(
309                        (float)x / width,
310                        (float)y / height,
311                        (float)z / depth
312                    );
313                    
314                    // Apply domain warping
315                    for (int octave = 0; octave < domainWarpingOctaves; octave++)
316                    {
317                        Vector3 sampleCoord = coord * domainWarpingScale;
318                        Color warpValue = SampleTextureCustomSize(baseColors, sampleCoord, width, height, depth);
319                        
320                        // Convert color to offset vector
321                        Vector3 offset = new Vector3(
322                            warpValue.r * 2f - 1f,
323                            warpValue.g * 2f - 1f,
324                            warpValue.b * 2f - 1f
325                        ) * domainWarpingStrength;
326                        
327                        coord += offset;
328                    }
329                    
330                    // Sample final color at warped coordinate
331                    int index = x + y * width + z * width * height;
332                    warpedColors[index] = SampleTextureCustomSize(baseColors, coord, width, height, depth);
333                }
334            }
335        }
336        
337        return warpedColors;
338    }
339
340    private TextureFormat GetTextureFormat()
341    {
342        switch (noiseType)
343        {
344            case NoiseType.OneDimensional:
345                return TextureFormat.R8;
346            case NoiseType.TwoDimensional:
347                return TextureFormat.RG16;
348            case NoiseType.ThreeDimensional:
349            case NoiseType.NormalizedThreeDimensional:
350                return TextureFormat.RGB48;
351            case NoiseType.FourDimensional:
352                return TextureFormat.RGBA32;
353            default:
354                return TextureFormat.RGB24;
355        }
356    }
357
358    private Color GenerateColor()
359    {
360        switch (noiseType)
361        {
362            case NoiseType.OneDimensional:
363                return new Color(Random.value, 0, 0, 1);
364            case NoiseType.TwoDimensional:
365                return new Color(Random.value, Random.value, 0, 1);
366            case NoiseType.ThreeDimensional:
367                return new Color(Random.value, Random.value, Random.value, 1);
368            case NoiseType.FourDimensional:
369                return new Color(Random.value, Random.value, Random.value, Random.value);
370            case NoiseType.NormalizedThreeDimensional:
371                Vector3 normalizedColor = Random.insideUnitSphere.normalized;
372                return new Color(normalizedColor.x * 0.5f + 0.5f, normalizedColor.y * 0.5f + 0.5f, normalizedColor.z * 0.5f + 0.5f, 1);
373            default:
374                return Color.white;
375        }
376    }
377
378    private void GenerateWithFBM(Texture3D texture)
379    {
380        // Calculate starting resolution based on target size and octaves
381        float scaleFactor = Mathf.Pow(fbmLacunarity, fbmOctaves - 1);
382        int currentWidth = Mathf.Max(1, Mathf.RoundToInt(textureWidth / scaleFactor));
383        int currentHeight = Mathf.Max(1, Mathf.RoundToInt(textureHeight / scaleFactor));
384        int currentDepth = Mathf.Max(1, Mathf.RoundToInt(textureDepth / scaleFactor));
385        
386        // Track previous dimensions
387        int prevWidth = currentWidth;
388        int prevHeight = currentHeight;
389        int prevDepth = currentDepth;
390        
391        Color[] baseColors = null;
392        float amplitude = 1.0f;
393        float maxAmplitude = 0.0f;
394        
395        for (int octave = 0; octave < fbmOctaves; octave++)
396        {
397            // Generate noise at current resolution
398            Color[] octaveColors = new Color[currentWidth * currentHeight * currentDepth];
399            for (int i = 0; i < octaveColors.Length; i++) {
400                octaveColors[i] = GenerateColor();
401            }
402            
403            if (baseColors == null) {
404                baseColors = octaveColors;
405            } else {
406                for (int z = 0; z < currentDepth; z++)
407                for (int y = 0; y < currentHeight; y++)
408                for (int x = 0; x < currentWidth; x++)
409                {
410                    int index = x + y * currentWidth + z * currentWidth * currentHeight;
411                    Vector3 coord = new Vector3(
412                        (float)x / currentWidth,
413                        (float)y / currentHeight,
414                        (float)z / currentDepth
415                    );
416                    Color prevColor = SampleTextureCustomSize(baseColors, coord, prevWidth, prevHeight, prevDepth);
417                    octaveColors[index] = prevColor + octaveColors[index] * amplitude;
418                }
419            }
420            
421            baseColors = octaveColors;
422            
423            maxAmplitude += amplitude;
424            amplitude *= fbmGain;
425            
426            // Store current dimensions as previous before updating
427            prevWidth = currentWidth;
428            prevHeight = currentHeight;
429            prevDepth = currentDepth;
430            
431            // Increase resolution for next octave
432            if (octave < fbmOctaves - 1)
433            {
434                currentWidth = Mathf.Min(textureWidth, Mathf.RoundToInt(currentWidth * fbmLacunarity));
435                currentHeight = Mathf.Min(textureHeight, Mathf.RoundToInt(currentHeight * fbmLacunarity));
436                currentDepth = Mathf.Min(textureDepth, Mathf.RoundToInt(currentDepth * fbmLacunarity));
437            }
438        }
439        
440        // Ensure final resolution matches target
441        if (currentWidth != textureWidth || currentHeight != textureHeight || currentDepth != textureDepth)
442        {
443            Color[] finalColors = new Color[textureWidth * textureHeight * textureDepth];
444            for (int z = 0; z < textureDepth; z++)
445            {
446                for (int y = 0; y < textureHeight; y++)
447                {
448                    for (int x = 0; x < textureWidth; x++)
449                    {
450                        int index = x + y * textureWidth + z * textureWidth * textureHeight;
451                        Vector3 coord = new Vector3(
452                            (float)x / textureWidth,
453                            (float)y / textureHeight,
454                            (float)z / textureDepth
455                        );
456                        finalColors[index] = SampleTextureCustomSize(baseColors, coord, currentWidth, currentHeight, currentDepth);
457                    }
458                }
459            }
460            baseColors = finalColors;
461        }
462        
463        // Normalize
464        for (int i = 0; i < baseColors.Length; i++)
465        {
466            baseColors[i] /= maxAmplitude;
467            baseColors[i].a = 1.0f;
468        }
469        
470        texture.SetPixels(baseColors);
471    }
472
473    private Color GeneratePerlinColor(float x, float y, float z, float scale = 1f)
474    {
475        switch (noiseType)
476        {
477            case NoiseType.OneDimensional:
478                return new Color(Mathf.PerlinNoise(x * scale, 0), 0, 0, 1);
479            case NoiseType.TwoDimensional:
480                return new Color(
481                    Mathf.PerlinNoise(x * scale, y * scale), 
482                    Mathf.PerlinNoise(x * scale + 100, y * scale + 100), 
483                    0, 1);
484            case NoiseType.ThreeDimensional:
485                return new Color(
486                    Mathf.PerlinNoise(x * scale, y * scale),
487                    Mathf.PerlinNoise(x * scale + 100, z * scale),
488                    Mathf.PerlinNoise(y * scale + 200, z * scale + 200),
489                    1);
490            case NoiseType.FourDimensional:
491                return new Color(
492                    Mathf.PerlinNoise(x * scale, y * scale),
493                    Mathf.PerlinNoise(x * scale + 100, z * scale),
494                    Mathf.PerlinNoise(y * scale + 200, z * scale + 200),
495                    Mathf.PerlinNoise(x * scale + 300, y * scale + 300));
496            default:
497                return Color.white;
498        }
499    }
500}