예제 #1
0
        public static void SnapshotSplats(this MMTerrainLayer layer, Terrain terrain)
        {
            var rawSplats = terrain.terrainData.GetAlphamaps(0, 0, terrain.terrainData.alphamapWidth,
                                                             terrain.terrainData.alphamapHeight);

            layer.SplatData.Clear();

            var splatWrapperLookup = ResolvePrototypes(terrain.terrainData.splatPrototypes);

            for (var k = 0; k < rawSplats.GetLength(2); ++k)
            {
                var prototype = terrain.terrainData.splatPrototypes[k];
                SplatPrototypeWrapper wrapper;
                if (!splatWrapperLookup.TryGetValue(prototype, out wrapper))
                {
                    continue;
                }
                var data = new Serializable2DByteArray(terrain.terrainData.alphamapResolution,
                                                       terrain.terrainData.alphamapResolution);
                float sum = 0;
                for (var u = 0; u < rawSplats.GetLength(0); ++u)
                {
                    for (var v = 0; v < rawSplats.GetLength(1); ++v)
                    {
                        var sample = (byte)Mathf.Clamp(rawSplats[u, v, k] * 255f, 0, 255);
                        data[v, u] = sample;
                        sum       += sample;
                    }
                }
                if (sum > 0)
                {
                    layer.SplatData[wrapper] = data;
                }
            }
        }
예제 #2
0
        private void WriteSplatsToTerrain(TerrainWrapper wrapper, Bounds bounds)
        {
            if (SplatData == null || SplatData.Count == 0)
            {
                return;
            }

            if (BlendMode == EMMTerrainLayerBlendMode.Set)
            {
                wrapper.CompoundTerrainData.SplatData.Clear();
            }

            var terrain     = wrapper.Terrain;
            var splatRes    = terrain.terrainData.alphamapResolution;
            var stencilSize = new Common.Coord(Stencil.Width, Stencil.Height);

            if (BlendMode == EMMTerrainLayerBlendMode.Stencil)
            {
                // Remove Stencil Values
                foreach (var pair in wrapper.CompoundTerrainData.SplatData)
                {
                    var data = pair.Value;
                    BlendMMTerrainLayerUtility.StencilEraseArray(ref data, Stencil, Common.Coord.Zero, new Common.Coord(splatRes, splatRes),
                                                                 stencilSize, false, false);
                }
            }

            foreach (var keyValuePair in SplatData)
            {
                var splatPrototypeWrapper = keyValuePair.Key;
                var readData = keyValuePair.Value;

                if (readData == null || readData.Width != splatRes || readData.Height != splatRes)
                {
                    Debug.LogWarning(
                        string.Format(
                            "Failed to write splat layer {0} for layer '{3}' as it was the wrong resolution. Expected {1}x{1}, got {2}x{2}",
                            splatPrototypeWrapper.name, splatRes, readData.Width, name), wrapper);
                    continue;
                }

                Serializable2DByteArray data;
                if (!wrapper.CompoundTerrainData.SplatData.TryGetValue(splatPrototypeWrapper, out data) ||
                    data.Width != splatRes || data.Height != splatRes)
                {
                    data = new Serializable2DByteArray(splatRes, splatRes);
                }

                BlendMMTerrainLayerUtility.BlendArray(ref data, readData,
                                                      IsValidStencil(Stencil) ? Stencil : null,
                                                      BlendMode, Common.Coord.Zero, stencilSize);

                wrapper.CompoundTerrainData.SplatData[splatPrototypeWrapper] = data;
            }
            GC.Collect();
        }
예제 #3
0
        public void SetDetailMap(DetailPrototypeWrapper prototype, int x, int z, Serializable2DByteArray details, int dRes, Serializable2DFloatArray stencil = null)
        {
            if (DetailData == null)
            {
                DetailData = new CompressedDetailDataLookup();
            }

            Serializable2DByteArray existingDetails;

            if (!DetailData.TryGetValue(prototype, out existingDetails) || existingDetails.Width != dRes ||
                existingDetails.Height != dRes)
            {
                existingDetails       = new Serializable2DByteArray(dRes, dRes);
                DetailData[prototype] = existingDetails;
            }

            var width  = details.Width;
            var height = details.Height;

            for (var u = x; u < x + width; ++u)
            {
                for (var v = z; v < z + height; ++v)
                {
                    var hx = u - x;
                    var hz = v - z;

                    try
                    {
                        var splatSample = details[hx, hz];
                        if (stencil != null)
                        {
                            existingDetails[u, v] = (byte)Mathf.Clamp(Mathf.Lerp(existingDetails[u, v], splatSample, stencil[hx, hz]), 0, 255);
                        }
                        else
                        {
                            existingDetails[u, v] = (byte)splatSample;
                        }
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }


#if UNITY_EDITOR
            UnityEditor.EditorUtility.SetDirty(this);
#endif
        }
예제 #4
0
        public override Serializable2DByteArray BlendDetails(DetailPrototypeWrapper detailWrapper, int x, int z, int width, int height, int dRes,
                                                             Serializable2DByteArray result)
        {
            var layerDetails = GetDetailMap(detailWrapper, x, z, width, height, dRes);

            if (layerDetails == null)
            {
                return(result);
            }

            var stencil = IsValidStencil(Stencil)
                ? Stencil
                : null;

            BlendMMTerrainLayerUtility.BlendArray(ref result, layerDetails, stencil, BlendMode,
                                                  Common.Coord.Zero, new Common.Coord(dRes, dRes));
            return(result);
        }
예제 #5
0
        /*
         * public static float BilinearSample(this Serializable2DIntArray array, Vector2 normalizedCoord)
         * {
         *  if (array == null)
         *  {
         *      return 0;
         *  }
         *
         *  if (normalizedCoord.x < 0 || normalizedCoord.x > 1 || normalizedCoord.y < 0 || normalizedCoord.y > 1)
         *      return 0;
         *  normalizedCoord = new Vector2(normalizedCoord.x * array.Width, normalizedCoord.y * array.Height);
         *
         *  int xMin = Mathf.FloorToInt(normalizedCoord.x);
         *  int xMax = Mathf.CeilToInt(normalizedCoord.x);
         *  int yMin = Mathf.FloorToInt(normalizedCoord.y);
         *  int yMax = Mathf.CeilToInt(normalizedCoord.y);
         *
         *  xMin = Mathf.Clamp(xMin, 0, array.Width - 1);
         *  xMax = Mathf.Clamp(xMax, 0, array.Width - 1);
         *  yMin = Mathf.Clamp(yMin, 0, array.Height - 1);
         *  yMax = Mathf.Clamp(yMax, 0, array.Height - 1);
         *
         *  float v1 = array[xMin, yMin];
         *  float v2 = array[xMin, yMax];
         *  float v3 = array[xMax, yMin];
         *  float v4 = array[xMax, yMax];
         *
         *  if (Math.Abs(v1 + v2 + v3 + v4) < Single.Epsilon)
         *  {
         *      return 0;
         *  }
         *
         *  float xFrac = normalizedCoord.x.Frac();
         *  float yFrac = normalizedCoord.y.Frac();
         *
         *  v1 *= (1 - xFrac) * (1 - yFrac);
         *  v2 *= (1 - xFrac) * (yFrac);
         *  v3 *= (xFrac) * (1 - yFrac);
         *  v4 *= (xFrac) * (yFrac);
         *
         *  return v1 + v2 + v3 + v4;
         * }
         */

        public static float BilinearSample(this Serializable2DByteArray array, Vector2 normalizedCoord)
        {
            if (array == null)
            {
                return(0);
            }

            if (normalizedCoord.x < 0 || normalizedCoord.x > 1 || normalizedCoord.y < 0 || normalizedCoord.y > 1)
            {
                return(0);
            }
            normalizedCoord = new Vector2(normalizedCoord.x * array.Width, normalizedCoord.y * array.Height);

            int xMin = Mathf.FloorToInt(normalizedCoord.x);
            int xMax = Mathf.CeilToInt(normalizedCoord.x);
            int yMin = Mathf.FloorToInt(normalizedCoord.y);
            int yMax = Mathf.CeilToInt(normalizedCoord.y);

            xMin = Mathf.Clamp(xMin, 0, array.Width - 1);
            xMax = Mathf.Clamp(xMax, 0, array.Width - 1);
            yMin = Mathf.Clamp(yMin, 0, array.Height - 1);
            yMax = Mathf.Clamp(yMax, 0, array.Height - 1);

            float v1 = array[xMin, yMin];
            float v2 = array[xMin, yMax];
            float v3 = array[xMax, yMin];
            float v4 = array[xMax, yMax];

            if (Math.Abs(v1 + v2 + v3 + v4) < Single.Epsilon)
            {
                return(0);
            }

            float xFrac = normalizedCoord.x.Frac();
            float yFrac = normalizedCoord.y.Frac();

            v1 *= (1 - xFrac) * (1 - yFrac);
            v2 *= (1 - xFrac) * (/*1 - */ yFrac);
            v3 *= (/*1 - */ xFrac) * (1 - yFrac);
            v4 *= (/*1 - */ xFrac) * (/*1 -*/ yFrac);

            return(v1 + v2 + v3 + v4);
        }
예제 #6
0
        public override Serializable2DByteArray BlendSplats(SplatPrototypeWrapper splat, int x, int z, int width, int height, int aRes,
                                                            Serializable2DByteArray result)
        {
            var layerSplats = GetSplatmap(splat, x, z, width, height, aRes);

            if (layerSplats == null)
            {
                return(result);
            }

            var stencil = BlendMode == EMMTerrainLayerBlendMode.Stencil && IsValidStencil(Stencil) ? Stencil : null;

            BlendMMTerrainLayerUtility.BlendArray(ref result,
                                                  layerSplats,
                                                  stencil,
                                                  BlendMode,
                                                  new Common.Coord(x, z),
                                                  new Common.Coord(aRes, aRes));
            return(result);
        }
예제 #7
0
        public override Serializable2DByteArray GetDetailMap(DetailPrototypeWrapper detailWrapper, int x, int z, int width, int height, int detailResolution)
        {
            if (DetailData == null)
            {
                return(null);
            }

            Serializable2DByteArray data;

            if (!DetailData.TryGetValue(detailWrapper, out data))
            {
                return(null);
            }

            if (data.Width != detailResolution || data.Height != detailResolution)
            {
                DetailData.Remove(detailWrapper);
                return(null);
            }

            var detailMap = new Serializable2DByteArray(width, height);

            for (var u = x; u < x + width; ++u)
            {
                for (var v = z; v < z + height; ++v)
                {
                    var hx = u - x;
                    var hz = v - z;
                    try
                    {
                        var detail = data[u, v];
                        detailMap[hx, hz] = detail;
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }
            return(detailMap);
        }
예제 #8
0
        public override Serializable2DByteArray GetSplatmap(SplatPrototypeWrapper prototype, int x, int z, int width, int height, int splatResolution)
        {
            if (SplatData == null)
            {
                return(null);
            }

            Serializable2DByteArray data;

            if (!SplatData.TryGetValue(prototype, out data))
            {
                return(null);
            }

            if (data.Width != splatResolution || data.Height != splatResolution)
            {
                SplatData.Remove(prototype);
                return(null);
            }

            var splats = new Serializable2DByteArray(width, height);

            for (var u = x; u < x + width; ++u)
            {
                for (var v = z; v < z + height; ++v)
                {
                    var hx = u - x;
                    var hz = v - z;
                    try
                    {
                        var splatSample = data[u, v];
                        splats[hx, hz] = splatSample;
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }
            return(splats);
        }
예제 #9
0
        public static void SnapshotDetails(this MMTerrainLayer layer, Terrain terrain)
        {
            layer.DetailData.Clear();
            var prototypes    = terrain.terrainData.detailPrototypes;
            var dRes          = terrain.terrainData.detailResolution;
            var wrapperLookup = ResolvePrototypes(prototypes);

            for (var i = 0; i < prototypes.Length; i++)
            {
                DetailPrototypeWrapper wrapper;
                var prototype = prototypes[i];
                if (!wrapperLookup.TryGetValue(prototype, out wrapper))
                {
                    continue;
                }

                var data      = new Serializable2DByteArray(dRes, dRes);
                var detailMap = terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailWidth,
                                                                   terrain.terrainData.detailHeight, i);
                int sum = 0;
                for (var u = 0; u < detailMap.GetLength(0); u++)
                {
                    for (var v = 0; v < detailMap.GetLength(1); v++)
                    {
                        var sample = (byte)detailMap[u, v];
                        data[v, u] = sample;
                        sum       += sample;
                    }
                }

                if (sum > 0)
                {
                    layer.DetailData.Add(wrapper, data);
                }
            }
        }
예제 #10
0
 public virtual Serializable2DByteArray BlendDetails(DetailPrototypeWrapper detail,
                                                     int x, int z, int width, int height, int dRes, Serializable2DByteArray result)
 {
     // throw new NotImplementedException();
     //Debug.LogErrorFormat("BlendDetails is not implemented for {0} ({1})", name, GetType());
     return(result);
 }
예제 #11
0
        public void SetSplatmap(SplatPrototypeWrapper prototype, int x, int z,
                                float[,] splats, int splatRes, Serializable2DFloatArray stencil = null)
        {
            if (splats == null || prototype == null)
            {
                return;
            }
            if (SplatData == null)
            {
                SplatData = new CompressedSplatDataLookup();
            }

            Serializable2DByteArray existingSplats;

            if (!SplatData.TryGetValue(prototype, out existingSplats) || existingSplats.Width != splatRes ||
                existingSplats.Height != splatRes)
            {
                existingSplats       = new Serializable2DByteArray(splatRes, splatRes);
                SplatData[prototype] = existingSplats;
            }

            var width  = splats.GetLength(0);
            var height = splats.GetLength(1);

            for (var u = x; u < x + width; ++u)
            {
                if (u < 0 || u >= splatRes)
                {
                    continue;
                }
                for (var v = z; v < z + height; ++v)
                {
                    if (v < 0 || v >= splatRes)
                    {
                        continue;
                    }

                    var hx = u - x;
                    var hz = v - z;

                    try
                    {
                        var splatSample = splats[hx, hz] * 255f;

                        if (stencil != null)
                        {
                            var stencilVal = stencil[hx, hz];
                            splatSample = (byte)Mathf.Clamp(Mathf.Lerp(existingSplats[u, v], splatSample, stencilVal), 0, 255);
                        }

                        existingSplats[u, v] = (byte)Mathf.Clamp(splatSample, 0, 255);
                    }
                    catch (Exception)
                    {
                        throw;
                    }
                }
            }


#if UNITY_EDITOR
            UnityEditor.EditorUtility.SetDirty(this);
#endif
        }
예제 #12
0
        private void WriteDetailsToTerrain(TerrainWrapper wrapper, Bounds bounds)
        {
            if (DetailData == null || DetailData.Count == 0)
            {
                return;
            }

            var terrain          = wrapper.Terrain;
            var detailResolution = terrain.terrainData.detailResolution;

            var detailCoordMin = terrain.WorldToDetailCoord(bounds.min);
            var detailCoordMax = terrain.WorldToDetailCoord(bounds.max);

            detailCoordMin = new Common.Coord(Mathf.Clamp(detailCoordMin.x, 0, detailResolution - 1),
                                              Mathf.Clamp(detailCoordMin.z, 0, detailResolution - 1));
            detailCoordMax = new Common.Coord(Mathf.Clamp(detailCoordMax.x, 0, detailResolution - 1),
                                              Mathf.Clamp(detailCoordMax.z, 0, detailResolution - 1));

            if (BlendMode == EMMTerrainLayerBlendMode.Set)
            {
                wrapper.CompoundTerrainData.DetailData.Clear();
            }

            foreach (var keyValuePair in DetailData)
            {
                var detailPrototypeWrapper = keyValuePair.Key;
                var readData = keyValuePair.Value;

                if (readData == null || readData.Width != detailResolution || readData.Height != detailResolution)
                {
                    Debug.LogWarning(
                        string.Format(
                            "Failed to write detail layer {0} for layer '{3}' as it was the wrong resolution. Expected {1}x{1}, got {2}x{2}",
                            detailPrototypeWrapper.name, detailResolution, readData.Width, name), wrapper);
                    continue;
                }

                Serializable2DByteArray data;
                if (!wrapper.CompoundTerrainData.DetailData.TryGetValue(detailPrototypeWrapper, out data) ||
                    data.Width != detailResolution || data.Height != detailResolution)
                {
                    data = new Serializable2DByteArray(detailResolution, detailResolution);
                }

                for (var u = detailCoordMin.x; u < detailCoordMax.x; ++u)
                {
                    var uF = u / (float)detailResolution;
                    //var arrayU = u - detailCoordMin.x;
                    for (var v = detailCoordMin.z; v < detailCoordMax.z; ++v)
                    {
                        var vF = v / (float)detailResolution;
                        //var arrayV = v - detailCoordMin.x;

                        if (BlendMode == EMMTerrainLayerBlendMode.Set)
                        {
                            data[u, v] = readData[u, v];
                        }
                        else if (BlendMode == EMMTerrainLayerBlendMode.Additive)
                        {
                            data[u, v] += readData[u, v];
                        }
                        else if (BlendMode == EMMTerrainLayerBlendMode.Stencil)
                        {
                            var stencil = this.GetStencilStrength(new Vector2(uF, vF));
                            if (stencil > 0)
                            {
                                var dataVal = data[u, v];
                                var readVal = readData[u, v];
                                var newVal  = (byte)
                                              Mathf.RoundToInt(Mathf.Clamp(Mathf.Lerp(dataVal, readVal, stencil), 0, 255));
                                data[u, v] = newVal;
                            }
                        }
                    }
                }

                /*BlendArrayUtility.BlendArray(ref data, readData,
                 *      Stencil != null ? Stencil.Select(0, 0, detailResolution, detailResolution) : null,
                 *      BlendMode, TerrainCoord.Zero, new TerrainCoord(detailResolution - 1, detailResolution - 1));*/
                wrapper.CompoundTerrainData.DetailData[detailPrototypeWrapper] = data;
            }
            GC.Collect();
        }
예제 #13
0
        public override void ProcessSplats(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var terrain    = wrapper.Terrain;
            var splatRes   = wrapper.Terrain.terrainData.alphamapResolution;
            var mainSpline = NodeConnection.GetSpline();
            var radius     = config.Radius;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = wrapper.Terrain.GetComponent <Collider>().bounds;

            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            float planeGive = -(wrapper.Terrain.terrainData.size.x / wrapper.Terrain.terrainData.alphamapResolution) * SplatOffset;
            Plane startPlane, endPlane;

            GenerateSplinePlanes(planeGive, mainSpline, out startPlane, out endPlane);

            // Get matrix space min/max
            var matrixMin = terrain.WorldToSplatCoord(bounds.min, TerrainX.RoundType.Floor);
            var matrixMax = terrain.WorldToSplatCoord(bounds.max, TerrainX.RoundType.Ceil);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMin.z, 0, terrain.terrainData.alphamapResolution));
            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMax.z, 0, terrain.terrainData.alphamapResolution));

            var floatArraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);

            // Get all the existing compound splats
            var currentPrototypes = wrapper.GetCompoundSplatPrototypes(layer, true);
            var baseData          = layer.GetSplatMaps(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, splatRes);

            stencilKey = GetStencilKey();
            Serializable2DFloatArray thisPatchStencil = new Serializable2DFloatArray(floatArraySize.x,
                                                                                     floatArraySize.z);

            foreach (var splatConfiguration in config.SplatConfigurations)
            {
                var splatPrototypeWrapper = splatConfiguration.SplatPrototype;
                Serializable2DByteArray baseLayerSplat;
                if (!baseData.TryGetValue(splatPrototypeWrapper, out baseLayerSplat))
                {
                    baseLayerSplat = new Serializable2DByteArray(floatArraySize.x, floatArraySize.z);
                    baseData[splatPrototypeWrapper] = baseLayerSplat;
                }

                for (var dz = 0; dz < floatArraySize.z; ++dz)
                {
                    for (var dx = 0; dx < floatArraySize.x; ++dx)
                    {
                        var coordX   = matrixMin.x + dx;
                        var coordZ   = matrixMin.z + dz;
                        var worldPos = terrain.SplatCoordToWorldPos(new Common.Coord(coordX, coordZ));
                        worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);

                        if (terrain.ContainsPointXZ(worldPos) &&
                            objectBounds.Contains(worldPos) &&
                            GeometryExtensions.BetweenPlanes(worldPos, startPlane, endPlane))
                        {
                            var uniformT                   = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                            var closestOnSpline            = mainSpline.GetUniformPointOnSpline(uniformT);
                            var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / (config.Radius);
                            if (normalizedFlatDistToSpline != Mathf.Clamp01(normalizedFlatDistToSpline))
                            {
                                continue;
                            }
                            var maskValue       = config.SplatFalloff.Evaluate(normalizedFlatDistToSpline);
                            var writeFloatValue = splatConfiguration.SplatStrength * maskValue;
                            var writeValue      = (byte)Mathf.RoundToInt(Mathf.Clamp(writeFloatValue * 255f, 0, 255));
                            var mainRead        = baseLayerSplat[dx, dz];
                            var newVal          = (byte)Mathf.Clamp(Mathf.Max(writeValue, mainRead), 0, 255);
                            var delta           = newVal - mainRead;

                            if (delta < 1 / 255f)
                            {
                                continue;
                            }

                            foreach (var currentPrototype in currentPrototypes)
                            {
                                if (!baseData.ContainsKey(currentPrototype))
                                {
                                    continue;
                                }
                                if (currentPrototype == splatPrototypeWrapper)
                                {
                                    continue;
                                }
                                var otherSplatFloatValue    = baseData[currentPrototype][dx, dz] / 255f;
                                var otherSplatFloatWriteVal = (otherSplatFloatValue * (1 - (delta / 255f)));
                                var write = (byte)Mathf.Clamp(Mathf.RoundToInt(otherSplatFloatWriteVal * 255), 0, 255);
                                baseData[currentPrototype][dx, dz] = write;
                            }
                            //DebugHelper.DrawPoint(worldPos, 1, Color.red, 10);
                            baseLayerSplat[dx, dz]        = newVal;
                            layer.Stencil[coordX, coordZ] = MiscUtilities.CompressStencil(stencilKey, 1);
                            thisPatchStencil[dx, dz]      = 1;
                        }
                        else
                        {
                            thisPatchStencil[dx, dz] = 0;
                        }
                    }
                }
            }

            foreach (var existingSplatPrototype in baseData)
            {
                var splat = existingSplatPrototype.Key;
                var data  = existingSplatPrototype.Value;
                layer.SetSplatmap(splat, matrixMin.x, matrixMin.z, data, wrapper.Terrain.terrainData.alphamapResolution, thisPatchStencil);
            }
        }
예제 #14
0
        public static void StencilEraseArray(
            ref Serializable2DByteArray baseData,
            Serializable2DFloatArray stencil,
            Common.Coord min, Common.Coord max, Common.Coord size,
            bool invert, bool absolute)
        {
            if (baseData == null || stencil == null)
            {
                return;
            }

            var width  = baseData.Width;
            var height = baseData.Height;

            if (TerrainWrapper.ComputeShaders && ShouldCompute(baseData))
            {
                var blendShader  = ComputeShaderPool.GetShader("MadMaps/WorldStamp/ComputeShaders/StencilIntArray");
                int kernelHandle = blendShader.FindKernel("StencilInts");

                var dataAsInt = baseData.Data.ConvertToIntArray();

                //var baseBuffer = new ComputeBuffer(baseData.Width * baseData.Height, sizeof(float));
                var baseBuffer = ComputeShaderPool.GetBuffer(baseData.Width * baseData.Height, sizeof(float));
                baseBuffer.SetData(dataAsInt);
                blendShader.SetBuffer(kernelHandle, "_Base", baseBuffer);
                blendShader.SetVector("_BaseSize", new Vector4(baseData.Width, baseData.Height));
                blendShader.SetVector("_MinMax", new Vector4(min.x, min.z, max.x, max.z));
                blendShader.SetVector("_TotalSize", new Vector4(size.x, size.z));

                //ComputeBuffer stencilBuffer= new ComputeBuffer(stencil.Width * stencil.Height, sizeof(float));
                var stencilBuffer = ComputeShaderPool.GetBuffer(stencil.Width * stencil.Height, sizeof(float));
                stencilBuffer.SetData(stencil.Data);
                blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer);
                blendShader.SetVector("_StencilSize", new Vector4(stencil.Width, stencil.Height));
                blendShader.SetBool("_Invert", invert);
                blendShader.SetBool("_Absolute", absolute);

                blendShader.Dispatch(kernelHandle, baseData.Width, baseData.Height, 1);

                baseBuffer.GetData(dataAsInt);

                for (int i = 0; i < dataAsInt.Length; i++)
                {
                    var val = dataAsInt[i];
                    baseData.Data[i] = (byte)Mathf.Clamp(val, 0, 255);
                }

                /*baseBuffer.Release();
                 * baseBuffer.Dispose();
                 * stencilBuffer.Release();
                 * stencilBuffer.Dispose();
                 * Resources.UnloadAsset(blendShader);*/

                ComputeShaderPool.ReturnBuffer(baseBuffer);
                ComputeShaderPool.ReturnBuffer(stencilBuffer);
                UseCount++;
            }
            else
            {
                for (var u = 0; u < width; ++u)
                {
                    var uF = (u + min.x) / (float)size.x;
                    for (var v = 0; v < height; ++v)
                    {
                        var vF = (v + min.z) / (float)size.z;

                        float value;
                        stencil.StencilBilinearSample(new Vector2(uF, vF), out value);
                        var existingValue = baseData[u, v];
                        var newValue      = existingValue;
                        if (absolute)
                        {
                            newValue = (byte)(value > 0 ? existingValue : 0);
                        }
                        else
                        {
                            newValue = (byte)Mathf.Clamp(existingValue * (1 - value), 0, 255);
                            if (invert)
                            {
                                newValue = (byte)Mathf.Clamp(existingValue * value, 0, 255);
                            }
                        }
                        baseData[u, v] = newValue;
                    }
                }
            }
            GC.Collect(3, GCCollectionMode.Forced);
        }
예제 #15
0
        public static void BlendArray(ref Serializable2DByteArray baseData,
                                      Serializable2DByteArray blendingData,
                                      Serializable2DFloatArray stencil,
                                      MMTerrainLayer.EMMTerrainLayerBlendMode blendMode,
                                      Common.Coord offset, Common.Coord size)
        {
            if (blendingData == null)
            {
                return;
            }
            if (baseData == null)
            {
                baseData = blendingData;
                return;
            }

            var width  = baseData.Width;
            var height = baseData.Height;

            if (TerrainWrapper.ComputeShaders && ShouldCompute(baseData))
            {
                var blendShader  = ComputeShaderPool.GetShader("MadMaps/WorldStamp/ComputeShaders/BlendIntArray");
                int kernelHandle = blendShader.FindKernel("BlendInts");

                var baseAsInt  = baseData.Data.ConvertToIntArray(); // TODO hmmmmm
                var blendAsInt = blendingData.Data.ConvertToIntArray();

                //var baseBuffer = new ComputeBuffer(baseData.Width * baseData.Height, sizeof(float));
                var baseBuffer = ComputeShaderPool.GetBuffer(baseData.Width * baseData.Height, sizeof(float));
                baseBuffer.SetData(baseAsInt);
                blendShader.SetBuffer(kernelHandle, "_Base", baseBuffer);
                blendShader.SetVector("_BaseSize", new Vector4(baseData.Width, baseData.Height));

                //var blendBuffer = new ComputeBuffer(blendingData.Width * blendingData.Height, sizeof(float));
                var blendBuffer = ComputeShaderPool.GetBuffer(blendingData.Width * blendingData.Height, sizeof(float));
                blendBuffer.SetData(blendAsInt);
                blendShader.SetBuffer(kernelHandle, "_Blend", blendBuffer);
                blendShader.SetVector("_BlendSize", new Vector4(blendingData.Width, blendingData.Height));

                ComputeBuffer stencilBuffer = null;
                if (stencil != null && stencil.Width > 0 && stencil.Height > 0)
                {
                    //stencilBuffer = new ComputeBuffer(stencil.Width * stencil.Height, sizeof(float));
                    stencilBuffer = ComputeShaderPool.GetBuffer(stencil.Width * stencil.Height, sizeof(float));
                    stencilBuffer.SetData(stencil.Data);
                    blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer);
                    blendShader.SetVector("_StencilSize", new Vector4(stencil.Width, stencil.Height));
                }
                else
                {
                    stencilBuffer = ComputeShaderPool.GetBuffer(1, sizeof(float));
                    blendShader.SetBuffer(kernelHandle, "_Stencil", stencilBuffer);
                    blendShader.SetVector("_StencilSize", new Vector4(0, 0));
                }

                blendShader.SetInt("_BlendMode", (int)blendMode);
                blendShader.SetVector("_MinMax", new Vector4(offset.x, offset.z, 0, 0));

                blendShader.Dispatch(kernelHandle, baseData.Width, baseData.Height, 1);

                baseBuffer.GetData(baseAsInt);
                for (int i = 0; i < baseAsInt.Length; i++)
                {
                    baseData.Data[i] = (byte)baseAsInt[i];
                }

                /*baseBuffer.Release();
                 * baseBuffer.Dispose();
                 * blendBuffer.Release();
                 * blendBuffer.Dispose();*/
                ComputeShaderPool.ReturnBuffer(baseBuffer);
                ComputeShaderPool.ReturnBuffer(blendBuffer);
                if (stencilBuffer != null)
                {
                    ComputeShaderPool.ReturnBuffer(stencilBuffer);
                    //stencilBuffer.Release();
                    //stencilBuffer.Dispose();
                }
                //Resources.UnloadAsset(blendShader);
                UseCount++;
            }
            else
            {
                for (int dx = 0; dx < width; dx++)
                {
                    for (int dz = 0; dz < height; dz++)
                    {
                        var blendingVal = blendingData[dx, dz];

                        switch (blendMode)
                        {
                        case MMTerrainLayer.EMMTerrainLayerBlendMode.Set:
                            baseData[dx, dz] = blendingVal;
                            break;

                        case MMTerrainLayer.EMMTerrainLayerBlendMode.Additive:
                            baseData[dx, dz] += blendingVal;
                            break;

                        case MMTerrainLayer.EMMTerrainLayerBlendMode.Stencil:
                            var   xF = (offset.x + dx) / (float)size.x;
                            var   zF = (offset.z + dz) / (float)size.z;
                            float strength;
                            stencil.StencilBilinearSample(new Vector2(xF, zF), out strength);
                            if (strength > 0)
                            {
                                var existingValue = baseData[dx, dz];
                                var newValue      = (byte)Mathf.RoundToInt(Mathf.Clamp(Mathf.Lerp(existingValue, blendingVal, strength), 0, 255));
                                baseData[dx, dz] = newValue;
                            }
                            break;
                        }
                    }
                }
            }
            GC.Collect(3, GCCollectionMode.Forced);
        }