diff options
Diffstat (limited to 'Editor/generate_3d_noise.cs')
| -rw-r--r-- | Editor/generate_3d_noise.cs | 257 |
1 files changed, 248 insertions, 9 deletions
diff --git a/Editor/generate_3d_noise.cs b/Editor/generate_3d_noise.cs index 1a0dca0..16d47e8 100644 --- a/Editor/generate_3d_noise.cs +++ b/Editor/generate_3d_noise.cs @@ -26,6 +26,12 @@ public class WhiteNoiseTextureGenerator : EditorWindow private float domainWarpingStrength = 0.1f; private float domainWarpingScale = 0.5f; + // FBM parameters + private bool enableFBM = false; + private int fbmOctaves = 4; + private float fbmLacunarity = 2.0f; + private float fbmGain = 0.5f; + [MenuItem("Tools/yum_food/White Noise Texture Generator")] public static void ShowWindow() { @@ -55,6 +61,19 @@ public class WhiteNoiseTextureGenerator : EditorWindow EditorGUI.indentLevel--; } + EditorGUILayout.Space(); + GUILayout.Label("FBM (Fractal Brownian Motion)", EditorStyles.boldLabel); + enableFBM = EditorGUILayout.Toggle("Enable FBM", enableFBM); + + if (enableFBM) + { + EditorGUI.indentLevel++; + fbmOctaves = EditorGUILayout.IntSlider("Octaves", fbmOctaves, 1, 10); + fbmLacunarity = EditorGUILayout.Slider("Lacunarity", fbmLacunarity, 1.0f, 4.0f); + fbmGain = EditorGUILayout.Slider("Gain", fbmGain, 0.1f, 1.0f); + EditorGUI.indentLevel--; + } + if (GUILayout.Button("Generate Texture")) { if (textureWidth <= 0 || textureHeight <= 0 || textureDepth <= 0) @@ -72,7 +91,11 @@ public class WhiteNoiseTextureGenerator : EditorWindow TextureFormat format = GetTextureFormat(); Texture3D texture = new Texture3D(textureWidth, textureHeight, textureDepth, format, false); - if (enableDomainWarping) + if (enableFBM) + { + GenerateWithFBM(texture); + } + else if (enableDomainWarping) { GenerateWithDomainWarping(texture); } @@ -199,6 +222,11 @@ public class WhiteNoiseTextureGenerator : EditorWindow float dy = fy - y0; float dz = fz - z0; + // Apply smoothstep to interpolation parameters + float sx = Mathf.SmoothStep(0, 1, dx); + float sy = Mathf.SmoothStep(0, 1, dy); + float sz = Mathf.SmoothStep(0, 1, dz); + // Sample 8 corners Color c000 = colors[x0 + y0 * textureWidth + z0 * textureWidth * textureHeight]; Color c001 = colors[x0 + y0 * textureWidth + z1 * textureWidth * textureHeight]; @@ -209,16 +237,104 @@ public class WhiteNoiseTextureGenerator : EditorWindow Color c110 = colors[x1 + y1 * textureWidth + z0 * textureWidth * textureHeight]; Color c111 = colors[x1 + y1 * textureWidth + z1 * textureWidth * textureHeight]; - // Interpolate - Color c00 = Color.Lerp(c000, c001, dz); - Color c01 = Color.Lerp(c010, c011, dz); - Color c10 = Color.Lerp(c100, c101, dz); - Color c11 = Color.Lerp(c110, c111, dz); + // Interpolate with smoothstepped values + Color c00 = Color.Lerp(c000, c001, sz); + Color c01 = Color.Lerp(c010, c011, sz); + Color c10 = Color.Lerp(c100, c101, sz); + Color c11 = Color.Lerp(c110, c111, sz); + + Color c0 = Color.Lerp(c00, c01, sy); + Color c1 = Color.Lerp(c10, c11, sy); + + return Color.Lerp(c0, c1, sx); + } + + private Color SampleTextureCustomSize(Color[] colors, Vector3 coord, int width, int height, int depth) + { + // Convert to texture space + float fx = coord.x * (width); + float fy = coord.y * (height); + float fz = coord.z * (depth); + + // Trilinear interpolation + int x0 = Mathf.FloorToInt(fx); + int y0 = Mathf.FloorToInt(fy); + int z0 = Mathf.FloorToInt(fz); + int x1 = (x0 + 1) % width; + int y1 = (y0 + 1) % height; + int z1 = (z0 + 1) % depth; + + float dx = fx - x0; + float dy = fy - y0; + float dz = fz - z0; + + // Apply smoothstep to interpolation parameters + float sx = Mathf.SmoothStep(0, 1, dx); + float sy = Mathf.SmoothStep(0, 1, dy); + float sz = Mathf.SmoothStep(0, 1, dz); + + // Sample 8 corners + Color c000 = colors[x0 + y0 * width + z0 * width * height]; + Color c001 = colors[x0 + y0 * width + z1 * width * height]; + Color c010 = colors[x0 + y1 * width + z0 * width * height]; + Color c011 = colors[x0 + y1 * width + z1 * width * height]; + Color c100 = colors[x1 + y0 * width + z0 * width * height]; + Color c101 = colors[x1 + y0 * width + z1 * width * height]; + Color c110 = colors[x1 + y1 * width + z0 * width * height]; + Color c111 = colors[x1 + y1 * width + z1 * width * height]; - Color c0 = Color.Lerp(c00, c01, dy); - Color c1 = Color.Lerp(c10, c11, dy); + // Interpolate with smoothstepped values + Color c00 = Color.Lerp(c000, c001, sz); + Color c01 = Color.Lerp(c010, c011, sz); + Color c10 = Color.Lerp(c100, c101, sz); + Color c11 = Color.Lerp(c110, c111, sz); - return Color.Lerp(c0, c1, dx); + Color c0 = Color.Lerp(c00, c01, sy); + Color c1 = Color.Lerp(c10, c11, sy); + + return Color.Lerp(c0, c1, sx); + } + + private Color[] ApplyDomainWarpingToColors(Color[] baseColors, int width, int height, int depth) + { + Color[] warpedColors = new Color[baseColors.Length]; + + for (int z = 0; z < depth; z++) + { + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + Vector3 coord = new Vector3( + (float)x / width, + (float)y / height, + (float)z / depth + ); + + // Apply domain warping + for (int octave = 0; octave < domainWarpingOctaves; octave++) + { + Vector3 sampleCoord = coord * domainWarpingScale; + Color warpValue = SampleTextureCustomSize(baseColors, sampleCoord, width, height, depth); + + // Convert color to offset vector + Vector3 offset = new Vector3( + warpValue.r * 2f - 1f, + warpValue.g * 2f - 1f, + warpValue.b * 2f - 1f + ) * domainWarpingStrength; + + coord += offset; + } + + // Sample final color at warped coordinate + int index = x + y * width + z * width * height; + warpedColors[index] = SampleTextureCustomSize(baseColors, coord, width, height, depth); + } + } + } + + return warpedColors; } private TextureFormat GetTextureFormat() @@ -258,4 +374,127 @@ public class WhiteNoiseTextureGenerator : EditorWindow return Color.white; } } + + private void GenerateWithFBM(Texture3D texture) + { + // Calculate starting resolution based on target size and octaves + float scaleFactor = Mathf.Pow(fbmLacunarity, fbmOctaves - 1); + int currentWidth = Mathf.Max(1, Mathf.RoundToInt(textureWidth / scaleFactor)); + int currentHeight = Mathf.Max(1, Mathf.RoundToInt(textureHeight / scaleFactor)); + int currentDepth = Mathf.Max(1, Mathf.RoundToInt(textureDepth / scaleFactor)); + + // Track previous dimensions + int prevWidth = currentWidth; + int prevHeight = currentHeight; + int prevDepth = currentDepth; + + Color[] baseColors = null; + float amplitude = 1.0f; + float maxAmplitude = 0.0f; + + for (int octave = 0; octave < fbmOctaves; octave++) + { + // Generate noise at current resolution + Color[] octaveColors = new Color[currentWidth * currentHeight * currentDepth]; + for (int i = 0; i < octaveColors.Length; i++) { + octaveColors[i] = GenerateColor(); + } + + if (baseColors == null) { + baseColors = octaveColors; + } else { + for (int z = 0; z < currentDepth; z++) + for (int y = 0; y < currentHeight; y++) + for (int x = 0; x < currentWidth; x++) + { + int index = x + y * currentWidth + z * currentWidth * currentHeight; + Vector3 coord = new Vector3( + (float)x / currentWidth, + (float)y / currentHeight, + (float)z / currentDepth + ); + Color prevColor = SampleTextureCustomSize(baseColors, coord, prevWidth, prevHeight, prevDepth); + octaveColors[index] = prevColor + octaveColors[index] * amplitude; + } + } + + baseColors = octaveColors; + + maxAmplitude += amplitude; + amplitude *= fbmGain; + + // Store current dimensions as previous before updating + prevWidth = currentWidth; + prevHeight = currentHeight; + prevDepth = currentDepth; + + // Increase resolution for next octave + if (octave < fbmOctaves - 1) + { + currentWidth = Mathf.Min(textureWidth, Mathf.RoundToInt(currentWidth * fbmLacunarity)); + currentHeight = Mathf.Min(textureHeight, Mathf.RoundToInt(currentHeight * fbmLacunarity)); + currentDepth = Mathf.Min(textureDepth, Mathf.RoundToInt(currentDepth * fbmLacunarity)); + } + } + + // Ensure final resolution matches target + if (currentWidth != textureWidth || currentHeight != textureHeight || currentDepth != textureDepth) + { + Color[] finalColors = new Color[textureWidth * textureHeight * textureDepth]; + for (int z = 0; z < textureDepth; z++) + { + for (int y = 0; y < textureHeight; y++) + { + for (int x = 0; x < textureWidth; x++) + { + int index = x + y * textureWidth + z * textureWidth * textureHeight; + Vector3 coord = new Vector3( + (float)x / textureWidth, + (float)y / textureHeight, + (float)z / textureDepth + ); + finalColors[index] = SampleTextureCustomSize(baseColors, coord, currentWidth, currentHeight, currentDepth); + } + } + } + baseColors = finalColors; + } + + // Normalize + for (int i = 0; i < baseColors.Length; i++) + { + baseColors[i] /= maxAmplitude; + baseColors[i].a = 1.0f; + } + + texture.SetPixels(baseColors); + } + + private Color GeneratePerlinColor(float x, float y, float z, float scale = 1f) + { + switch (noiseType) + { + case NoiseType.OneDimensional: + return new Color(Mathf.PerlinNoise(x * scale, 0), 0, 0, 1); + case NoiseType.TwoDimensional: + return new Color( + Mathf.PerlinNoise(x * scale, y * scale), + Mathf.PerlinNoise(x * scale + 100, y * scale + 100), + 0, 1); + case NoiseType.ThreeDimensional: + return new Color( + Mathf.PerlinNoise(x * scale, y * scale), + Mathf.PerlinNoise(x * scale + 100, z * scale), + Mathf.PerlinNoise(y * scale + 200, z * scale + 200), + 1); + case NoiseType.FourDimensional: + return new Color( + Mathf.PerlinNoise(x * scale, y * scale), + Mathf.PerlinNoise(x * scale + 100, z * scale), + Mathf.PerlinNoise(y * scale + 200, z * scale + 200), + Mathf.PerlinNoise(x * scale + 300, y * scale + 300)); + default: + return Color.white; + } + } } |
