柏林噪声分形&幻想大陆地图生成

这篇具有很好参考价值的文章主要介绍了柏林噪声分形&幻想大陆地图生成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

序言

之前介绍过perlin噪声的实现,现在应用实践一下——程序化生成幻想大陆
这里使用的是perlin噪声倍频技术(也称分形噪声),详情传送门:柏林噪声算法
代码示例使用的是shadertoy的语法规则,shandertoy传送门:ShaderToy

示例

柏林噪声分形&幻想大陆地图生成

#define amp 1.9
#define fre 1.
#define oct 5.

#define laun 2.
#define pers 0.8

#define zoom 5.

#define edge 1.0
#define delta_edge .2

#define snow        vec3(.9, .9, .9)
#define mountains   vec3(.4, .4, .2)
#define hills       vec3(.6, .6, .1)
#define plain       vec3(.1, .8, .2)
#define beach       vec3(.8, .8, .1)
#define shallow_sea vec3(.1, .1, .9)
#define deep_sea    vec3(.1, .1, .6)

#define v_snow =       .95
#define v_mountains    .90
#define v_hills        .80
#define v_plain        .70
#define v_beach        .55
#define v_shallow_sea  .50
#define v_deep_sea     .30

float rand(vec2 p){
    return fract(sin(dot(p ,vec2(12.9898,78.233))) * 43758.5453);
}

float noise(vec2 x)
{
    vec2 i = floor(x);
    vec2 f = fract(x);

    float a = rand(i);
    float b = rand(i + vec2(1.0, 0.0));
    float c = rand(i + vec2(0.0, 1.0));
    float d = rand(i + vec2(1.0, 1.0));
    vec2 u = f * f * f * (f * (f * 6. - 15.) + 10.);

    float x1 = mix(a,b,u.x);
    float x2 = mix(c,d,u.x);
    return mix(x1,x2,u.y);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = (fragCoord.xy-0.5 * iResolution.xy) / iResolution.y; 
    vec2 u = fragCoord.xy / iResolution.xy;
     float d = min(min(u.x, edge - u.x), min(u.y, edge - u.y));

    float dw = smoothstep(0.0, delta_edge, d);
    
    float val = .0;
    uv *= zoom;
    

    for(float i = 0.; i < oct; i++)
    {
        float a = amp * pow(pers, i);
        float f = fre * pow(laun, i);
        val += a * noise(uv * f) / oct;
    }
    
    val *= dw;
    
    vec3 col = vec3(0.);
    if (val < v_deep_sea)
        col = deep_sea;
        
    if (val >= v_deep_sea && val < v_shallow_sea)
        col = shallow_sea;
        
    if (val >= v_shallow_sea && val < v_beach)
        col = beach;
        
    if (val >= v_beach && val < v_plain)
        col = plain;
        
    if (val >= v_plain && val < v_hills )
        col = hills ;
        
    if (val >= v_hills && val < v_mountains)
        col = mountains;
        
    if (val >= v_mountains)
        col = snow;    
    

    fragColor = vec4(col, 0.);
}

思路

生成地形轮廓

地形轮廓的生成主要依靠噪声,来看倍频相关代码(for迭代那部分)相关参数
主要参数

  • frequency 频率
  • amplitude 振幅
  • octave 八度,即迭代次数

相信相关三角函数都学过,就不赘述了
辅助参数
柏林噪声分形&幻想大陆地图生成

  • lacunarity 隙度,修饰频率,使得频率随每个八度以指数增长
  • persistent 持久度,与隙度类似

使用上述代码的参数,随着迭代,每次迭代叠加的细节越来越多(频率更高),但影响越来越小(振幅更小),具象一点的比喻就像:第一次迭代产生山峰的轮廓,第二次迭代产生山峰上巨石的轮廓,第三次迭代产生小石头等的轮廓...

雕刻大陆

经过第一步我们的每一个uv都可以得到一个噪声值,因为噪声值是连续的,可以定义连续的区间为某个地形,这样产生的地形也一定是连续的。比如我把[-∞,0.5)区间定义为海洋,[0.5, 0.55)定义为沙滩等,如代码那一堆地形相关的define。接下来就是不断调整参数,使其参数在合理的区间变化(合理是指生成的大陆符合你的逻辑或审美),由于参数较多且关联,虽然在一定区间内有些规律可循,还是有点难以预料,我称之为——赛博炼丹。

大陆边缘处理

我们生成的是一片完整的大陆,边缘当然得是海!让生成的噪声乘以一个权重,改该权重在图片边缘部分的一个区间内递减,这里是delta_edge = 0.2的边缘区间,如上述代码d和dw的计算。

附录

简化版perlin噪声

柏林噪声分形&幻想大陆地图生成

float rand(vec2 p){
    return fract(sin(dot(p ,vec2(12.9898,78.233))) * 43758.5453);
}

float noise(vec2 x)
{
    vec2 i = floor(x);
    vec2 f = fract(x);

    float a = rand(i);
    float b = rand(i + vec2(1.0, 0.0));
    float c = rand(i + vec2(0.0, 1.0));
    float d = rand(i + vec2(1.0, 1.0));
    vec2 u = f * f * f * (f * (f * 6. - 15.) + 10.);

    float x1 = mix(a,b,u.x);
    float x2 = mix(c,d,u.x);
    return mix(x1,x2,u.y);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = (fragCoord.xy-0.5 * iResolution.xy) / iResolution.y; 
    uv *= 4.;
    float val = noise(uv.xy) ;
    fragColor = vec4(val);
}

分形噪声

柏林噪声分形&幻想大陆地图生成文章来源地址https://www.toymoban.com/news/detail-468553.html

#define amp 1.9
#define fre 1.
#define oct 5.

