private void ResampleGrassPatches()
        {
            List <GGrassInstance> grassInstances = new List <GGrassInstance>();

            for (int i = 0; i < grassPatches.Length; ++i)
            {
                grassInstances.AddRange(grassPatches[i].Instances);
            }

            grassPatches = new GGrassPatch[PatchGridSize * PatchGridSize];
            for (int x = 0; x < PatchGridSize; ++x)
            {
                for (int z = 0; z < patchGridSize; ++z)
                {
                    int         index = GUtilities.To1DIndex(x, z, PatchGridSize);
                    GGrassPatch patch = new GGrassPatch(this, x, z);
                    grassPatches[index] = patch;
                }
            }

            AddGrassInstances(grassInstances);
        }
Beispiel #2
0
        private static void RenderGrass(GStylizedTerrain t, Camera cam)
        {
            if (t.TerrainData.Foliage.Grasses == null ||
                t.TerrainData.Foliage.Grasses.Prototypes.Count == 0)
            {
                return;
            }
            List <GGrassPrototype> prototypes = t.TerrainData.Foliage.Grasses.Prototypes;

            GGrassPatch[] patches = t.TerrainData.Foliage.GrassPatches;
            if (patches == null)
            {
                return;
            }

            float   grassDistance = t.TerrainData.Rendering.GrassDistance;
            Vector3 dimension     = new Vector3(
                t.TerrainData.Geometry.Width,
                t.TerrainData.Geometry.Height,
                t.TerrainData.Geometry.Length);
            float   patchWorldRadius = dimension.x * 0.5f / t.TerrainData.Foliage.PatchGridSize;
            Vector3 boundLocalPos    = Vector3.zero;
            Vector3 boundWorldPos    = Vector3.zero;

            int FLAG_CULLED  = 0;
            int FLAG_DIRTY   = 1;
            int FLAG_BATCHED = 2;

            int[]  flags     = new int[patches.Length];
            Rect[] dirtyRect = t.TerrainData.Foliage.GetGrassDirtyRegions();
            for (int i = 0; i < patches.Length; ++i)
            {
                Rect uvRect = patches[i].GetUvRange();
                boundLocalPos.Set(
                    uvRect.center.x * dimension.x,
                    0,
                    uvRect.center.y * dimension.z);
                boundWorldPos   = t.transform.TransformPoint(boundLocalPos);
                boundWorldPos.y = cam.transform.position.y;
                if (Vector3.Distance(boundWorldPos, cam.transform.position) - patchWorldRadius > grassDistance)
                {
                    flags[i] = FLAG_CULLED;
                    continue;
                }

                for (int r = 0; r < dirtyRect.Length; ++r)
                {
                    if (dirtyRect[r].Overlaps(uvRect))
                    {
                        flags[i] = FLAG_DIRTY;
                        break;
                    }
                }

                if (flags[i] == FLAG_DIRTY)
                {
                    continue;
                }

                flags[i] = FLAG_BATCHED;
            }

            Vector3 meshLocalPos = Vector3.zero;
            Vector3 meshWorldPos = Vector3.zero;

            grassMaterialPropertyBlock.Clear();
            if (t.TerrainData.Foliage.EnableInteractiveGrass)
            {
                grassMaterialPropertyBlock.SetTexture(VECTOR_FIELD_PROPERTY, t.GetGrassVectorFieldRenderTexture());
                grassMaterialPropertyBlock.SetMatrix(WORLD_TO_NORMALIZED_PROPERTY, t.GetWorldToNormalizedMatrix());
            }

            grassMaterialPropertyBlock.SetTexture(NOISETEX_PROPERTY, GGriffinSettings.Instance.DefaultNoiseTexture);
            IEnumerator <GWindZone> windZone = GWindZone.ActiveWindZones.GetEnumerator();

            if (windZone.MoveNext())
            {
                GWindZone w = windZone.Current;
                grassMaterialPropertyBlock.SetVector(WIND_PROPERTY, w.GetWindParams());
            }

            //draw batched
            //Material grassMat = GCommon.CurrentRenderPipeline == GRenderPipelineType.Lightweight ?
            //    GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassMaterialLW :
            //    GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassMaterial;
            Material grassMat = null;

            if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Builtin)
            {
                grassMat = t.TerrainData.Foliage.EnableInteractiveGrass ?
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassInteractiveMaterial :
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassMaterial;
                if (grassMat == null)
                {
                    Debug.Log("Grass material missing. Try re-installing the Polaris V2 package.");
                }
            }
            else if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Lightweight)
            {
                grassMat = t.TerrainData.Foliage.EnableInteractiveGrass ?
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassInteractiveMaterialLWRP :
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassMaterialLWRP;
                if (grassMat == null)
                {
                    Debug.Log("Grass material missing. Try installing the 'Lightweight Render Pipeline Support' extension from the Extension Window (Window>Griffin>Tools>Extension)");
                }
            }
            else if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Universal)
            {
                grassMat = t.TerrainData.Foliage.EnableInteractiveGrass ?
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassInteractiveMaterialURP :
                           GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassMaterialURP;
                if (grassMat == null)
                {
                    Debug.Log("Grass material missing. Try installing the 'Universal Render Pipeline Support' extension from the Extension Window (Window>Griffin>Tools>Extension)");
                }
            }

            if (grassMat == null)
            {
                return;
            }

            for (int i = 0; i < patches.Length; ++i)
            {
                if (flags[i] != FLAG_BATCHED)
                {
                    continue;
                }
                for (int p = 0; p < prototypes.Count; ++p)
                {
                    grassMaterialPropertyBlock.SetColor(COLOR_PROPERTY, prototypes[p].Color);
                    grassMaterialPropertyBlock.SetFloat(BEND_FACTOR_PROPERTY, prototypes[p].BendFactor);
                    if (prototypes[p].Shape != GGrassShape.DetailObject && prototypes[p].Texture != null)
                    {
                        grassMaterialPropertyBlock.SetTexture(MAINTEX_PROPERTY, prototypes[p].Texture);
                    }
                    Mesh mesh = patches[i].GetMesh(p);
                    if (mesh != null)
                    {
                        meshLocalPos = mesh.bounds.center;
                        meshWorldPos = t.transform.TransformPoint(meshLocalPos);
                        if (Vector3.Distance(meshWorldPos, cam.transform.position) - patchWorldRadius > grassDistance)
                        {
                            continue;
                        }

                        Graphics.DrawMesh(
                            mesh,
                            Matrix4x4.TRS(t.transform.position, Quaternion.identity, Vector3.one),
                            prototypes[p].Shape == GGrassShape.DetailObject ? prototypes[p].DetailMaterial : grassMat,
                            prototypes[p].Layer,
                            cam,
                            0,
                            prototypes[p].Shape == GGrassShape.DetailObject ? null : grassMaterialPropertyBlock,
                            prototypes[p].Shape == GGrassShape.DetailObject ? prototypes[p].ShadowCastingMode : ShadowCastingMode.On,
                            prototypes[p].Shape == GGrassShape.DetailObject ? prototypes[p].ReceiveShadow : true,
                            null,
                            LightProbeUsage.BlendProbes,
                            null);
                    }
                }
            }

            if (GCommon.CurrentRenderPipeline == GRenderPipelineType.Builtin)
            {
                return;
            }

            Vector3 localPos = Vector3.zero;
            Vector3 worldPos = Vector3.zero;
            Vector3 scale    = Vector3.zero;

            Material previewMat = GGriffinSettings.Instance.TerrainDataDefault.Foliage.GrassPreviewMaterial;

            for (int pIndex = 0; pIndex < prototypes.Count; ++pIndex)
            {
                GGrassPrototype proto = prototypes[pIndex];
                //grassMaterialPropertyBlock.Clear();
                //grassMaterialPropertyBlock.SetTexture(MAINTEX_PROPERTY, proto.Texture);

                for (int i = 0; i < patches.Length; ++i)
                {
                    if (flags[i] != FLAG_DIRTY)
                    {
                        continue;
                    }
                    GGrassPatch patch         = patches[i];
                    int         instanceCount = patch.Instances.Count;
                    for (int j = 0; j < instanceCount; ++j)
                    {
                        GGrassInstance grass = patch.Instances[j];
                        if (grass.PrototypeIndex != pIndex)
                        {
                            continue;
                        }

                        localPos.Set(
                            dimension.x * grass.Position.x,
                            dimension.y * grass.Position.y,
                            dimension.z * grass.Position.z);
                        worldPos = t.transform.TransformPoint(localPos);
                        scale.Set(
                            prototypes[grass.PrototypeIndex].Size.x * grass.Scale.x,
                            prototypes[grass.PrototypeIndex].Size.y * grass.Scale.y,
                            prototypes[grass.PrototypeIndex].Size.z * grass.Scale.z);

                        Mesh mesh = prototypes[grass.PrototypeIndex].GetBaseMesh();
                        Graphics.DrawMesh(
                            mesh,
                            Matrix4x4.TRS(worldPos, grass.Rotation, scale),
                            previewMat,
                            prototypes[grass.PrototypeIndex].Layer,
                            cam,
                            0,
                            null,     //grassMaterialPropertyBlock
                            ShadowCastingMode.On,
                            true,
                            null,
                            LightProbeUsage.BlendProbes,
                            null);
                    }
                }
            }
        }