Created
August 16, 2017 20:09
-
-
Save igaln/5db575ff6e2883bc2d9e7410f8eeda0b to your computer and use it in GitHub Desktop.
Procedural Mesh with Perlin noise
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] | |
public class Grid : MonoBehaviour { | |
public float xOrg; | |
public float yOrg; | |
public float scale = 0.1F; | |
public int xSize, ySize; | |
private Mesh mesh; | |
private Vector3[] vertices; | |
private void Awake () { | |
Generate(); | |
} | |
void Update() { | |
Generate(); | |
} | |
private void Generate () { | |
GetComponent<MeshFilter>().mesh = mesh = new Mesh(); | |
mesh.name = "Procedural Grid"; | |
vertices = new Vector3[(xSize + 1) * (ySize + 1)]; | |
Vector2[] uv = new Vector2[vertices.Length]; | |
Vector4[] tangents = new Vector4[vertices.Length]; | |
Vector4 tangent = new Vector4(1f, 0f, 0f, -1f); | |
for (int i = 0, y = 0; y <= ySize; y++) { | |
for (int x = 0; x <= xSize; x++, i++) { | |
float xCoord = xOrg + x / xSize * scale; | |
float yCoord = yOrg + y / ySize * scale; | |
float sample = Noise.Perlin3D (new Vector3 (x, y), scale); | |
vertices[i] = new Vector3(x, y,sample); | |
uv[i] = new Vector2((float)x / xSize, (float)y / ySize); | |
tangents[i] = tangent; | |
} | |
} | |
mesh.vertices = vertices; | |
mesh.uv = uv; | |
mesh.tangents = tangents; | |
int[] triangles = new int[xSize * ySize * 6]; | |
for (int ti = 0, vi = 0, y = 0; y < ySize; y++, vi++) { | |
for (int x = 0; x < xSize; x++, ti += 6, vi++) { | |
triangles[ti] = vi; | |
triangles[ti + 3] = triangles[ti + 2] = vi + 1; | |
triangles[ti + 4] = triangles[ti + 1] = vi + xSize + 1; | |
triangles[ti + 5] = vi + xSize + 2; | |
} | |
} | |
mesh.triangles = triangles; | |
mesh.RecalculateNormals(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
public delegate float NoiseMethod (Vector3 point, float frequency); | |
public enum NoiseMethodType { | |
Value, | |
Perlin | |
} | |
public static class Noise { | |
public static NoiseMethod[] valueMethods = { | |
Value1D, | |
Value2D, | |
Value3D | |
}; | |
public static NoiseMethod[] perlinMethods = { | |
Perlin1D, | |
Perlin2D, | |
Perlin3D | |
}; | |
public static NoiseMethod[][] methods = { | |
valueMethods, | |
perlinMethods | |
}; | |
private static int[] hash = { | |
151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225, | |
140, 36,103, 30, 69,142, 8, 99, 37,240, 21, 10, 23,190, 6,148, | |
247,120,234, 75, 0, 26,197, 62, 94,252,219,203,117, 35, 11, 32, | |
57,177, 33, 88,237,149, 56, 87,174, 20,125,136,171,168, 68,175, | |
74,165, 71,134,139, 48, 27,166, 77,146,158,231, 83,111,229,122, | |
60,211,133,230,220,105, 92, 41, 55, 46,245, 40,244,102,143, 54, | |
65, 25, 63,161, 1,216, 80, 73,209, 76,132,187,208, 89, 18,169, | |
200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3, 64, | |
52,217,226,250,124,123, 5,202, 38,147,118,126,255, 82, 85,212, | |
207,206, 59,227, 47, 16, 58, 17,182,189, 28, 42,223,183,170,213, | |
119,248,152, 2, 44,154,163, 70,221,153,101,155,167, 43,172, 9, | |
129, 22, 39,253, 19, 98,108,110, 79,113,224,232,178,185,112,104, | |
218,246, 97,228,251, 34,242,193,238,210,144, 12,191,179,162,241, | |
81, 51,145,235,249, 14,239,107, 49,192,214, 31,181,199,106,157, | |
184, 84,204,176,115,121, 50, 45,127, 4,150,254,138,236,205, 93, | |
222,114, 67, 29, 24, 72,243,141,128,195, 78, 66,215, 61,156,180, | |
151,160,137, 91, 90, 15,131, 13,201, 95, 96, 53,194,233, 7,225, | |
140, 36,103, 30, 69,142, 8, 99, 37,240, 21, 10, 23,190, 6,148, | |
247,120,234, 75, 0, 26,197, 62, 94,252,219,203,117, 35, 11, 32, | |
57,177, 33, 88,237,149, 56, 87,174, 20,125,136,171,168, 68,175, | |
74,165, 71,134,139, 48, 27,166, 77,146,158,231, 83,111,229,122, | |
60,211,133,230,220,105, 92, 41, 55, 46,245, 40,244,102,143, 54, | |
65, 25, 63,161, 1,216, 80, 73,209, 76,132,187,208, 89, 18,169, | |
200,196,135,130,116,188,159, 86,164,100,109,198,173,186, 3, 64, | |
52,217,226,250,124,123, 5,202, 38,147,118,126,255, 82, 85,212, | |
207,206, 59,227, 47, 16, 58, 17,182,189, 28, 42,223,183,170,213, | |
119,248,152, 2, 44,154,163, 70,221,153,101,155,167, 43,172, 9, | |
129, 22, 39,253, 19, 98,108,110, 79,113,224,232,178,185,112,104, | |
218,246, 97,228,251, 34,242,193,238,210,144, 12,191,179,162,241, | |
81, 51,145,235,249, 14,239,107, 49,192,214, 31,181,199,106,157, | |
184, 84,204,176,115,121, 50, 45,127, 4,150,254,138,236,205, 93, | |
222,114, 67, 29, 24, 72,243,141,128,195, 78, 66,215, 61,156,180 | |
}; | |
private const int hashMask = 255; | |
private static float[] gradients1D = { | |
1f, -1f | |
}; | |
private const int gradientsMask1D = 1; | |
private static Vector2[] gradients2D = { | |
new Vector2( 1f, 0f), | |
new Vector2(-1f, 0f), | |
new Vector2( 0f, 1f), | |
new Vector2( 0f,-1f), | |
new Vector2( 1f, 1f).normalized, | |
new Vector2(-1f, 1f).normalized, | |
new Vector2( 1f,-1f).normalized, | |
new Vector2(-1f,-1f).normalized | |
}; | |
private const int gradientsMask2D = 7; | |
private static Vector3[] gradients3D = { | |
new Vector3( 1f, 1f, 0f), | |
new Vector3(-1f, 1f, 0f), | |
new Vector3( 1f,-1f, 0f), | |
new Vector3(-1f,-1f, 0f), | |
new Vector3( 1f, 0f, 1f), | |
new Vector3(-1f, 0f, 1f), | |
new Vector3( 1f, 0f,-1f), | |
new Vector3(-1f, 0f,-1f), | |
new Vector3( 0f, 1f, 1f), | |
new Vector3( 0f,-1f, 1f), | |
new Vector3( 0f, 1f,-1f), | |
new Vector3( 0f,-1f,-1f), | |
new Vector3( 1f, 1f, 0f), | |
new Vector3(-1f, 1f, 0f), | |
new Vector3( 0f,-1f, 1f), | |
new Vector3( 0f,-1f,-1f) | |
}; | |
private const int gradientsMask3D = 15; | |
private static float Dot (Vector2 g, float x, float y) { | |
return g.x * x + g.y * y; | |
} | |
private static float Dot (Vector3 g, float x, float y, float z) { | |
return g.x * x + g.y * y + g.z * z; | |
} | |
private static float Smooth (float t) { | |
return t * t * t * (t * (t * 6f - 15f) + 10f); | |
} | |
private static float sqr2 = Mathf.Sqrt(2f); | |
public static float Value1D (Vector3 point, float frequency) { | |
point *= frequency; | |
int i0 = Mathf.FloorToInt(point.x); | |
float t = point.x - i0; | |
i0 &= hashMask; | |
int i1 = i0 + 1; | |
int h0 = hash[i0]; | |
int h1 = hash[i1]; | |
t = Smooth(t); | |
return Mathf.Lerp(h0, h1, t) * (1f / hashMask); | |
} | |
public static float Value2D (Vector3 point, float frequency) { | |
point *= frequency; | |
int ix0 = Mathf.FloorToInt(point.x); | |
int iy0 = Mathf.FloorToInt(point.y); | |
float tx = point.x - ix0; | |
float ty = point.y - iy0; | |
ix0 &= hashMask; | |
iy0 &= hashMask; | |
int ix1 = ix0 + 1; | |
int iy1 = iy0 + 1; | |
int h0 = hash[ix0]; | |
int h1 = hash[ix1]; | |
int h00 = hash[h0 + iy0]; | |
int h10 = hash[h1 + iy0]; | |
int h01 = hash[h0 + iy1]; | |
int h11 = hash[h1 + iy1]; | |
tx = Smooth(tx); | |
ty = Smooth(ty); | |
return Mathf.Lerp( | |
Mathf.Lerp(h00, h10, tx), | |
Mathf.Lerp(h01, h11, tx), | |
ty) * (1f / hashMask); | |
} | |
public static float Value3D (Vector3 point, float frequency) { | |
point *= frequency; | |
int ix0 = Mathf.FloorToInt(point.x); | |
int iy0 = Mathf.FloorToInt(point.y); | |
int iz0 = Mathf.FloorToInt(point.z); | |
float tx = point.x - ix0; | |
float ty = point.y - iy0; | |
float tz = point.z - iz0; | |
ix0 &= hashMask; | |
iy0 &= hashMask; | |
iz0 &= hashMask; | |
int ix1 = ix0 + 1; | |
int iy1 = iy0 + 1; | |
int iz1 = iz0 + 1; | |
int h0 = hash[ix0]; | |
int h1 = hash[ix1]; | |
int h00 = hash[h0 + iy0]; | |
int h10 = hash[h1 + iy0]; | |
int h01 = hash[h0 + iy1]; | |
int h11 = hash[h1 + iy1]; | |
int h000 = hash[h00 + iz0]; | |
int h100 = hash[h10 + iz0]; | |
int h010 = hash[h01 + iz0]; | |
int h110 = hash[h11 + iz0]; | |
int h001 = hash[h00 + iz1]; | |
int h101 = hash[h10 + iz1]; | |
int h011 = hash[h01 + iz1]; | |
int h111 = hash[h11 + iz1]; | |
tx = Smooth(tx); | |
ty = Smooth(ty); | |
tz = Smooth(tz); | |
return Mathf.Lerp( | |
Mathf.Lerp(Mathf.Lerp(h000, h100, tx), Mathf.Lerp(h010, h110, tx), ty), | |
Mathf.Lerp(Mathf.Lerp(h001, h101, tx), Mathf.Lerp(h011, h111, tx), ty), | |
tz) * (1f / hashMask); | |
} | |
public static float Perlin1D (Vector3 point, float frequency) { | |
point *= frequency; | |
int i0 = Mathf.FloorToInt(point.x); | |
float t0 = point.x - i0; | |
float t1 = t0 - 1f; | |
i0 &= hashMask; | |
int i1 = i0 + 1; | |
float g0 = gradients1D[hash[i0] & gradientsMask1D]; | |
float g1 = gradients1D[hash[i1] & gradientsMask1D]; | |
float v0 = g0 * t0; | |
float v1 = g1 * t1; | |
float t = Smooth(t0); | |
return Mathf.Lerp(v0, v1, t) * 2f; | |
} | |
public static float Perlin2D (Vector3 point, float frequency) { | |
point *= frequency; | |
int ix0 = Mathf.FloorToInt(point.x); | |
int iy0 = Mathf.FloorToInt(point.y); | |
float tx0 = point.x - ix0; | |
float ty0 = point.y - iy0; | |
float tx1 = tx0 - 1f; | |
float ty1 = ty0 - 1f; | |
ix0 &= hashMask; | |
iy0 &= hashMask; | |
int ix1 = ix0 + 1; | |
int iy1 = iy0 + 1; | |
int h0 = hash[ix0]; | |
int h1 = hash[ix1]; | |
Vector2 g00 = gradients2D[hash[h0 + iy0] & gradientsMask2D]; | |
Vector2 g10 = gradients2D[hash[h1 + iy0] & gradientsMask2D]; | |
Vector2 g01 = gradients2D[hash[h0 + iy1] & gradientsMask2D]; | |
Vector2 g11 = gradients2D[hash[h1 + iy1] & gradientsMask2D]; | |
float v00 = Dot(g00, tx0, ty0); | |
float v10 = Dot(g10, tx1, ty0); | |
float v01 = Dot(g01, tx0, ty1); | |
float v11 = Dot(g11, tx1, ty1); | |
float tx = Smooth(tx0); | |
float ty = Smooth(ty0); | |
return Mathf.Lerp( | |
Mathf.Lerp(v00, v10, tx), | |
Mathf.Lerp(v01, v11, tx), | |
ty) * sqr2; | |
} | |
public static float Perlin3D (Vector3 point, float frequency) { | |
point *= frequency; | |
int ix0 = Mathf.FloorToInt(point.x); | |
int iy0 = Mathf.FloorToInt(point.y); | |
int iz0 = Mathf.FloorToInt(point.z); | |
float tx0 = point.x - ix0; | |
float ty0 = point.y - iy0; | |
float tz0 = point.z - iz0; | |
float tx1 = tx0 - 1f; | |
float ty1 = ty0 - 1f; | |
float tz1 = tz0 - 1f; | |
ix0 &= hashMask; | |
iy0 &= hashMask; | |
iz0 &= hashMask; | |
int ix1 = ix0 + 1; | |
int iy1 = iy0 + 1; | |
int iz1 = iz0 + 1; | |
int h0 = hash[ix0]; | |
int h1 = hash[ix1]; | |
int h00 = hash[h0 + iy0]; | |
int h10 = hash[h1 + iy0]; | |
int h01 = hash[h0 + iy1]; | |
int h11 = hash[h1 + iy1]; | |
Vector3 g000 = gradients3D[hash[h00 + iz0] & gradientsMask3D]; | |
Vector3 g100 = gradients3D[hash[h10 + iz0] & gradientsMask3D]; | |
Vector3 g010 = gradients3D[hash[h01 + iz0] & gradientsMask3D]; | |
Vector3 g110 = gradients3D[hash[h11 + iz0] & gradientsMask3D]; | |
Vector3 g001 = gradients3D[hash[h00 + iz1] & gradientsMask3D]; | |
Vector3 g101 = gradients3D[hash[h10 + iz1] & gradientsMask3D]; | |
Vector3 g011 = gradients3D[hash[h01 + iz1] & gradientsMask3D]; | |
Vector3 g111 = gradients3D[hash[h11 + iz1] & gradientsMask3D]; | |
float v000 = Dot(g000, tx0, ty0, tz0); | |
float v100 = Dot(g100, tx1, ty0, tz0); | |
float v010 = Dot(g010, tx0, ty1, tz0); | |
float v110 = Dot(g110, tx1, ty1, tz0); | |
float v001 = Dot(g001, tx0, ty0, tz1); | |
float v101 = Dot(g101, tx1, ty0, tz1); | |
float v011 = Dot(g011, tx0, ty1, tz1); | |
float v111 = Dot(g111, tx1, ty1, tz1); | |
float tx = Smooth(tx0); | |
float ty = Smooth(ty0); | |
float tz = Smooth(tz0); | |
return Mathf.Lerp( | |
Mathf.Lerp(Mathf.Lerp(v000, v100, tx), Mathf.Lerp(v010, v110, tx), ty), | |
Mathf.Lerp(Mathf.Lerp(v001, v101, tx), Mathf.Lerp(v011, v111, tx), ty), | |
tz); | |
} | |
public static float Sum (NoiseMethod method, Vector3 point, float frequency, int octaves, float lacunarity, float persistence) { | |
float sum = method(point, frequency); | |
float amplitude = 1f; | |
float range = 1f; | |
for (int o = 1; o < octaves; o++) { | |
frequency *= lacunarity; | |
amplitude *= persistence; | |
range += amplitude; | |
sum += method(point, frequency) * amplitude; | |
} | |
return sum / range; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment