柏林噪声&幻想大陆地图生成
序言
之前介绍过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);
}
分形噪声
#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.);
}
柏林噪声&幻想大陆地图生成的更多相关文章
- Unity中使用柏林噪声生成地图
孙广东 2017.3.27 http://blog.csdn.NET/u010019717 主要是利用Unity的 Mathf.PerlinNoise 函数(柏林噪声)的不同寻常的功能. htt ...
- 柏林噪声算法(Perlin Noise)
概述 引述维基百科的介绍: Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值. 在电子游 ...
- GPS地图生成02之经典算法体验
经典的利用轨迹生成地图的算法与数据集可寻找于:Mapconstruction by pfoser Mapconstruction by pfoser数据集中,雅典数据集投影坐标系为(UTM, GGRS ...
- unity3d WorldComposer1 卫星地图生成地形
http://blog.csdn.net/myarrow/article/details/42709113 1. 简介 1.1 TerrainComposer(TC) 一个Unity扩展工具,可用于创 ...
- RaceWeb介绍(7):由500强公司数据高速生成百度地图——生成坐标字段及坐标数据
接上篇. 一.生成X坐标.Y坐标两个字段. 我们须要为每一个公司建立X坐标和Y坐标字段,用来保存XY坐标. 既然为了突出"快",这一步就有程序来完毕吧. 右键单击"世界5 ...
- echarts使用------地图生成----省市地图的生成及其他相关细节调整
为使用多种业务场景,百度echarts地图示例只有中国地图,那么在使用省市地图的时候,就需要我们使用省市的地图数据了 以下为陕西西安市的地图示例: 此页面引用echarts的js:http://ech ...
- Unity 随机房间地图生成
无论是在迷宫还是类似于地牢的游戏地图中,利用程序来生成每次都不一样的地图是一件叫人兴奋不已的事. 这时我们需要解决两个非常重要的随机事件: 1.在一定范围内随机出各不相同但又不能互相重叠的房间 2.优 ...
- 帝国CMS网站地图生成插件
可以生成电脑端也可以生成手机端的地图XML. 安装方法: 这个帝国sitemap插件的安装跟其他插件的安装方式一样,介于可能有人不会安装帝国的插件,就写一下吧,以后你们如果碰到帝国插件也可以参考这个. ...
- GPS地图生成04之数据预处理
1. 引言¶ 下载的轨迹数据来源真实,并非特意模拟的轨迹数据,所以质量问题十分严重,进行预处理就显得尤为重要 2. 裁剪¶ 我们将下载的岳麓山轨迹数据加载入QGIS,并使用OSM作为底 ...
- Unity3d 随机地图生成
2D解析图: 3D地形: 嘿嘿.
随机推荐
- Redis 线程模型
一.概述 [1]Redis 是基于 Reactor 模式开发的网络事件处理器:这个处理器被称为文件事件处理器(file event handler),这个文件事件处理器是单线程的,所以 Redis 才 ...
- 可靠消息最终一致性【本地消息表、RocketMQ 事务消息方案】
更多内容,前往IT-BLOG 一.可靠消息最终一致性事务概述 可靠消息最终一致性方案是指当事务发起方执行完成本地事务后并发出一条消息,事务参与方(消息消费者)一定能够接收消息并处理事务成功,此方案强调 ...
- HTML+JS+CSS实现图片文件上传界面设计的例子
在Java Web应用程序设计中文件上传功能的实现是一项非常重要的工作,本文中的例子程序实现了文件上传功能的界面设计.在Java Web应用程序设计中涉及到上传图片文件功能时,往往都需要对图片文件进行 ...
- 【数仓运维实践】关于GaussDB(DWS)单SQL磁盘空间管控
摘要:本文主要讲解数仓运维中遇到单SQL磁盘空间管控问题的解析和方案. 本文分享自华为云社区<GaussDB(DWS)运维 -- 单SQL磁盘空间管控>,作者: 譡里个檔. [问题描述] ...
- 对偶问题影子价格求解—R实现
table { margin: auto } 线性规划的对偶问题 线性规划对偶问题概述 例1:某厂生产A,B, C三种产品,每种产品的单位利润分别为12,18和15,资源消耗如下表,求总利润最大的生产 ...
- CommunityToolkit.Mvvm系列文章导航
包 CommunityToolkit.Mvvm (又名 MVVM 工具包,以前名为 Microsoft.Toolkit.Mvvm) 是一个现代.快速且模块化的 MVVM 库. 它是 .NET 社区工具 ...
- 【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II)
零钱兑换II 力扣题目链接(opens new window) 给定不同面额的硬币和一个总金额.写出函数来计算可以凑成总金额的硬币组合数.假设每一种面额的硬币有无限个. 示例 1: 输入: amoun ...
- ROS机器人雷达跟随
ROS机器人雷达跟随 初始化 打开一个终端输入: ssh clbrobot@ip # 连接小车 roslaunch clbrobot bringup.launch # 激活主板 开启摄像头 开新终端输 ...
- Function-advanced
函数进阶 1. 函数防抖 在频率触发的情况下 只有等待一定的时间才会触发 执行一次代码 特点 执行之前先清除之前的即将执行操作 保证只有最后一次生效 优化高频执行JS代码操作 提高性能 防抖代码实现 ...
- Spring源码:Bean的生命周期(二)
前言 让我们继续讲解Spring的Bean实例化过程.在上一节中,我们已经讲解了Spring是如何将Bean定义加入到IoC容器中,并使用合并的Bean定义来包装原始的Bean定义.接下来,我们将继续 ...