public static void Render(
            RenderTexture rt,
            GConditionalStampLayer layer,
            GStylizedTerrain terrain,
            Matrix4x4 stamperTransform,
            Texture mask,
            Texture falloffTexture,
            Vector2[] uvPoints,
            bool useTerrainMask)
        {
            GCommon.ClearRT(rt);
            if (layer.Ignore)
            {
                return;
            }

            Material brushMat = GInternalMaterials.TextureStamperBrushMaterial;

            int resolution = Mathf.Max(rt.width, rt.height);
            //no need to release these maps
            RenderTexture heightMap = terrain.GetHeightMap(resolution);
            RenderTexture normalMap =
                layer.NormalMapMode == GNormalMapMode.Sharp ? terrain.GetSharpNormalMap(resolution) :
                layer.NormalMapMode == GNormalMapMode.Interpolated ? terrain.GetInterpolatedNormalMap(resolution) :
                layer.NormalMapMode == GNormalMapMode.PerPixel ? terrain.GetPerPixelNormalMap(resolution) : null;

            brushMat.SetTexture("_HeightMap", heightMap);

            Vector3 position = stamperTransform.MultiplyPoint(Vector3.zero);
            Vector3 scale    = stamperTransform.lossyScale;

            float stamperMinHeight = terrain.WorldPointToNormalized(position).y;
            float stamperMaxHeight = terrain.WorldPointToNormalized(position + Vector3.up * scale.y).y;

            brushMat.SetFloat("_StamperMinHeight", stamperMinHeight);
            brushMat.SetFloat("_StamperMaxHeight", stamperMaxHeight);

            Vector3 terrainSize = new Vector3(
                terrain.TerrainData.Geometry.Width,
                terrain.TerrainData.Geometry.Height,
                terrain.TerrainData.Geometry.Length);

            brushMat.SetTexture("_Mask", mask);
            brushMat.SetTexture("_Falloff", falloffTexture);
            brushMat.SetFloat("_MinHeight", GUtilities.InverseLerpUnclamped(0, terrainSize.y, layer.MinHeight));
            brushMat.SetFloat("_MaxHeight", GUtilities.InverseLerpUnclamped(0, terrainSize.y, layer.MaxHeight));
            brushMat.SetTexture("_HeightTransition", layer.heightTransitionTexture);
            brushMat.SetFloat("_MinSlope", layer.MinSlope * Mathf.Deg2Rad);
            brushMat.SetFloat("_MaxSlope", layer.MaxSlope * Mathf.Deg2Rad);
            brushMat.SetTexture("_SlopeTransition", layer.slopeTransitionTexture);
            brushMat.SetVector("_NoiseOrigin", layer.NoiseOrigin);
            brushMat.SetFloat("_NoiseFrequency", layer.NoiseFrequency);
            brushMat.SetInt("_NoiseOctaves", layer.NoiseOctaves);
            brushMat.SetFloat("_NoiseLacunarity", layer.NoiseLacunarity);
            brushMat.SetFloat("_NoisePersistence", layer.NoisePersistence);
            brushMat.SetTexture("_NoiseRemap", layer.noiseRemapTexture);
            brushMat.SetTexture("_NormalMap", normalMap);
            if (useTerrainMask)
            {
                brushMat.SetTexture("_TerrainMask", terrain.TerrainData.Mask.MaskMap);
            }
            else
            {
                brushMat.SetTexture("_TerrainMask", Texture2D.blackTexture);
            }

            GCommon.SetMaterialKeywordActive(brushMat, BLEND_HEIGHT_KW, layer.BlendHeight);
            GCommon.SetMaterialKeywordActive(brushMat, BLEND_SLOPE_KW, layer.BlendSlope);
            GCommon.SetMaterialKeywordActive(brushMat, BLEND_NOISE_KW, layer.BlendNoise);
            DrawOnBrushTexture(rt, uvPoints, brushMat, 0);
        }
Example #2
0
        private void SpawnObjectOnTerrain(GStylizedTerrain t, Color[] maskData, int layerIndex)
        {
            GObjectStampLayer layer       = Layers[layerIndex];
            Vector3           centerPos   = Vector3.zero;
            Vector3           samplePos   = Vector3.zero;
            Vector2           uv          = Vector2.zero;
            float             maskValue   = 0;
            Vector3           terrainSize = new Vector3(
                t.TerrainData.Geometry.Width,
                t.TerrainData.Geometry.Height,
                t.TerrainData.Geometry.Length);
            Vector3 scale = new Vector3(
                GUtilities.InverseLerpUnclamped(0, terrainSize.x, Scale.x),
                1,
                GUtilities.InverseLerpUnclamped(0, terrainSize.z, Scale.z));
            Matrix4x4 matrix = Matrix4x4.TRS(
                t.WorldPointToNormalized(Position),
                Rotation,
                scale);

            int        index         = -1;
            int        instanceCount = 0;
            int        attempt       = 0;
            int        maxAttempt    = layer.InstanceCount * 100;
            RaycastHit hit;

#if UNITY_EDITOR
            string title           = "Stamping on " + t.name;
            string info            = string.Format("Layer: {0}", !string.IsNullOrEmpty(layer.Name) ? layer.Name : layerIndex.ToString());
            int    currentPercent  = 0;
            int    attemptPercent  = 0;
            int    instancePercent = 0;
            GCommonGUI.CancelableProgressBar(title, info, 0);
#endif

            while (instanceCount < layer.InstanceCount && attempt <= maxAttempt)
            {
                attempt += 1;

#if UNITY_EDITOR
                attemptPercent  = (int)(attempt * 100.0f / maxAttempt);
                instancePercent = (int)(instanceCount * 100.0f / layer.InstanceCount);
                if (currentPercent != Mathf.Max(attemptPercent, instancePercent))
                {
                    currentPercent = Mathf.Max(attemptPercent, instancePercent);
                    GCommonGUI.CancelableProgressBar(title, string.Format("{0} ... {1}%", info, currentPercent), currentPercent / 100.0f);
                }
#endif

                index = layer.PrototypeIndices[Random.Range(0, layer.PrototypeIndices.Count)];
                if (index < 0 || index >= layer.Prototypes.Count)
                {
                    continue;
                }
                GameObject g = layer.Prototypes[index];
                if (g == null)
                {
                    continue;
                }

                centerPos.Set(Random.value - 0.5f, 0, Random.value - 0.5f);
                samplePos = matrix.MultiplyPoint(centerPos);
                if (samplePos.x < 0 || samplePos.x > 1 ||
                    samplePos.z < 0 || samplePos.z > 1)
                {
                    continue;
                }
                uv.Set(samplePos.x, samplePos.z);
                maskValue = GUtilities.GetColorBilinear(maskData, MaskResolution, MaskResolution, uv).r;
                if (Random.value > maskValue)
                {
                    continue;
                }

                if (t.Raycast(samplePos, out hit))
                {
                    GameObject instance = GSpawner.Spawn(t, g, hit.point);
                    instance.transform.rotation   = Quaternion.Euler(0, Random.Range(layer.MinRotation, layer.MaxRotation), 0);
                    instance.transform.localScale = Vector3.Lerp(layer.MinScale, layer.MaxScale, Random.value);
                    if (layer.AlignToSurface)
                    {
                        instance.transform.up = hit.normal;
                    }

                    instanceCount += 1;
                }
            }
#if UNITY_EDITOR
            GCommonGUI.ClearProgressBar();
#endif
        }
