当前位置:   article > 正文

Unity 地形设计之分形布朗运动(五)_fractal brownian motion model

fractal brownian motion model

     分形布朗运动FBM(Fractal Brown Motion)是1968年Mandelbrot和Ness两人提出的一种数学模型,它是一种随机运动,粒子的运动方向随时改变,其运动轨迹是一条无规则的折线,不受什么约束和支配。它主要用于描述自然界的山脉、云层、地形地貌以及模拟星球表面等不规则形状阶。

分型布朗运动的原理:https://thebookofshaders.com/13/?lan=ch

 从音乐理论上说,每个音符都和一个特定的频率相关联。这些音符和频率的关系遵从一定的模式,也就是我们所说的音阶,一个八度(octave)对应着频率上的加倍或减半。

通过在循环(循环次数为 octaves,一次循环为一个八度)中叠加噪声,并以一定的倍数(lacunarity,间隙度)连续升高频率,同时以一定的比例(gain,增益)降低 噪声 的振幅,最终的结果会有更好的细节。这项技术叫“分形布朗运动(fractal Brownian Motion)”(fBM),或者“分形噪声(fractal noise)”

这一篇我们将自己创建一个布朗运动,通过分型布朗运动改进噪音算法,下面我们创建一个静态的工具类。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public static class Utils {
  5. // 分形布朗运动函数,静态方法方便从外部调用
  6. //要在热点地图中传递一个位置x,y,
  7. public static float fBM(float x, float y, int oct, float persistance)
  8. {
  9. float total = 0;
  10. float frequency = 1;//频率是波的紧密程度,一个八度(octave)对应着频率上的加倍或减半
  11. float amplitude = 1;//振幅
  12. float maxValue = 0;
  13. for (int i = 0; i < oct; i++)//遍历每个八度
  14. {
  15. total += Mathf.PerlinNoise(x * frequency, y * frequency) * amplitude;//通过循环叠加噪声
  16. maxValue += amplitude;//最大值是每个oct使用的振幅相加
  17. amplitude *= persistance;//以一定的比例降低噪声的振幅
  18. frequency *= 2;//以一定的倍数连续升高频率
  19. }
  20. return total / maxValue;//注意返回值降到01之间的范围内
  21. }
  22. }

自定义地形脚本:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System;
  5. using System.Linq;
  6. using UnityEditor;
  7. public class CustomTerrain : MonoBehaviour {
  8.  //首先,我们需要一些值来存储缩放值,而这些是我们将其发送到噪声函数以确定幅度的间隔,
  9.     //如上一篇所讲,随着增量值的变大,噪音曲线将变得更加平滑
  10. //PERLIN NOISE ----------------------------------------------
  11. public float perlinXScale = 0.01f;
  12. public float perlinYScale = 0.01f;
  13. //地形整体沿X和y偏移
  14. public int perlinOffsetX = 0;
  15. public int perlinOffsetY = 0;
  16. //分型布朗运动新增属性
  17. public int perlinOctaves = 3;
  18. public float perlinPersistance = 8;
  19. public float perlinHeightScale = 0.09f;
  20. //获取地形(物体)对象
  21. public Terrain terrain;
  22. //TerrainData里有地形所有的数据
  23. public TerrainData terrainData;
  24. //每次编辑完脚本内容返回编辑器时运行后会执行此方法
  25. private void OnEnable()
  26. {
  27. //初始化地形数据 先获取地形再获取本身的地形数据
  28. terrain = gameObject.GetComponent<Terrain>();
  29. terrainData = Terrain.activeTerrain.terrainData;
  30. }
  31. public void Perlin()
  32. {
  33. float[,] heightMap = terrainData.GetHeights(0, 0, terrainData.heightmapWidth,
  34. terrainData.heightmapHeight);
  35. for (int y = 0; y < terrainData.heightmapHeight; y++)
  36. {
  37. for (int x = 0; x < terrainData.heightmapWidth; x++)
  38. {
  39. //heightMap[x, y] = Mathf.PerlinNoise((x + perlinOffsetX) * perlinXScale,
  40. // (y + perlinOffsetY) * perlinYScale);
  41. //分型布朗运动
  42. heightMap[x, y] += Utils.fBM((x + perlinOffsetX) * perlinXScale,
  43. (y + perlinOffsetY) * perlinYScale,
  44. perlinOctaves,
  45. perlinPersistance) * perlinHeightScale;
  46. }
  47. }
  48. terrainData.SetHeights(0, 0, heightMap);
  49. }
  50. }

 

编辑脚本:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEditor;
  5. [CustomEditor(typeof(CustomTerrain))]
  6. public class CustomTerrainEditor : Editor {
  7. SerializedProperty perlinXScale;
  8. SerializedProperty perlinYScale;
  9. SerializedProperty perlinOffsetX;
  10. SerializedProperty perlinOffsetY;
  11. //分型布朗运动新增属性
  12. SerializedProperty perlinOctaves;
  13. SerializedProperty perlinPersistance;
  14. SerializedProperty perlinHeightScale;
  15. bool showPerlinNoise = false;
  16. private void OnEnable()
  17. {
  18. //找到需要反复更改的属性
  19. //地形幅度大小缩放值
  20. perlinXScale = serializedObject.FindProperty("perlinXScale");
  21. perlinYScale = serializedObject.FindProperty("perlinYScale");
  22. //地形偏移量
  23. perlinOffsetX = serializedObject.FindProperty("perlinOffsetX");
  24. perlinOffsetY = serializedObject.FindProperty("perlinOffsetY");
  25. //分型布朗运动新增属性
  26. perlinOctaves = serializedObject.FindProperty("perlinOctaves");
  27. perlinPersistance = serializedObject.FindProperty("perlinPersistance");
  28. perlinHeightScale = serializedObject.FindProperty("perlinHeightScale");
  29. }
  30. //绘制编辑面板
  31. public override void OnInspectorGUI()
  32. {
  33. //更新所有序列化的值
  34. serializedObject.Update();
  35. //获取自定义的地形属性脚本组件
  36. CustomTerrain terrain = (CustomTerrain)target;
  37. #region
  38. showPerlinNoise = EditorGUILayout.Foldout(showPerlinNoise, "Single Perlin Noise");
  39. if (showPerlinNoise)
  40. {
  41. EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);
  42. GUILayout.Label("Perlin Noise", EditorStyles.boldLabel);
  43. EditorGUILayout.Slider(perlinXScale, 0, 1, new GUIContent("X Scale"));
  44. EditorGUILayout.Slider(perlinYScale, 0, 1, new GUIContent("Y Scale"));
  45. EditorGUILayout.IntSlider(perlinOffsetX, 0, 10000, new GUIContent("Offset X"));
  46. EditorGUILayout.IntSlider(perlinOffsetY, 0, 10000, new GUIContent("Offset Y"));
  47. EditorGUILayout.IntSlider(perlinOctaves, 1, 10, new GUIContent("Octaves"));
  48. EditorGUILayout.Slider(perlinPersistance, 0.1f, 10, new GUIContent("Persistance"));
  49. EditorGUILayout.Slider(perlinHeightScale, 0, 1, new GUIContent("Height Scale"));
  50. if (GUILayout.Button("Perlin"))
  51. {
  52. terrain.Perlin();
  53. }
  54. }
  55. #endregion
  56. //应用发生的所有更改
  57. serializedObject.ApplyModifiedProperties();
  58. }
  59. }

 

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号