Пример #1
0
 private bool CheckChunkAt(IntegerCoordinate2D coordinate2D)
 {
     if (ChunkExistsAt(coordinate2D))
     {
         return(false);
     }
     GenerateTile(coordinate2D);
     return(true);
 }
Пример #2
0
        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));
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
        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;
            }
        }
Пример #5
0
        public TerrainTile GetExistingTile(int chunkX, int chunkY)
        {
            var coordinate = new IntegerCoordinate2D(chunkX, chunkY);

            return(ChunkExistsAt(coordinate) ? _tileBuffer[coordinate] : null);
        }
Пример #6
0
 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);
        }
Пример #8
0
        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);
        }