private bool CheckChunkAt(IntegerCoordinate2D coordinate2D) { if (ChunkExistsAt(coordinate2D)) { return(false); } GenerateTile(coordinate2D); return(true); }
public IEnumerator GetChunkData(int chunkX, int chunkY, TerrainTile tile) { var coordinate = new IntegerCoordinate2D(chunkX, chunkY); if (ChunkExistsAt(coordinate)) { tile.data = _tileBuffer[coordinate].data; yield return(null); } else { yield return(gpuTerrainCompute ? TerrainGpuGenerator.GetChunkData(coordinate, this, tile) : TerrainCpuGenerator.GetChunkData(coordinate, this, tile)); } }
private void GenerateTile(IntegerCoordinate2D coordinate2D) { TerrainTile newTile; if (_unusedTileQueue.Count > 0) { var key = _unusedTileQueue.Dequeue(); newTile = _tileBuffer[key]; _tileBuffer.Remove(key); } else { newTile = Instantiate(terrainTilePrefab, _child).GetComponent <TerrainTile>(); } newTile.Build(this, coordinate2D.x, coordinate2D.y); _tileBuffer.Add(coordinate2D, newTile); }
public void Update() { var centerPosition = loadingCenter.position; var tileSize = (terrainGeneratorSettings.size - 1) * terrainGeneratorSettings.gridSize; var centerX = Mathf.FloorToInt((centerPosition.x + 0.5f * tileSize) / (tileSize)); var centerY = Mathf.FloorToInt((centerPosition.z + 0.5f * tileSize) / (tileSize)); if (centerX != _lastCenterX || centerY != _lastCenterY) { _currentLoadStartIndex = 0; _lastCenterX = centerX; _lastCenterY = centerY; } if (_currentLoadStartIndex == 0) { _unusedTileQueue.Clear(); foreach (var tile in _tileBuffer) { if (Mathf.Abs(tile.Key.x - centerX) > loadRadius + loadBorder || Mathf.Abs(tile.Key.y - centerY) > loadRadius + loadBorder) { _unusedTileQueue.Enqueue(tile.Key); } } } for (var i = _currentLoadStartIndex; i < _loadingCircle.Length; i++) { if (Time.time - _lastChunkLoad < timeBetweenChunkLoads) { break; } _intermediateCoordinate2D = new IntegerCoordinate2D(_loadingCircle[i].x + centerX, _loadingCircle[i].y + centerY); if (CheckChunkAt(_intermediateCoordinate2D)) { _lastChunkLoad = Time.time; } _currentLoadStartIndex = i; } }
public TerrainTile GetExistingTile(int chunkX, int chunkY) { var coordinate = new IntegerCoordinate2D(chunkX, chunkY); return(ChunkExistsAt(coordinate) ? _tileBuffer[coordinate] : null); }
private bool ChunkExistsAt(IntegerCoordinate2D coordinate2D) { return(_tileBuffer.TryGetValue(coordinate2D, out _)); }
public static IEnumerator GetChunkData(IntegerCoordinate2D coordinate2D, TerrainController controller, TerrainTile tile) { //Working = true; var settings = controller.terrainGeneratorSettings; var shader = settings.terrainComputeShader; //Debug.Log("Starting GPU Compute "+Time.frameCount); var dataSize = settings.size + 2; var kernel1 = settings.terrainComputeShader.FindKernel("TerrainGeneratorPass1"); var kernel2 = settings.terrainComputeShader.FindKernel("TerrainGeneratorPass2"); if (_inputData == null || _inputData.Length != dataSize * dataSize) { _inputData = new TerrainTileVertexData[dataSize * dataSize]; _dataBuffer = new ComputeBuffer(_inputData.Length, 24); //2 * Vector3 = 2 * (3 * float) = 2 * (3 * 4) = 24 _dataBuffer.SetData(_inputData); shader.SetInt("_size", dataSize); TerrainUtilities.TransferTerrainGeneratorSettingsToComputeShader(shader, settings); shader.SetBuffer(kernel1, "_Data", _dataBuffer); shader.SetBuffer(kernel2, "_Data", _dataBuffer); shader.SetFloat("_BlendExponent", controller.blendExponent); shader.SetFloat("_BlendOffset", controller.blendOffset); shader.SetVectorArray("_maxTessellationStrengths", controller.materialData.GetMaxTessellationStrengthArray()); } //Debug.Log("StartX: "+coordinate2D.x * (settings.size - 1)); settings.terrainComputeShader.SetInt("_startX", coordinate2D.x * (settings.size - 1)); settings.terrainComputeShader.SetInt("_startY", coordinate2D.y * (settings.size - 1)); //Init splat RenderTexture var splatTexture = new RenderTexture(dataSize, dataSize, 0) { enableRandomWrite = true, useMipMap = true, filterMode = FilterMode.Bilinear }; splatTexture.Create(); settings.terrainComputeShader.SetTexture(kernel2, "_splatTexture", splatTexture); /*if (tile.data.tessellationTexture != null) * { * Object.Destroy(tile.data.tessellationTexture); * }*/ //Init tessellation Texture var tessellationTexture = new RenderTexture(dataSize, dataSize, 0) { enableRandomWrite = true, useMipMap = true, filterMode = FilterMode.Point }; tessellationTexture.Create(); settings.terrainComputeShader.SetTexture(kernel2, "_tessellationTexture", tessellationTexture); settings.terrainComputeShader.Dispatch(kernel1, dataSize * dataSize / 8, 1, 1); settings.terrainComputeShader.Dispatch(kernel2, dataSize * dataSize / 8, 1, 1); var request = AsyncGPUReadback.Request(_dataBuffer); yield return(new WaitUntil(() => request.done)); _inputData = request.GetData <TerrainTileVertexData>().ToArray(); //Combine all data into output struct tile.data = new TerrainTileData { locationData = _inputData//, splatTexture = splatTexture, tessellationTexture = tessellationTexture }; yield return(null); }
public static IEnumerator GetChunkData(IntegerCoordinate2D coordinate2D, TerrainController controller, TerrainTile tile) { var settings = controller.terrainGeneratorSettings; var dataSize = settings.size + 2; var data = new TerrainTileVertexData[dataSize * dataSize]; var colors = new Color[settings.size * settings.size]; for (var x = 0; x < dataSize; x++) { for (var y = 0; y < dataSize; y++) { var position = new Vector2((x - 1 + coordinate2D.x * (settings.size - 1)) * settings.gridSize, (y - 1 + coordinate2D.y * (settings.size - 1)) * settings.gridSize); var h1 = Perlin(position, settings.offset, settings.scale1, settings.pow1) * Perlin(position, settings.offset, settings.scale2, settings.pow2) * settings.height1; var h3 = Perlin(position, settings.offset, settings.scale3, settings.pow3) * settings.height3; var h4 = 0.5f * (Perlin(position, settings.offset, settings.scale4, settings.pow4) + Perlin(position, settings.offset, settings.scale4 * 2, settings.pow4)) * settings.height4; var h5 = Perlin(position, settings.offset, settings.scale5, settings.pow5) * settings.height5; var mul1 = Perlin(position, settings.offset, settings.scale6, settings.pow6); var mul2 = Perlin(position, settings.offset, settings.scale7, settings.pow7) * settings.weightMultiplier2; var height = (h1 + h3 + h4 + h5) * (1 + (mul1 + mul2) / (1 + settings.weightMultiplier2) * settings.multiplierScale); var maxHeight = settings.height1 + settings.height3 + settings.height4 + settings.height5; var sandStrength = BlendSplat(1 - height / maxHeight + Perlin(position, settings.offset, settings.scale4 * 2, settings.pow4) * settings.sandRandom, settings.sandBlend, 0.99f); var snowStrength = (1 - sandStrength) * BlendSplat(height / maxHeight + Perlin(position, settings.offset, settings.scale4 * 2, settings.pow4) * settings.snowRandom, settings.snowBlend, 0.6f); var temperature = BlendSplat((Perlin(position, settings.offset, settings.temperatureScale, 1) * ((1 + (Perlin(position, settings.offset, settings.temperatureScale * 20, 1) - 0.5f) * settings.temperatureRandom))), settings.temperatureBlend, 0.5f); var remainingStrength = (1 - (snowStrength + sandStrength)); data[x + dataSize * y].position = new Vector3((x - 1) * settings.gridSize, height, (y - 1) * settings.gridSize); if (x > 0 && y > 0 && x < settings.size + 1 && y < settings.size + 1) { colors[(x - 1) + settings.size * (y - 1)] = new Color(remainingStrength * temperature, remainingStrength * (1 - temperature), sandStrength, snowStrength); } } } //Calculate Normals... for (var x = 0; x < settings.size; x++) { for (var y = 0; y < settings.size; y++) { var l = data[(x + 0) + dataSize * (y + 1)].position.y; var r = data[(x + 2) + dataSize * (y + 1)].position.y; var b = data[(x + 1) + dataSize * (y + 0)].position.y; var t = data[(x + 1) + dataSize * (y + 2)].position.y; var dx = 2 * (r - l); var dy = 2 * (t - b); var up = -4.0f * settings.gridSize; data[(x + 1) + dataSize * (y + 1)].normal = -(new Vector3(dx, up, dy) * 0.25f).normalized; } } for (var x = 0; x < settings.size; x++) { for (var y = 0; y < settings.size; y++) { var splat = colors[x + settings.size * y]; var normal = data[(x + 1) + dataSize * (y + 1)].normal; var tessellationStrength = GetTessellationStrength(splat, normal, controller.blendOffset, controller.blendExponent, controller.materialData.GetMaxTessellationStrengthArray()); //Debug.Log(tessellationStrength); data[(x + 1) + dataSize * (y + 1)].tessellationStrength = new Vector2(tessellationStrength, 0); } } tile.data = new TerrainTileData { locationData = data, splats = colors }; yield return(null); }