// ... /*public struct GenerateNoise : IJob { * public int seed; * public Noise.NoiseSource noiseSource; * public GPUNoiseGenerator.NoiseData noiseData; * public NativeArray<float> heightMapX; * public NativeArray<float> heightMapY; * * public void Execute() { * float[,] heightMap; * * switch (noiseSource) { * case Noise.NoiseSource.GPU_2DFloatArray: * heightMap = GPUNoiseGenerator.GenerateNoiseArray(seed, noiseData); * break; * case Noise.NoiseSource.GPU_RenderTextureTo2DFloatArray: * heightMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, noiseData); * break; * default: * throw new System.Exception("Not Implemented"); * } * * float[] x = new float[heightMap.Length]; * float[] y = new float[heightMap.Length]; * for (int i = 0; i < heightMap.Length; ++i) { * x[i] = heightMap[i, 0]; * y[i] = heightMap[i, 1]; * } * heightMapX.CopyFrom(x); * heightMapY.CopyFrom(y); * } * }*/ // Generate Planet LOD public Tuple <GameObject, List <RenderTexture> > GeneratePlanetChunk(int gridSize, Vector3 position, bool hasHeight, bool hasCollider, string side = "") { string name = ""; Vector2 rotation = Vector3.zero; Mesh chunkMesh = null; Material[] materials; float[][,] heightMaps; List <RenderTexture> renderTextureList; // Jos full niin pitää kaikki sivut generoida if (side[0] == 'F') { name = "F"; // TODO: LOD Full planet generation jos ees haluun sitä return(Tuple.Create(new GameObject(side), new List <RenderTexture>())); } // Generoidaan yksi sivu tai quarter else { chunkMesh = GenerateSphericalMesh(Mathf.RoundToInt(gridSize), side); // generoi spherical meshen GPUNoiseGenerator.Side planetSide; switch (side[0]) { case '0': planetSide = GPUNoiseGenerator.Side.Bottom; rotation = new Vector2(270, 0); break; case '1': planetSide = GPUNoiseGenerator.Side.Left; rotation = new Vector2(0, 90); break; case '2': planetSide = GPUNoiseGenerator.Side.Front; rotation = new Vector2(0, 0); break; case '3': planetSide = GPUNoiseGenerator.Side.Right; rotation = new Vector2(0, -90); break; case '4': planetSide = GPUNoiseGenerator.Side.Top; rotation = new Vector2(90, 0); break; default: //case '5': planetSide = GPUNoiseGenerator.Side.Back; rotation = new Vector2(180, 0); break; } // TODO: en tiiä pitäiskö vaan parametrina laittaa planet side ja side noise generaattoriin ettei tarttee jokaiselle laittaa niitä erikseen ocean.side = planetSide; plainHills.side = planetSide; largeMountains.side = planetSide; mediumDetail.side = planetSide; side = side.Substring(1); ocean.quarter = side; plainHills.quarter = side; largeMountains.quarter = side; mediumDetail.quarter = side; name = planetSide.ToString(); if (side != "") { name += "_" + side; } float[,] oceanHeightMap; // = new float[(int)ocean.resolution, (int)ocean.resolution]; float[,] plainHillsHeightMap; // = new float[(int)plainHills.resolution, (int)plainHills.resolution]; float[,] largeMountainsHeightMap; // = new float[(int)largeMountains.resolution, (int)largeMountains.resolution]; float[,] mediumDetailHeightMap; // = new float[(int)mediumDetail.resolution, (int)mediumDetail.resolution]; switch (noiseSource) { case Noise.NoiseSource.GPU_2DFloatArray: oceanHeightMap = GPUNoiseGenerator.GenerateNoiseArray(seed, ocean, gridSize); plainHillsHeightMap = GPUNoiseGenerator.GenerateNoiseArray(seed, plainHills, radius, gridSize); largeMountainsHeightMap = GPUNoiseGenerator.GenerateNoiseArray(seed, largeMountains, radius, gridSize); mediumDetailHeightMap = GPUNoiseGenerator.GenerateNoiseArray(seed, mediumDetail, gridSize); break; case Noise.NoiseSource.GPU_RenderTextureTo2DFloatArray: oceanHeightMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, ocean); plainHillsHeightMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, plainHills); largeMountainsHeightMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, largeMountains); mediumDetailHeightMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, mediumDetail); break; default: throw new System.Exception("Not Implemented"); } heightMaps = new float[][, ] { oceanHeightMap, plainHillsHeightMap, largeMountainsHeightMap, mediumDetailHeightMap }; //heightMaps = new float[][,] { oceanHeightMap, plainHillsHeightMap, largeMountainsHeightMap }; materials = new Material[1]; // Height Map material /*materials[0] = new Material(Shader.Find("Unlit/Texture")); * Texture2D noiseTexture = TextureGenerator.TextureFromHeightMap(mediumDetailHeightMap); * Vector2 textureScale = new Vector2(1f / gridSize, 1f / gridSize); * materials[0].mainTextureScale = textureScale; * materials[0].mainTexture = noiseTexture;*/ // Textured //materials[0] = new Material(Shader.Find("Shader Forge/Terrain")); materials[0] = new Material(Shader.Find("Shader Graphs/TestPlanetTextureShader")); RenderTexture oceanTex = GPUNoiseGenerator.GenerateNoise(seed, ocean, radius); RenderTexture plainHillsTex = GPUNoiseGenerator.GenerateNoise(seed, plainHills, radius); RenderTexture largeMountainsTex = GPUNoiseGenerator.GenerateNoise(seed, largeMountains, radius); RenderTexture mediumDetailTex = GPUNoiseGenerator.GenerateNoise(seed, mediumDetail, radius); materials[0].SetTexture(OCEAN_NOISE_TEXTURE_NAME, oceanTex); materials[0].SetTexture(PLAIN_HILLS_NOISE_TEXTURE_NAME, plainHillsTex); materials[0].SetTexture(LARGE_MOUNTAINS_NOISE_TEXTURE_NAME, largeMountainsTex); materials[0].SetTexture(MEDIUM_DETAIL_NOISE_TEXTURE_NAME, mediumDetailTex); Vector2 tiling = new Vector2(1f / gridSize, 1f / gridSize); materials[0].SetVector("_Tiling", tiling); materials[0].SetFloat("_Brightness1", 6.36f); materials[0].SetFloat("_Brightness2", 1.66f); materials[0].SetFloat("_Brightness3", 0.4f); materials[0].SetFloat("_Brightness4", 22.73f); materials[0].SetTexture("_MainTex", oceanTex); renderTextureList = new List <RenderTexture> { oceanTex, plainHillsTex, largeMountainsTex, mediumDetailTex }; // //mat.SetTexture("_MedTex", ); //mat.SetTexture("_HighTex", ); //mat.SetTexture("_DisplacementTexture", ); // } return(Tuple.Create( GeneratePlanetChunkObj(name, side, position, planetSize, rotation, chunkMesh, materials, ref heightMaps, gridSize, hasHeight, hasCollider), renderTextureList )); }
// Generate noise map //mapSizeSqrt, mapSizeSqrt, seed, side, offset, octaves, persistence, lacunarity, noiseSource public static float[,] GenerateNoiseMap(int seed, Vector3 offset, GPUNoiseGenerator.NoiseData noise, float scale, NoiseSource source, int?meshGridSize = null, float zoom = 1, int performanceTestLoops = 1, float radius = 100) { int mapSizeSqrt = (int)noise.resolution; float[,] noiseMap = new float[mapSizeSqrt, mapSizeSqrt]; System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); st.Start(); for (int performanceLoopIndex = 0; performanceLoopIndex < performanceTestLoops; ++performanceLoopIndex) { switch (source) { case NoiseSource.Unity: #region [ - Unity Noise - ] Vector2 chunkOffset = offset; //GenerateFalloffMap(ref falloffMap, mapChunkSize); /* Generate Height Map * (mapSide tarkottaa yhen spherical cuben reunan HeightMapin kokoa) * [5] * [4] * [1][2][3] * [0] */ // Laskee sphericalCuben valitun lähtöpisteen for (int i = 0, len = int.Parse(((int)noise.side).ToString()); i <= len; ++i) { switch (i) { case 0: chunkOffset.x += mapSizeSqrt; break; case 1: chunkOffset.x -= mapSizeSqrt; chunkOffset.y += mapSizeSqrt; break; case 2: chunkOffset.x += mapSizeSqrt; break; case 3: chunkOffset.x += mapSizeSqrt; break; case 4: chunkOffset.x -= mapSizeSqrt; chunkOffset.y += mapSizeSqrt; break; case 5: chunkOffset.y += mapSizeSqrt; break; } } // Laskee quartereitten (..quartereitten (..quartereitten (..jne))) lähtöpisteen int quarterSize = mapSizeSqrt; for (int i = 0, len = noise.quarter.Length; i < len; ++i) { //quarterSize /= 2; // quarterin leveys\korkeus scale *= 2; switch (noise.quarter[i]) { case '0': // vasenala // -> piste ei liiku minnekkään Debug.Log("scale: " + scale + ", quarter size: " + quarterSize + ", side:" + noise.quarter[i] + ", offset: " + chunkOffset.x + " | " + chunkOffset.y); break; case '1': // oikeeala chunkOffset.x += quarterSize / scale; Debug.Log("scale: " + scale + ", quarter size: " + quarterSize + ", side:" + noise.quarter[i] + ", offset: " + chunkOffset.x + " | " + chunkOffset.y); break; case '2': // vasenylä chunkOffset.y += quarterSize / scale; Debug.Log("scale: " + scale + ", quarter size: " + quarterSize + ", side:" + noise.quarter[i] + ", offset: " + chunkOffset.x + " | " + chunkOffset.y); break; case '3': // oikeeylä chunkOffset.x += quarterSize / scale; chunkOffset.y += quarterSize / scale; Debug.Log("scale: " + scale + ", quarter size: " + quarterSize + ", side:" + noise.quarter[i] + ", offset: " + chunkOffset.x + " | " + chunkOffset.y); break; } } Vector2[] octaveOffset = new Vector2[noise.octaves]; maxPossibleHeight = 0; noise.amplitude = 1; noise.frequency = 1; NormalizeMode normalizeMode = NormalizeMode.Global; System.Random prng = new System.Random(seed); Vector2 randomOffsetFromSeed = new Vector2(prng.Next(-100000, 100000) - chunkOffset.x, prng.Next(-100000, 100000) - chunkOffset.y); for (i = 0; i < noise.octaves; ++i) { octaveOffset[i] = randomOffsetFromSeed; maxPossibleHeight += noise.amplitude; noise.amplitude *= noise.persistence; } if (scale <= 0) { scale = 0.0001f; } maxLocalNoiseHeight = float.MinValue; minLocalNoiseHeight = float.MaxValue; halfWidth = mapSizeSqrt / 2f; halfHeight = mapSizeSqrt / 2f; for (y = 0; y < mapSizeSqrt; ++y) { for (x = 0; x < mapSizeSqrt; ++x) { noise.amplitude = 1; noise.frequency = 1; noiseHeight = 0; for (i = 0; i < noise.octaves; ++i) // Oktaavien teko kuluttaa sikana eli tarkkana { sampleX = (x - mapSizeSqrt) / scale * noise.frequency + octaveOffset[i].x * noise.frequency; sampleY = (y - mapSizeSqrt) / scale * noise.frequency + octaveOffset[i].y * noise.frequency; perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1; // tää on raskas, * 2 - 1 tekee sen että se menee [-1, 1]) noiseHeight += perlinValue * noise.amplitude; //Debug.Log("X: " + x + ", Y: " + y + " | " + perlinValue + " | " + amplitude); noise.amplitude *= noise.persistence; noise.frequency *= noise.lacunarity; } if (noiseHeight > maxLocalNoiseHeight) { maxLocalNoiseHeight = noiseHeight; } else if (noiseHeight < minLocalNoiseHeight) { minLocalNoiseHeight = noiseHeight; } noiseMap[x, y] = noiseHeight; //Debug.Log("X: " + x + ", Y: " + y + " | " + noiseMap[x, y]); //noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } } for (int y = 0; y < mapSizeSqrt; ++y) { for (int x = 0; x < mapSizeSqrt; ++x) { if (normalizeMode == NormalizeMode.Local) { noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]); } else { float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight / 0.9f); noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue); } } } #endregion break; case NoiseSource.LibNoise: #region [ - LibNoise - ] Perlin perlinNoise = new Perlin { Quality = QualityMode.Medium, OctaveCount = noise.octaves, Lacunarity = noise.lacunarity, Seed = seed, Persistence = noise.persistence, Frequency = noise.frequency }; LibNoise.Unity.ModuleBase moduleBase; moduleBase = perlinNoise; Noise2D noise2D = new LibNoise.Unity.Noise2D((int)noise.resolution, (int)noise.resolution, moduleBase); //noise.GeneratePlanar((double)offset.x, (double)(offset.x + mapWidth), (double)(offset.y + mapHeight), (double)offset.y); noise2D.GeneratePlanar((int)noise.resolution, 0, (int)noise.resolution, 0); noiseMap = noise2D.m_data; #endregion break; case NoiseSource.GPU_2DFloatArray: #region [ - GPU 2D Float Array - ] noiseMap = GPUNoiseGenerator.GenerateNoiseArray(seed, noise, radius, meshGridSize, offset, zoom); #endregion break; case NoiseSource.GPU_RenderTextureTo2DFloatArray: #region [ - GPU Render Texture to 2D Float Array - ] noiseMap = GPUNoiseGenerator.GenerateNoiseArrayFromRenderTexture(seed, noise); #endregion break; default: return(null); } } st.Stop(); if (performanceTestLoops > 1) { Debug.Log(string.Format("Generated noise with {0} {1} times and it took {2} ms to complete.", source.ToString(), performanceTestLoops, st.ElapsedMilliseconds)); } return(noiseMap); }