public void Configure(GStylizedTerrain terrain, int prototypeIndex, MaterialPropertyBlock propertyBlock) { GGrassPrototype proto = terrain.TerrainData.Foliage.Grasses.Prototypes[prototypeIndex]; propertyBlock.SetTexture(NOISE_TEX, GRuntimeSettings.Instance.foliageRendering.windNoiseTexture); IEnumerator <GWindZone> windZone = GWindZone.ActiveWindZones.GetEnumerator(); if (windZone.MoveNext()) { GWindZone w = windZone.Current; propertyBlock.SetVector(WIND, w.GetWindParams()); } propertyBlock.SetColor(COLOR, proto.Color); if (proto.Shape != GGrassShape.DetailObject && proto.Texture != null) { propertyBlock.SetTexture(MAIN_TEX, proto.Texture); } propertyBlock.SetFloat(BEND_FACTOR, proto.BendFactor); if (terrain.TerrainData.Foliage.EnableInteractiveGrass) { propertyBlock.SetTexture(VECTOR_FIELD, terrain.GetGrassVectorFieldRenderTexture()); propertyBlock.SetMatrix(WORLD_TO_NORMALIZED, terrain.GetWorldToNormalizedMatrix()); } float fadeMaxDistance = terrain.TerrainData.Rendering.GrassDistance; float fadeMinDistance = Mathf.Clamp(terrain.TerrainData.Rendering.GrassFadeStart, 0f, 0.99f) * fadeMaxDistance; propertyBlock.SetFloat(FADE_MIN_DISTANCE, fadeMinDistance); propertyBlock.SetFloat(FADE_MAX_DISTANCE, fadeMaxDistance); }
private void DrawOnTerrain(GStylizedTerrain t) { Vector3[] worldCorners = GCommon.GetBrushQuadCorners(transform.position, Radius, 0); Vector2[] uvCorners = new Vector2[worldCorners.Length]; for (int i = 0; i < uvCorners.Length; ++i) { uvCorners[i] = t.WorldPointToUV(worldCorners[i]); } Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners); if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1))) { return; } RenderTexture rt = t.GetGrassVectorFieldRenderTexture(); Material mat = GInternalMaterials.InteractiveGrassVectorFieldMaterial; mat.SetFloat("_Opacity", t.TerrainData.Foliage.BendSensitive); int pass = 0; GCommon.DrawQuad(rt, uvCorners, mat, pass); }
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); } } } }