duck

Unity 3D Procedural Terrain - Step 6 - Texture Lerping

Mar 1st, 2013
310
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class TerrainNoise : MonoBehaviour {
  5.    
  6.     float waterSmooth = 0;
  7.     float[,] heights;
  8.     Terrain terrain;
  9.     TerrainData data;
  10.     Transform water;
  11.     int noiseLayerCount = 20;
  12.     NoiseLayer[] noiseLayers;
  13.     float heightBoost = 10;
  14.     float updateTime;
  15.     bool dirty = true;
  16.    
  17.     void OnGUI()
  18.     {
  19.         GUILayout.BeginArea( new Rect(20,20,400,400) );
  20.        
  21.         GUI.color = Color.black;
  22.        
  23.         GUILayout.Label("WaterSmooth: "+waterSmooth);
  24.         float newWaterSmooth = GUILayout.HorizontalSlider(waterSmooth, 0f, 1f);
  25.         if (newWaterSmooth != waterSmooth)
  26.         {
  27.             waterSmooth = newWaterSmooth;
  28.             dirty = true;
  29.             updateTime = Time.time + 0.5f;
  30.         }
  31.        
  32.         GUILayout.Label("HeightBoost: "+heightBoost);
  33.         float newHeightBoost = GUILayout.HorizontalSlider(heightBoost, 1f, 40f);
  34.         if (newHeightBoost != heightBoost)
  35.         {
  36.             heightBoost = newHeightBoost;
  37.             dirty = true;
  38.             updateTime = Time.time + 0.5f;
  39.         }
  40.        
  41.         GUILayout.EndArea();
  42.        
  43.     }
  44.    
  45.     void Start()
  46.     {
  47.        
  48.         terrain = GetComponent<Terrain>(); 
  49.         data = terrain.terrainData;
  50.         heights = new float[ data.heightmapWidth, data.heightmapHeight];
  51.         water = GameObject.Find ("Water").transform;
  52.        
  53.        
  54.        
  55.         // create the required number of noise layer definitions
  56.         noiseLayers = new NoiseLayer[noiseLayerCount];
  57.         float frequency = .003f;
  58.         float amplitude = 0.5f;
  59.         for( int n=0; n<noiseLayers.Length; ++n)
  60.         {
  61.             noiseLayers[n] = new NoiseLayer();
  62.             noiseLayers[n].frequency = frequency;
  63.             noiseLayers[n].amplitude = amplitude;
  64.            
  65.             amplitude *= 0.5f;
  66.             frequency *= 2f;
  67.            
  68.         }
  69.        
  70.     }
  71.    
  72.     // Use this for initialization
  73.     void Update () {
  74.    
  75.         if (dirty && Time.time > updateTime)
  76.         {
  77.        
  78.             // Generate Heightmap
  79.            
  80.             float waterHeight = water.position.y / data.size.y;
  81.            
  82.             for( int x=0; x< data.heightmapWidth; ++x)
  83.             {
  84.                 for( int z=0; z< data.heightmapHeight; ++z)
  85.                 {
  86.                     // accumulate height values from each perlin noise layer
  87.                     float height = 0;
  88.                     foreach(NoiseLayer noiseLayer in noiseLayers)
  89.                     {
  90.                         float f = noiseLayer.frequency;
  91.                         float a = noiseLayer.amplitude;
  92.                         height += Mathf.PerlinNoise(x*f, z*f) * a;
  93.                     }
  94.                    
  95.                     // smooth heights at water level
  96.                     float waterSmoothedHeight = height - waterHeight;
  97.                     float heightSign = Mathf.Sign(waterSmoothedHeight);
  98.                     waterSmoothedHeight *= (waterSmoothedHeight * heightSign) * heightBoost;
  99.                     waterSmoothedHeight += waterHeight;
  100.                    
  101.                    
  102.                     height = Mathf.Lerp( height, waterSmoothedHeight, waterSmooth );
  103.                    
  104.                     heights[x,z] = height;
  105.                    
  106.                 }
  107.             }
  108.            
  109.             data.SetHeights(0, 0, heights);
  110.            
  111.            
  112.             float waterBlendRange = 25 / data.size.y;
  113.            
  114.             // Generate Texture mixing map
  115.            
  116.             float [,,] alphamap = new float[ data.alphamapWidth, data.alphamapHeight, 4];
  117.                
  118.             for (int x=0; x<data.alphamapWidth; ++x)
  119.             {
  120.                 for (int z=0; z<data.alphamapWidth; ++z)
  121.                 {
  122.                     // normalize x and z values
  123.                     float nx = x / (float)data.alphamapHeight;
  124.                     float nz = z / (float)data.alphamapWidth;
  125.                    
  126.                     Vector4 mix = new Vector4(1,0,0,0);
  127.                    
  128.                     float height = data.GetInterpolatedHeight( nz, nx ) / data.size.y;
  129.                        
  130.                    
  131.                    
  132.                     if (height > waterHeight ) {
  133.                        
  134.                         float blend = Mathf.InverseLerp( waterHeight, waterHeight+waterBlendRange, height );
  135.                        
  136.                         mix = Vector4.Lerp ( mix, new Vector4(0,1,0,0), blend );
  137.                        
  138.                     }
  139.                    
  140.                    
  141.                    
  142.                     alphamap[x,z,0] = mix.x;
  143.                     alphamap[x,z,1] = mix.y;
  144.                     alphamap[x,z,2] = mix.z;
  145.                     alphamap[x,z,3] = mix.w;
  146.                 }
  147.                
  148.             }
  149.            
  150.             data.SetAlphamaps( 0, 0, alphamap );
  151.            
  152.        
  153.             dirty = false;
  154.         }
  155.     }
  156.    
  157. }
  158.  
  159.  
  160. public struct NoiseLayer
  161. {
  162.     public float amplitude;
  163.     public float frequency;
  164.    
  165. }
Advertisement
Add Comment
Please, Sign In to add comment