Example #3
0
        private void DrawOnTexture(RenderTexture rt, Material mat, int pass, List <Vector4> worldPoints, GStylizedTerrain t)
        {
            Vector4        worldOffset      = new Vector4(0, HeightOffset, 0, 0);
            List <Vector4> normalizedPoints = new List <Vector4>();

            for (int i = 0; i < worldPoints.Count; ++i)
            {
                Vector3 v = t.WorldPointToNormalized(worldPoints[i] + worldOffset);
                normalizedPoints.Add(new Vector4(Mathf.Clamp01(v.x), Mathf.Clamp01(v.y), Mathf.Clamp01(v.z), worldPoints[i].w));
            }

            RenderTexture.active = rt;
            GL.PushMatrix();
            GL.LoadOrtho();
            GL.Begin(GL.TRIANGLES);
            int trisCount = worldPoints.Count / 3;

            GCommon.SetMaterialKeywordActive(mat, "FALLOFF", true);
            mat.SetPass(pass);
            for (int i = 0; i < trisCount; ++i)
            {
                Vector4 v0 = worldPoints[i * 3 + 0];
                Vector4 v1 = worldPoints[i * 3 + 1];
                Vector4 v2 = worldPoints[i * 3 + 2];

                if (v0.w == 0 || v1.w == 0 || v2.w == 0)
                {
                    Vector4 vn0 = normalizedPoints[i * 3 + 0];
                    Vector4 vn1 = normalizedPoints[i * 3 + 1];
                    Vector4 vn2 = normalizedPoints[i * 3 + 2];

                    GL.MultiTexCoord3(0, vn0.x, vn0.z, vn0.y);
                    GL.MultiTexCoord3(1, v0.x, v0.z, v0.y);
                    GL.Color(new Color(vn0.w, vn0.w, vn0.w, vn0.w));
                    GL.Vertex3(vn0.x, vn0.z, vn0.y);

                    GL.MultiTexCoord3(0, vn1.x, vn1.z, vn1.y);
                    GL.MultiTexCoord3(1, v1.x, v1.z, v1.y);
                    GL.Color(new Color(vn1.w, vn1.w, vn1.w, vn1.w));
                    GL.Vertex3(vn1.x, vn1.z, vn1.y);

                    GL.MultiTexCoord3(0, vn2.x, vn2.z, vn2.y);
                    GL.MultiTexCoord3(1, v2.x, v2.z, v2.y);
                    GL.Color(new Color(vn2.w, vn2.w, vn2.w, vn2.w));
                    GL.Vertex3(vn2.x, vn2.z, vn2.y);
                }
            }
            GL.End();

            GL.Begin(GL.TRIANGLES);
            GCommon.SetMaterialKeywordActive(mat, "FALLOFF", false);
            mat.SetPass(pass);
            for (int i = 0; i < trisCount; ++i)
            {
                Vector4 v0 = worldPoints[i * 3 + 0];
                Vector4 v1 = worldPoints[i * 3 + 1];
                Vector4 v2 = worldPoints[i * 3 + 2];

                if (v0.w != 0 && v1.w != 0 && v2.w != 0)
                {
                    Vector4 vn0 = normalizedPoints[i * 3 + 0];
                    Vector4 vn1 = normalizedPoints[i * 3 + 1];
                    Vector4 vn2 = normalizedPoints[i * 3 + 2];

                    GL.MultiTexCoord3(0, vn0.x, vn0.z, vn0.y);
                    GL.MultiTexCoord3(1, v0.x, v0.z, v0.y);
                    GL.Color(new Color(vn0.w, vn0.w, vn0.w, vn0.w));
                    GL.Vertex3(vn0.x, vn0.z, vn0.y);

                    GL.MultiTexCoord3(0, vn1.x, vn1.z, vn1.y);
                    GL.MultiTexCoord3(1, v1.x, v1.z, v1.y);
                    GL.Color(new Color(vn1.w, vn1.w, vn1.w, vn1.w));
                    GL.Vertex3(vn1.x, vn1.z, vn1.y);

                    GL.MultiTexCoord3(0, vn2.x, vn2.z, vn2.y);
                    GL.MultiTexCoord3(1, v2.x, v2.z, v2.y);
                    GL.Color(new Color(vn2.w, vn2.w, vn2.w, vn2.w));
                    GL.Vertex3(vn2.x, vn2.z, vn2.y);
                }
            }
            GL.End();
            GL.PopMatrix();
            RenderTexture.active = null;
        }
        private void HandleSpawnGrass(GStylizedTerrain terrain, GFoliagePainterArgs args)
        {
            int        grassIndex   = -1;
            Vector3    randomPos    = Vector3.zero;
            Vector3    rayOrigin    = Vector3.zero;
            Vector3    rayDirection = Vector3.down;
            float      sqrtTwo      = Mathf.Sqrt(2);
            Ray        ray          = new Ray();
            RaycastHit samplePoint;
            Vector3    bary0      = Vector3.zero;
            Vector3    bary1      = Vector3.zero;
            Vector2    maskUv     = Vector2.zero;
            Color      maskColor  = Color.white;
            Texture2D  clonedMask = null;

            if (args.Mask != null)
            {
                clonedMask = GCommon.CloneAndResizeTexture(args.Mask, 256, 256);
            }

            int sampleCount = Mathf.Clamp(args.Density * args.Density / 10, 1, 1000);
            List <GGrassInstance> newInstances = new List <GGrassInstance>();

            for (int i = 0; i < sampleCount; ++i)
            {
                grassIndex = args.GrassIndices[Random.Range(0, args.GrassIndices.Count)];
                randomPos  = args.HitPoint + Random.insideUnitSphere * args.Radius * sqrtTwo;
                rayOrigin.Set(
                    randomPos.x,
                    10000,
                    randomPos.z);
                ray.origin    = rayOrigin;
                ray.direction = rayDirection;
                if (terrain.Raycast(ray, out samplePoint, float.MaxValue))
                {
                    GUtilities.CalculateBarycentricCoord(
                        new Vector2(samplePoint.point.x, samplePoint.point.z),
                        new Vector2(args.WorldPointCorners[0].x, args.WorldPointCorners[0].z),
                        new Vector2(args.WorldPointCorners[1].x, args.WorldPointCorners[1].z),
                        new Vector2(args.WorldPointCorners[2].x, args.WorldPointCorners[2].z),
                        ref bary0);
                    GUtilities.CalculateBarycentricCoord(
                        new Vector2(samplePoint.point.x, samplePoint.point.z),
                        new Vector2(args.WorldPointCorners[0].x, args.WorldPointCorners[0].z),
                        new Vector2(args.WorldPointCorners[2].x, args.WorldPointCorners[2].z),
                        new Vector2(args.WorldPointCorners[3].x, args.WorldPointCorners[3].z),
                        ref bary1);
                    if (bary0.x >= 0 && bary0.y >= 0 && bary0.z >= 0)
                    {
                        maskUv = bary0.x * Vector2.zero + bary0.y * Vector2.up + bary0.z * Vector2.one;
                    }
                    else if (bary1.x >= 0 && bary1.y >= 0 && bary1.z >= 0)
                    {
                        maskUv = bary1.x * Vector2.zero + bary1.y * Vector2.one + bary1.z * Vector2.right;
                    }
                    else
                    {
                        continue;
                    }

                    //sample mask
                    if (clonedMask != null)
                    {
                        maskColor = clonedMask.GetPixelBilinear(maskUv.x, maskUv.y);
                        if (Random.value > maskColor.grayscale)
                        {
                            continue;
                        }
                    }

                    //apply filter
                    GSpawnFilterArgs filterArgs = GSpawnFilterArgs.Create();
                    filterArgs.Terrain         = terrain;
                    filterArgs.Position        = samplePoint.point;
                    filterArgs.SurfaceNormal   = samplePoint.normal;
                    filterArgs.SurfaceTexcoord = samplePoint.textureCoord;

                    List <Type> suitableFilter = SuitableFilterTypes;
                    if (args.Filters != null)
                    {
                        for (int fIndex = 0; fIndex < args.Filters.Length; ++fIndex)
                        {
                            if (args.Filters[fIndex] != null &&
                                args.Filters[fIndex].Ignore != true)
                            {
                                if (suitableFilter.Contains(args.Filters[fIndex].GetType()))
                                {
                                    args.Filters[fIndex].Apply(ref filterArgs);
                                }
                            }
                            if (filterArgs.ShouldExclude)
                            {
                                break;
                            }
                        }
                    }

                    //spawn
                    if (filterArgs.ShouldExclude)
                    {
                        continue;
                    }

                    GGrassInstance grass = GGrassInstance.Create(grassIndex);
                    grass.Position = terrain.WorldPointToNormalized(filterArgs.Position);
                    grass.Rotation = filterArgs.Rotation;
                    grass.Scale    = filterArgs.Scale;
                    newInstances.Add(grass);
                }
            }

            terrain.TerrainData.Foliage.AddGrassInstances(newInstances);
            if (clonedMask != null)
            {
                Object.DestroyImmediate(clonedMask);
            }
        }