前言
正态分布
正态分布(英语:normal distribution)又名高斯分布(英语:Gaussian distribution),是一个非常常见的连续概率分布。
这里就简单介绍一下:
噪点
什么是噪点(noise)?
我们通常看到的噪点,都是画面上成千上万的小斑点,这些噪点可能会降低细节或使画面中的暗部细节显得很“脏”。 这就是为什么在大多数情况下,噪音被认为是“不速之客”。
噪点同许多事物一样是一把“双刃剑”,合理运用反而可以产生一些良好的效果:
如表现出一种老胶卷的效果,营造恐怖气氛等
当然,也可以利用噪点完成一些效果,如:Unity Shader - Noise 噪点应用,实现类似流水的表面效果_Jave.Lin的博客-CSDN博客_shader 噪点
噪声函数介绍(Introduction To Noise Functions)
实际操作
那么在Unity中我们应当从何下手呢?
把上面的公式转换成可执行代码:
/// <summary> /// 高斯分布概率模型 /// </summary> /// <param name="_x">随机变量</param> /// <param name="_μ">位置参数</param> /// <param name="_σ">尺度参数</param> /// <returns></returns> private static float NormalDistribution(float _x, float _μ, float _σ) { float _inverseSqrt2PI = 1 / Mathf.Sqrt(2 * Mathf.PI); float _powOfE = -(Mathf.Pow((_x - _μ), 2) / (2 * _σ * _σ)); float _result = (_inverseSqrt2PI / _σ) * Mathf.Exp(_powOfE); return _result; }
情景假设
假设我们要绘制一张大小为1024*1024,从中心向四周逐渐稀疏,并且颜色越来越淡的噪点图,代码如下:
/// <summary> /// 通过高斯分布公式绘制一张离散效果图 /// </summary> /// <param name="_centerPoint">中心点坐标</param> /// <param name="_consi">图颜色的阿尔法值</param> /// <returns></returns> public Texture2D CreateTeture2D(Vector2 _centerPoint, float _consi) { Texture2D _newTex = new Texture2D(1024, 1024, TextureFormat.ARGB32, true); Color[] _colorBase = new Color[1024 * 1024]; int _hwidth = (int)(1024 * _centerPoint.x); int _hheight = (int)(1024 * _centerPoint.y); float _per; int _index; for (int i = 0; i < 1024; i++) { for (int j = 0; j < 1024; j++) { _per = (Mathf.Sqrt((i - _hwidth) * (i - _hwidth) + (j - _hheight) * (j - _hheight))) / 512; float _tr = NormalDistribution(_per, 0, 1); //float _tr = NormalDistribution(0, 0, 1)=0.3989423f;也就是说中心点的概率为0.3989423f,即最大概率 bool _drawing = Random.Range(0, 0.3989423f) < _tr ? true : false; if (_drawing) { _index = i * 1024 + j; _colorBase[_index] = new Color(1, 0, 0, _tr * _consi); } else { _colorBase[i * 1024 + j] = new Color(0, 0, 0, 0); } } } _newTex.SetPixels(_colorBase); _newTex.Apply(); _colorBase = null; System.GC.Collect(); return _newTex; }
效果演示
当中心点坐标为(0.5,0.5),颜色阿尔法值为1时,效果如下:
当中心点坐标为(0.2,0.3)时,效果如下:
我们还可以将这句代码:
_colorBase[_index] = new Color(1, 0, 0, _tr * _consi );
更改为:
_colorBase[_index] = new Color(1, 0, 0, _tr * _consi * (1 - _per));
这样绘制的图,颜色从中心点渐变到边缘时,会完全透明,效果如下: