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);
        }
Ejemplo n.º 2
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);
        }