|
闲聊
最早学习细胞噪声是为了做体积云,之前写柏林噪声堆集了经验,写新噪声应该能轻松不少吧?
我离准点下班又近了一步
然而,事实是
核心算法
计算过程
细胞噪声是怎么计算的呢,先看一张图,下图是256x256的细胞噪声
我们将其拆分为16个格子
为了便利讲解,把图片外的格子也画出来
在每个格子内放入一个随机点
所有像素点的计算方式都是一致的,这里拿P点举例
先找到P点地址的格子
先算出P点至周围9个点的距离- float GetDistance(float3 pnt0, float3 pnt1) {
- return distance(pnt0, pnt1);
- }
- float distances[9];
- distances[0] = GetDistance(P, A);
- distances[1] = GetDistance(P, B);
- distances[2] = GetDistance(P, C);
- distances[3] = GetDistance(P, D);
- distances[4] = GetDistance(P, E);
- distances[5] = GetDistance(P, F);
- distances[6] = GetDistance(P, G);
- distances[7] = GetDistance(P, H);
- distances[8] = GetDistance(P, I);
复制代码 找出离P点比来的距离- float closestDistance = 999999;
- float secondClosestDistance = 999999;
- float thirdClosestDistance = 999999;
- for(int iii = 0; iii < 9; iii++) {
- float tempDistance = distances[iii];
- if(tempDistance < closestDistance ) {
- thirdClosestDistance = secondClosestDistance ;
- secondClosestDistance = closestDistance ;
- closestDistance = tempDistance;
- }
- else if(tempDistance < secondClosestDistance ) {
- thirdClosestDistance = secondClosestDistance ;
- secondClosestDistance = tempDistance;
- }
- else if(tempDistance < thirdClosestDistance ) {
- thirdClosestDistance = tempDistance;
- }
- }
复制代码 贴图尺寸为256x256,图片共占用16个格子,每个格子有64x64个像素点- float noiseValue = closestDistance / 64;
复制代码 大功告成!我们算出了P点的细胞噪声!
变体
改削公式还能得到分歧风格的噪声- float GetDistance(float3 pnt0, float3 pnt1) {
- float3 vec = vec0 - vec1;
- return abs(vec .x) + abs(vec .y);
- }
复制代码- float noiseValue = (secondClosestDistance - closestDistance) / 64;
复制代码
持续性
接下来我们再讨论下噪声的持续性,以P1和P2为例
P1、P2的噪声值由到各自周围9个点的距离决定,只要保证9个距离是一致的,两点的噪声值就相等,即摆布持续
3D噪声是同样的道理,只不外多了一个维度,计算量要大些
分形噪声(FBM)
这是一张频率为4的细胞噪声
图A
频率为8的细胞噪声
图B
频率为16的细胞噪声
图C
分形噪声 = 图A + 图B * 0.5 + 图C * 0.25,即多张噪声图叠加,每次频率翻倍,强度减半,叠加得到的图是这样
细胞噪声的道理讲完了,有没有感觉很简单呢?感兴趣的同学可以挑战下!
插件
分享一个自研噪声插件
主要功能
生成2D、3D细胞噪声,撑持四方、六方持续,以单通道保留(R8)
自定义FBM
演化动画
ComputeShader计算,运行性能良好
下载地址
Github:https://github.com/MagicStones23/Unity-Shader-Tutorial-Seamless-2D-3D-Worley-Noise
百度网盘:https://pan.baidu.com/s/1wyeZGxh_GJTIUuI0-LjWcA?pwd=1111 提取码:1111
东西教程
Unity版本是2021.3
点击Generate生成噪声,点击SaveToDisk将噪声保留到当地
主要参数说明
SaveToDiskPath:保留路径
Resolution:分辩率
Frequency:频率
Is3D:生成3D噪声
IsTilable:生成持续的噪声,需要保证频率>=4,分辩率/频率=整数,例如 256 / 4,256 / 8
FbmIteration:分形噪声迭代次数
RemapTo01:将噪声值从头映射到[0,1]
Invert:将噪声值反相
ReturnType:风格
Evolution:演化动画,需要配合脚本使用
提示:3D噪声的内存占用和运算量都斗劲大,生成3D噪声时,分辩率最好不要超过256(除非你的显卡很棒)
示例
默认2D噪声
ReturnType = IrregularRock
开启反相
封锁/开启持续
不持续
四方持续
开启重映射,开启反相,FbmIteration = 2
演化,演化功能需要配合脚本使用- public class WorleyNoise_Test_Evolution : MonoBehaviour {
- public float evolutionSpeed;
- public WorleyNoise worleyNoise;
- private void FixedUpdate() {
- float time = Time.realtimeSinceStartup;
- if (time % 3 < 1) {
- worleyNoise.evolution.x += Time.fixedDeltaTime * evolutionSpeed * 1.0f;
- worleyNoise.evolution.y += Time.fixedDeltaTime * evolutionSpeed * 0.75f;
- worleyNoise.evolution.z += Time.fixedDeltaTime * evolutionSpeed * 0.5f;
- }
- else if (time % 3 < 2) {
- worleyNoise.evolution.x += Time.fixedDeltaTime * evolutionSpeed * 0.75f;
- worleyNoise.evolution.y += Time.fixedDeltaTime * evolutionSpeed * 1.0f;
- worleyNoise.evolution.z += Time.fixedDeltaTime * evolutionSpeed * 0.5f;
- }
- else {
- worleyNoise.evolution.x += Time.fixedDeltaTime * evolutionSpeed * 1.0f;
- worleyNoise.evolution.y += Time.fixedDeltaTime * evolutionSpeed * 0.5f;
- worleyNoise.evolution.z += Time.fixedDeltaTime * evolutionSpeed * 0.75f;
- }
- worleyNoise.Generate();
- }
- }
复制代码
https://www.zhihu.com/video/1628019249930260480
默认3D噪声
封锁/开启持续
不持续
六方持续
开启重映射,开启反相,FbmIteration = 2
主页
此次的教程就到此结束了,如果喜欢记得点个赞,我们下篇文章再见! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|