using System.Collections.Generic; namespace UnityEngine.Rendering.HighDefinition { /// /// Controls the type of the procedural foam generator. /// [GenerateHLSL(PackingRules.Exact)] public enum WaterFoamGeneratorType { /// /// Disk foam generator. /// Disk = 0, /// /// Square foam generator. /// Rectangle = 1, /// /// Texture foam generator. /// Texture = 2, /// /// Material foam generator. /// Material = 3, } /// /// Procedural water foam generator component. /// [DisallowMultipleComponent] [ExecuteInEditMode] [HDRPHelpURL("WaterSystem-foam")] public partial class WaterFoamGenerator : MonoBehaviour { /// /// Specifies the type of the generator. This parameter defines which parameters will be used to render it. /// public WaterFoamGeneratorType type = WaterFoamGeneratorType.Disk; /// /// Specifies the size of the generator in meters. /// public Vector2 regionSize = new Vector2(20.0f, 20.0f); /// /// Specifies the texture used for the foam. /// public Texture texture = null; #region Material Generator /// /// Specifies the resolution when written inside the atlas. /// public Vector2Int resolution = new Vector2Int(256, 256); /// /// Frequency of update of the Material in the atlas. /// [Tooltip("Frequency of update of the Material in the atlas.")] public CustomRenderTextureUpdateMode updateMode = CustomRenderTextureUpdateMode.OnLoad; /// /// Specifies the material used for the foam. /// [Tooltip("Specifies the material used for the generator.")] public Material material = null; internal bool shouldUpdate = false; /// /// Triggers a render of the material in the deformer atlas. /// public void RequestUpdate() { shouldUpdate = true; } internal MaterialPropertyBlock mpb; /// /// Override per-generator material parameters. This is more memory efficient than having one complete distinct Material per generator but is recommended when only a few properties of a Material overriden. /// /// Property block with values you want to override. public void SetPropertyBlock(MaterialPropertyBlock properties) { mpb = properties; } /// /// Returns true if the Foam Generator has a material property block attached via SetPropertyBlock. /// /// Returns true if the Foam Generator has a material property block attached via SetPropertyBlock. public bool HasPropertyBlock() { return mpb != null; } internal bool IsValidMaterial() { #if UNITY_EDITOR return material != null && material.GetTag("ShaderGraphTargetId", false, null) == "WaterDecalSubTarget"; #else return true; #endif } internal int GetMaterialAtlasingId() { // If material has a property block, we can't reuse the atlas slot if (HasPropertyBlock()) return GetInstanceID(); else return material.GetInstanceID(); } #endregion /// /// Specifies the dimmer for the surface foam. /// [Range(0.0f, 1.0f)] public float surfaceFoamDimmer = 1.0f; /// /// Specifies a dimmer for the deep foam. /// [Range(0.0f, 1.0f)] public float deepFoamDimmer = 1.0f; /// /// The scaling mode to apply to this Foam Generator. /// [Tooltip("Specify the scaling mode")] public DecalScaleMode scaleMode = DecalScaleMode.ScaleInvariant; internal Vector2 scale { get { Vector3 scale = scaleMode == DecalScaleMode.InheritFromHierarchy ? transform.lossyScale : Vector3.one; return new Vector2(scale.x, scale.z); } } #region Instance Management // Management to avoid memory allocations at fetch time internal static HashSet instances = new HashSet(); internal static WaterFoamGenerator[] instancesAsArray = null; internal static int instanceCount = 0; internal static void RegisterInstance(WaterFoamGenerator foamGenerator) { instances.Add(foamGenerator); instanceCount = instances.Count; if (instanceCount > 0) { instancesAsArray = new WaterFoamGenerator[instanceCount]; instances.CopyTo(instancesAsArray); } else { instancesAsArray = null; } } internal static void UnregisterInstance(WaterFoamGenerator foamGenerator) { instances.Remove(foamGenerator); instanceCount = instances.Count; if (instanceCount > 0) { instancesAsArray = new WaterFoamGenerator[instanceCount]; instances.CopyTo(instancesAsArray); } else { instancesAsArray = null; } } #endregion #region MonoBehavior Methods private void Start() { // Add this water surface to the internal surface management RegisterInstance(this); } private void Awake() { k_Migration.Migrate(this); // Add this water surface to the internal surface management RegisterInstance(this); } private void OnEnable() { // Add this water surface to the internal surface management RegisterInstance(this); if (updateMode == CustomRenderTextureUpdateMode.OnLoad) shouldUpdate = true; } private void OnDisable() { // Remove this water surface from the internal surface management UnregisterInstance(this); } void OnDestroy() { // Remove this water surface from the internal surface management UnregisterInstance(this); } #endregion } }