Opengl 具有脊状分形噪声的程序地形
我实现了双线性插值白噪声,以便按程序生成地形 我可以得到这样的结果: 我想实现脊状分形噪波,以获得更真实的地形,如:Opengl 具有脊状分形噪声的程序地形,opengl,terrain,procedural-generation,Opengl,Terrain,Procedural Generation,我实现了双线性插值白噪声,以便按程序生成地形 我可以得到这样的结果: 我想实现脊状分形噪波,以获得更真实的地形,如: 然而,我找不到一个关于脊状分形噪声的好教程。你能给我解释一下怎么做吗?脊状柏林噪波实际上很容易做到-你只需要ABS()最终的高度贴图或噪波层的某个子集(然后反转生成的高度贴图值,以确保脊出现在高值处) 示例:(带有三线性插值的基本柏林噪声,然后是ABS和整个高度场的反转)。(反转表示“乘以-1”。) 我强烈建议尝试各种分形噪声层的配置和基本的数学/逻辑运算 另一个示例:(两个
然而,我找不到一个关于脊状分形噪声的好教程。你能给我解释一下怎么做吗?脊状柏林噪波实际上很容易做到-你只需要ABS()最终的高度贴图或噪波层的某个子集(然后反转生成的高度贴图值,以确保脊出现在高值处) 示例:(带有三线性插值的基本柏林噪声,然后是ABS和整个高度场的反转)。(反转表示“乘以-1”。) 我强烈建议尝试各种分形噪声层的配置和基本的数学/逻辑运算 另一个示例:(两个不同的低频柏林噪声层使用逻辑交点/数学最小值函数合并) 但是,对分形噪波算法进行简单的修改,将不会为您提供“向下流动”(并使地形更加逼真和吸引人)的细节。要实现这些,您需要添加某种侵蚀模拟,这是一种更为复杂的beast(无论是算法方面还是CPU方面) 关于这方面的一些信息,我推荐这两篇论文(您可以忽略GPU部分,算法在CPU上运行良好,但根据我的经验,对于1000x1000 px图像,模拟将需要一分钟左右): 编辑: 让我们澄清我所说的“在高度场上应用ABS”的意思 您只需获取地图每个像素的高度数值,并对其应用ABS()函数,丢弃其符号 这假定柏林噪波生成器生成范围(或以0为中心的另一个范围)中的值~50%的像素的值应大于0,约50%的像素的值应小于0 由于所有双线性/三线性插值将确保过去有一个平滑的坡度通过0值,因此ABS会在0处创建尖锐的脊线 以这幅图像为例:
它显示了两个COS(x)函数,其中一个是用ABS函数调制的(我添加了一个小偏移量,以确保两条线分别可见)。现在,假设紫色线垂直翻转-您最终看到两座山,山上有尖锐的山脊,山脊之间有一个山谷:)为了产生物理上真实的山脊,正如前面的答案所述,修改噪波函数可能不是最好的方法。相反,如果您从分形曲面开始,并对其应用适当的侵蚀功能,则可以相当轻松地创建具有物理真实形状的山脊 我最近在我的网站上写下了我的努力: 基本上,如果您的目标是简单的山脊,您可以修改热侵蚀方程以去除所有沉积(即,仅减去侵蚀)。我使用C#代码来腐蚀一个单点-它相当快,并且会在我的PC上在大约10秒内用250次迭代来腐蚀我的4096x4096测试环境(尽管在12个核上进行了一些并行化) 位的混乱只是获取被侵蚀点的8个相邻点的有效方法——我的表示使用线性阵列,因此y坐标被预先乘以景观的宽度(yMul等)。为了简单起见,可以将步幅视为1。r2和位移位只是角点的1/sqrt(2)的快速乘法
var x0 = (x1 - stride) & mask;
var x2 = (x1 + stride) & mask;
indices[0] = x0 + yMul0;
indices[1] = x1 + yMul0;
indices[2] = x2 + yMul0;
indices[3] = x0 + yMul1;
indices[4] = x2 + yMul1;
indices[5] = x0 + yMul2;
indices[6] = x1 + yMul2;
indices[7] = x2 + yMul2;
for (int i = 0; i < actualLength; i++)
{
elements[i] = thisSurface[indices[i]];
}
var height = thisSurface[x1 + yMul1];
//Differences in height.
//Corner differences multipled by 1/sqrt(2)
diffs[0] = ((height - elements[0]) * r2denom) >> 8;
diffs[1] = height - elements[1];
diffs[2] = ((height - elements[2]) * r2denom) >> 8;
diffs[3] = height - elements[3];
diffs[4] = height - elements[4];
diffs[5] = ((height - elements[5]) * r2denom) >> 8;
diffs[6] = height - elements[6];
diffs[7] = ((height - elements[7]) * r2denom) >> 8;
//Compare the differences to the talus threshold.
var max = 0;
var talusSum = 0;
var slopeSum = 0;
for (var i = 0; i < actualLength; i++)
{
var diff = diffs[i];
if (diff > 0)
{
if (diff > max)
{
max = diff;
}
talusSum += diff;
if (diff > talusThreshold)
{
slopeSum += (diff - talusThreshold);
}
}
}
talusSum = talusSum / 2 - talusThreshold;
if (talusSum > 0)
{
//Work out how much height to redistribute.
var toMove = talusSum / 4;
if (altitudeProportional)
{
toMove *= (height - minAltitude);
toMove /= (maxAltitude - minAltitude);
}
newSurface[x1 + yMul1] -= toMove;
}
var x0=(x1-步幅)和掩码;
变量x2=(x1+步幅)和遮罩;
指数[0]=x0+yMul0;
指数[1]=x1+yMul0;
指数[2]=x2+yMul0;
指数[3]=x0+yMul1;
指数[4]=x2+yMul1;
指数[5]=x0+yMul2;
指数[6]=x1+yMul2;
指数[7]=x2+yMul2;
对于(int i=0;i<实际长度;i++)
{
元素[i]=该表面[i]];
}
var高度=该表面[x1+yMul1];
//身高差异。
//角差乘以1/sqrt(2)
差异[0]=((高度-元素[0])*r2denom)>>8;
差异[1]=高度-元素[1];
差异[2]=((高度-元素[2])*r2denom)>>8;
差异[3]=高度-元素[3];
差异[4]=高度-元素[4];
差异[5]=((高度-元素[5])*r2denom)>>8;
差异[6]=高度-元素[6];
差异[7]=((高度-元素[7])*r2denom)>>8;
//将差异与距骨阈值进行比较。
var max=0;
talusSum变量=0;
var slopeSum=0;
对于(变量i=0;i<实际长度;i++)
{
var diff=差异[i];
如果(差异>0)
{
如果(差异>最大值)
{
最大值=差值;
}
距骨+=diff;
如果(差异>talusThreshold)
{
斜率sum+=(差-塔卢斯阈值);
}
}
}
talusSum=talusSum/2-talusThreshold;
如果(距骨>0)
{
//计算出要重新分配的高度。
var-toMove=talusSum/4;
if(高度比例)
{
toMove*=(高度-高度);
toMove/=(最大高度-最低高度);
}
newSurface[x1+yMul1]=toMove;
}
+1用于包含所需输出的示例-当我们都有相同的目标时,可以更轻松地对流程进行故障排除。说到这里,它看起来像一个模拟侵蚀可能已经被应用到获取输出-你在哪里找到它的?嗨:)谢谢你的帮助。我认为这是对噪波函数的一个修改,以获得脊线。我认为这是脊状分形噪声。但是我找不到我必须对我的噪音做的改变来得到这样的东西。在一个网站上,有人说这只是一个用绝对值函数改变的噪音。但我不知道如何使用绝对值函数来更改噪声输出:我不清楚如何使用ab