#define laun 2.
#define pers 0.8

#define zoom 5.

float rand(vec2 p){
    return fract(sin(dot(p ,vec2(12.9898,78.233))) * 43758.5453);
}

float noise(vec2 x)
{
    vec2 i = floor(x);
    vec2 f = fract(x);

    float a = rand(i);
    float b = rand(i + vec2(1.0, 0.0));
    float c = rand(i + vec2(0.0, 1.0));
    float d = rand(i + vec2(1.0, 1.0));
    vec2 u = f * f * f * (f * (f * 6. - 15.) + 10.);

    float x1 = mix(a,b,u.x);
    float x2 = mix(c,d,u.x);
    return mix(x1,x2,u.y);
}


void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
	vec2 uv = (fragCoord.xy-0.5 * iResolution.xy) / iResolution.y; 

    
    float val = .0;
    uv *= zoom;
    

    for(float i = 0.; i < oct; i++)
    {
        float a = amp * pow(pers, i);
        float f = fre * pow(laun, i);
        val += a * noise(uv * f) / oct;
    }
    
    vec3 col = vec3(val);

    fragColor = vec4(col, 0.);
}

到了这里,关于柏林噪声分形&幻想大陆地图生成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity 使用柏林噪声程序化生成地形

    参考教程链接 项目链接 👇对噪声和柏林噪声不了解的可以看下面这个讲解。 柏林函数简介   简单来说柏林噪声是一种连续的、渐变的噪声,不理解原理也无所谓,unity自带有Mathf.PerlinNoise(X-coordinate,Y-coordinate);我们可以根据这个来制作更有层次性的柏林噪声。你可以把这个

    2024年02月15日
    浏览(41)
  • OpenCV学习笔记(十一)——图像噪声的生成(椒盐噪声、高斯噪声)

    图像在获取和传输过程种会受到随机信号的干扰从而产生噪声,例如电阻引起的热噪声、光子噪声、暗电流噪声以及光响应非均匀性噪声等,由于噪声会影响对图像的理解以及后续的处理工作,因此去除噪声的影响在图像中具有十分重要的意义。图像中常见的噪声有:椒盐噪

    2024年02月04日
    浏览(68)
  • 基于FPGA的高斯白噪声的生成(中心极限定理)

    大家可以在网上查询中心极限定理的定理和解释。中心极限定理意思就是说在一组服从均匀分布的数据中,随机抽取选取m个数,然后求这个m个数的平均值,这个平均数作为x1。继续随机抽取m个数,求这m个数的平均值,作为x2,就这样一直抽取n组数,也就是获得n个的数,每一

    2024年02月10日
    浏览(50)
  • Java面试八股文宝典:序言

    Java作为一门广泛应用于企业级应用开发的编程语言,一直以来都是技术面试中的重要话题。无论您是刚刚踏入编程世界的新手,还是经验丰富的Java开发工程师,都需要通过面试来展示自己的技能和知识。 在面试中,除了技术知识,还需要展现出解决问题、沟通能力和编程实

    2024年02月09日
    浏览(57)
  • 【安全密钥交换协议】基尔霍夫定律-约翰逊噪声(KLJN)方案的随机数生成器攻击研究(Matlab代码实现)

     💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 2.1 算例1 2.2 算例2  2.3 算例3 🎉3 参考文

    2024年02月04日
    浏览(56)
  • 【安全密钥】对基尔霍夫-洛-约翰逊噪声(KLJN)安全密钥交换协议的统计随机数生成器攻击(Matlab代码实现)

    💥💥💞💞 欢迎来到本博客 ❤️❤️💥💥 🏆博主优势: 🌞🌞🌞 博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️ 座右铭: 行百里者,半于九十。 📋📋📋 本文目录如下: 🎁🎁🎁 目录 💥1 概述 📚2 运行结果 🎉3 参考文献 🌈4 Matlab代码、数据、文章

    2024年04月12日
    浏览(56)
  • Rx.NET in Action 中文介绍 前言及序言

    目标 可选方式 Rx 处理器(Operator) 创建 Observable Creating Observables 直接创建 By explicit logic Create Defer 根据范围创建 By specification Range Repeat Generate Timer Interval Return 使用预设 Predefined primitives Throw Never Empty 从其他类型创建 From other types FromEventPattern FromEvent FromTask FromAsync 变换 Transform

    2024年02月13日
    浏览(51)
  • 如何高度优化适用于企业自定义的AI (一) 序言

    在当前信息时代的背景下, 社会对AI的需求在不断增长. AI的快速发展得益于大数据、云计算和计算能力的提升, 使得机器学习和深度学习等技术取得了重大突破. AI在图像识别、语音识别、自然语言处理等领域展现出惊人的能力, 为企业带来了巨大的商机. 然而, 通用的AI解决方案

    2024年02月11日
    浏览(42)
  • shader编程经典:分形--科赫曲线

    科赫(雪花)曲线是一个经典分形图案,来一起领略下分形之美。本篇内容用到一些基础的内容,例如UV的理解和画线技巧,有需要的话可以参考合集的画圆和画线两篇文章。 shadertoy 代码: 先简化一下问题--只考虑一次迭代 观察到上述代码有偏移和对称,其实我们只需要关

    2024年02月07日
    浏览(37)
  • shader编程经典:分形--科赫(雪花)曲线

    科赫(雪花)曲线是一个经典分形图案,来一起领略下分形之美。本篇内容用到一些基础的内容,例如UV的理解和画线技巧,有需要的话可以参考合集的画圆和画线两篇文章。 shadertoy 代码: 先简化一下问题--只考虑一次迭代 观察到上述代码有偏移和对称,其实我们只需要关

    2024年02月07日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包