首页 > 其他分享 >柏林噪声&幻想大陆地图生成

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

时间:2023-06-02 16:36:02浏览次数:49  
标签:幻想 rand 1.0 val float 噪声 vec2 柏林 define

序言

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

示例

image

#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 八度,即迭代次数

相信相关三角函数都学过,就不赘述了
辅助参数
image

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

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

雕刻大陆

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

大陆边缘处理

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

附录

简化版perlin噪声

image

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);
}

分形噪声

image

#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.);
}

标签:幻想,rand,1.0,val,float,噪声,vec2,柏林,define
From: https://www.cnblogs.com/hggzhang/p/17432947.html

相关文章

  • 杂记:噪声
    从声学的角度看,一切不规则的或随机的声信号都称为噪声。而从心里学的角度看,一切不希望存在的干扰声,都称为噪声。即使是优美的音乐,如果它干扰人们的睡眠或思考,也属于噪声。以下主要从声学角度描述噪声。白噪声白噪声是听觉研究中十分有用的一类噪声。借意于光学中白光形成的原理......
  • L1频段卫星导航射频前端低噪声放大器芯片 AT2659/AT2659S
    AT2659是一款具有高增益、低噪声系数的低噪声放大器(LNA)芯片,支持L1频段多模式全球卫星定位,可以应用于GPS、北斗二代、伽利略、Glonass等GNSS导航接收机中。芯片采用先进的SiGe工艺制造,采用1.5mmX1mm×0.78mm的6pinDFN封装。主要特点-支持北斗、GPS、GALILEO、GLONASS......
  • 数字基带仿真之--噪声怎么加
    我们在仿真时需要加噪声,噪声功率谱密度是N0/2,但是对于无限频谱宽度的白噪声,功率无穷大。那么,噪声怎么加?来看一幅图:白噪声通过匹配滤波器后,方差有限,并且大小为功率谱密度。因此,对其抽样,得到方差为N0/2的噪声序列。加噪声也就是一行(伪代码):noise=sqrt(N0/2)*randn(1,length(syb......
  • BOSHIDA电源模块 开关电源磁性元件设计 电磁噪声的处理
    BOSHIDA电源模块开关电源磁性元件设计电磁噪声的处理众所周知,开关电源在降低装置物理尺寸和内部功耗方面具有显著的优势。然而,其快速变化的电压和电流波形富含高频谐波,它们产生的电磁干扰EMI)一直是个严重的问题。因此,电磁兼容性(EMC)的设计要求已经和电源性能同样重要,本章将介绍......
  • 基于FPGA的FIR低通滤波器verilog开发,包含testbench测试程序,输入噪声信号使用MATLAB
    1.算法仿真效果VIVADO2019.2/matlab2022a仿真结果如下:运行matlab:将matlab得到的数据文件保存到FPGA的project_13.sim\sim_1\behav\xsim路径,测试仿真时,可以自动调用matlab任意产生的测试数据。rtl:2.算法涉及理论知识概要FIR(FiniteImpulseResponse)滤波器:有限长单位冲激......
  • 基于FPGA的FIR低通滤波器verilog开发,包含testbench测试程序,输入噪声信号使用MATLAB
    1.算法仿真效果VIVADO2019.2/matlab2022a仿真结果如下: 运行matlab:    将matlab得到的数据文件保存到FPGA的project_13.sim\sim_1\behav\xsim路径,测试仿真时,可以自动调用matlab任意产生的测试数据。   rtl:   2.算法涉及理论知识概要       ......
  • 数字信号处理(四)噪声
    噪声分为加性噪声、乘性噪声。加性噪声一般被认为是系统的背景噪声;而乘性噪声伴随信号产生,是系统时变性引起的。单独分析时,只需要对乘性噪声取对数,就可化为加性噪声,所以所有的乘性噪声都可被近似为加性噪声。 实际上,信号既存在加性又存在乘性噪声。 但是,通常只处理乘性噪......
  • matlab,基于卡尔曼滤波的语音处理程序,针对现有语音信号,人为添加噪声,使用卡尔曼滤波器对
    matlab,基于卡尔曼滤波的语音处理程序,针对现有语音信号,人为添加噪声,使用卡尔曼滤波器对其噪声进行滤波,达到语音去噪的目的ID:89500621487113339......
  • 利用MATLAB GUI设计平台,设计多算法雷达一维恒虚警检测CFAR可视化界面,通过选择噪声类型
    利用MATLABGUI设计平台,设计多算法雷达一维恒虚警检测CFAR可视化界面,通过选择噪声类型、目标类型、算法类型,手动输入相关参数,可视化显示噪声波形与目标检测的回波-检测门限波形图ID:94200670614830016......
  • ICEEMDAN,改进的/完全自适应噪声集合经验模态分解。 是由自适应
    ICEEMDAN,改进的/完全自适应噪声集合经验模态分解。是由自适应噪声完全集合经验模态分解(CEEMDAN)的基础上发展而来。改进的方法不同于CEEMDAN在分解过程中直接添加高斯白噪声,而是选取白噪声被EMD分解后的第K个IMF分量。ID:8180701014875386......