Advertisement
Staggart

Vertex color baker for Stylized Water 2

Jan 3rd, 2022 (edited)
1,705
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.69 KB | None | 0 0
  1. using Unity.Mathematics;
  2. using UnityEngine;
  3. #if UNITY_EDITOR
  4. using UnityEditor;
  5. #endif
  6.  
  7. [RequireComponent(typeof(MeshFilter))]
  8. [ExecuteInEditMode]
  9. public class WaterVertexColorBaker : MonoBehaviour
  10. {
  11.     [Header("Geometry")]
  12.     public MeshFilter meshFilter;
  13.     public Mesh sourceMesh;
  14.  
  15.     [Space]
  16.    
  17.     [Header("Raycasting")]
  18.     [Tooltip("Only accept raycast hits from terrain geometry")]
  19.     public bool terrainOnly = true;
  20.     [Tooltip("Instead of raycasting precesly from the vertex's position, move the origin of the ray up this much. " +
  21.              "\n\nThis is particularly useful when a vertex sits just underneath the terrain at a shoreline, but you need it to register a hit")]
  22.     public float heightOffset = 0f;
  23.    
  24.     [Space]
  25.    
  26.     [Header("Effect information")]
  27.     [Min(0f)]
  28.     public float intersectionLength = 1f;
  29.     [Min(0f)]
  30.     public float depthExponent = 1f;
  31.     [Min(0f)]
  32.     public float waveAttenuation = 1f;
  33.  
  34.     [Space]
  35.  
  36.     [Header("Procedural surface foam painting")]
  37.     [Range(0f,1f)]
  38.     public float foamNoiseAmount;
  39.     public float foamNoiseFrequency = 0.1f;
  40.    
  41.     private void Reset()
  42.     {
  43.         meshFilter = GetComponent<MeshFilter>();
  44.         sourceMesh = meshFilter.sharedMesh;
  45.     }
  46.  
  47.     [ContextMenu("BAKE")]
  48.     public void Bake()
  49.     {
  50.         if(!meshFilter || !sourceMesh) return;
  51.        
  52.         meshFilter.sharedMesh = BakeVertexColors(transform, heightOffset, sourceMesh, intersectionLength, depthExponent, waveAttenuation, foamNoiseAmount, foamNoiseFrequency, terrainOnly);
  53.     }
  54.  
  55.     public static Mesh BakeVertexColors(Transform transform, float heightOffset, Mesh sourceMesh, float intersectionLength, float depthExponent, float waveAttenuation, float foamAmount, float foamFrequency, bool terrainOnly)
  56.     {
  57.         Vector3[] verts = sourceMesh.vertices;
  58.         Mesh newMesh = new Mesh();
  59.         newMesh.name = sourceMesh.name + " (Baked vertex colors)";
  60.        
  61.         Color[] colors = new Color[verts.Length];
  62.  
  63.         RaycastHit hit;
  64.  
  65.         float dist = 0;
  66.         bool hasHitBelow = false;
  67.         bool hasHitAbove = false;
  68.        
  69.         for (int i = 0; i < verts.Length; i++)
  70.         {
  71.             Vector3 position = transform.TransformPoint(verts[i]);
  72.             Vector3 rayOrigin = position;
  73.  
  74.             //Default value for missed hits
  75.             dist = 0;
  76.             hasHitAbove = false;
  77.             hasHitBelow = false;
  78.  
  79.             rayOrigin.y += heightOffset;
  80.            
  81.             if (Physics.Raycast(rayOrigin, Vector3.down, out hit, Mathf.Infinity, -1, QueryTriggerInteraction.Ignore))
  82.             {
  83.                 hasHitBelow = hit.point.y < position.y;
  84.                 hasHitAbove = hit.point.y >= position.y;
  85.                
  86.                 dist = hit.point.y - position.y;
  87.                
  88.                 if (terrainOnly && hit.collider.GetType() != typeof(TerrainCollider))
  89.                 {
  90.                     dist = 0;
  91.                     hasHitAbove = false;
  92.                     hasHitBelow = false;
  93.                 }
  94.             }
  95.  
  96.             float intersection = 1-Mathf.Abs(dist / intersectionLength);
  97.             float depthVal = Mathf.Exp(dist * depthExponent);
  98.             float waveVal = Mathf.Clamp01(1-Mathf.Abs(dist / waveAttenuation));
  99.             float foam = (noise.cnoise(new float2(position.x * foamFrequency * 0.1f, position.z * foamFrequency * 0.1f)) * 0.5f + 0.5f) * foamAmount;
  100.            
  101.             intersection = hasHitBelow ? intersection : 0f;
  102.             intersection = hasHitAbove ? 1f : intersection;
  103.  
  104.             depthVal = hasHitBelow ? depthVal : 0f;
  105.             depthVal = hasHitAbove ? 1f : depthVal;
  106.            
  107.             waveVal = hasHitBelow ? waveVal : 0f;
  108.             waveVal = hasHitAbove ? 1f : waveVal;
  109.  
  110.             colors[i] = new Color(intersection, depthVal, waveVal, foamAmount > 0 ? foam : colors[i].a);
  111.         }
  112.  
  113.         newMesh.vertices = verts;
  114.         newMesh.triangles = sourceMesh.triangles;
  115.         newMesh.normals = sourceMesh.normals;
  116.         newMesh.tangents = sourceMesh.tangents;
  117.         newMesh.uv = sourceMesh.uv;
  118.        
  119.         newMesh.colors = colors;
  120.        
  121.         newMesh.RecalculateBounds();
  122.  
  123.         return newMesh;
  124.     }
  125. }
  126.  
  127. #if UNITY_EDITOR
  128. [CustomEditor(typeof(WaterVertexColorBaker))]
  129. [CanEditMultipleObjects]
  130. class WaterVertexColorBakerEditor : Editor
  131. {
  132.     public override void OnInspectorGUI()
  133.     {
  134.         EditorGUI.BeginChangeCheck();
  135.  
  136.         base.OnInspectorGUI();
  137.  
  138.         if (EditorGUI.EndChangeCheck())
  139.         {
  140.             EditorApplication.delayCall += () =>
  141.             {
  142.                 foreach (var target in targets)
  143.                     ((WaterVertexColorBaker)target).Bake();
  144.             };
  145.         }
  146.     }
  147. }
  148. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement