基于Processing的noise随机数做出炫酷的图片

可以做出很多类似这种的图片

内容

  • 前置知识
    • 一维noise函数
    • 二维noise函数
  • 制作思路
  • 代码

一维noise函数(img-xsIXsB8G-1646966451620)(1dnose.png)]

x x x的取值范围是负无穷到正无穷,且函数本身关于 y y y轴对称。返回值是一个 [ 0 , 1 ] [0,1] [0,1]之间的数。
需要注意的是, [ 0 , 1 ] [0,1] [0,1]中的每个数出现概率并不相同,其结果类似于正态分布,越接近 0.5 0.5 0.5的数出现概率越大,越接近 0 , 1 0,1 0,1的数出现概率越低。

与random随机数的区别

randow随机数生成的数是均匀分布的,而noise随机数的生成值是接近正态分布的,且noise随机数的值是“确定“的,同一次运行中,调用 10 10 10次noise(233),每次的返回值都是相同的。

一些性质

  • noise生成的随机数看起来比较“自然”。
  • 连续取值时,间隔越小,生成的数起伏越小,间隔越大,生成的数起伏越大。

二维noise函数

在这里插入图片描述


在这里插入图片描述
如果把值当成高度,分的再细一点的话,就能得到类似于自然中群山的样子。

在这里插入图片描述

如果贴一个模型,再加上光影…
实际上,很多游戏中的山都是基于noise生成的。
在这里插入图片描述

noise函数的应用

noise函数得到的随机数,比较“自然”,所以基于它绘制的内容比较有特点。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

那么这张图片是怎么生成的呢?

如果我们在二维noise上画一个圆,并且把得到的值当作一个新的圆的半径:
在这里插入图片描述

然后我们让在noise函数中的圆向右平移,并把得到的圆绘制在另一个图中,并且也向右平移…

最终就能得到这种图了。

代码-变量
float centerX, centerY, offsetX, offsetY, inc, r, rd;
int segNumber;

c e n t e r X , c e n t e r Y centerX,centerY centerX,centerY是在绘制图中,圆的中心坐标
o f f s e t X , o f f s e t Y offsetX, offsetY offsetX,offsetY是在noise函数图中,圆的坐标。
s e g N u m b e r segNumber segNumber把圆分成几个点
i n c inc inc是在noise函数图中圆的半径
r , r d r,rd r,rd是在绘制图中圆的半径

代码-setup部分
void setup() 
{
    size(1920, 1080);
    background(0);
    noFill();
    colorMode(HSB);
    centerX = 0; centerY = height / 2;
    offsetX = offsetY = 0; 
    inc = 0.725; 
    segNumber = 500;
    r = 0; rd = 350;
}
beginShape();
//通过vertex(x,y)函数画几个节点
endShape(CLOSE);

这个函数负责把在两个函数之间绘制的节点依次连接起来,从而形成一个封闭图形。

代码-怎么绘制一个圆

我们知道单位圆方程 x 2 + y 2 = 1 x^2 + y^2=1 x2+y2=1
以及 c o s 2 ( α ) + s i n 2 ( α ) = 1 cos^2(\alpha)+sin^2(\alpha)=1 cos2(α)+sin2(α)=1

我们借助 c o s 2 ( α ) + s i n 2 ( α ) = 1 cos^2(\alpha)+sin^2(\alpha)=1 cos2(α)+sin2(α)=1这个方程,
对于每个点 ( c o s ( α ) , s i n ( α ) ) (cos(\alpha),sin(\alpha)) (cos(α),sin(α)),它们都在 x 2 + y 2 = 1 x^2 + y^2=1 x2+y2=1这个圆上。

所以我们枚举在 [ 0 , 2 π ] [0,2\pi] [0,2π]中枚举 α \alpha α,就得到了所有单位圆中点的坐标。然后我们把所有坐标都乘上一个数 i n c inc inc,就得到了任意半径的圆了。

代码-draw部分
void draw() 
{
    stroke((frameCount * 0.05) % 255, 180, 255, 64);
    beginShape();//画圆
    for(int i = 0; i < segNumber; i++) {
        float angel = TWO_PI * i / segNumber;
        PVector p = new PVector(cos(angel), sin(angel));
        float radius = r + rd * noise(offsetX + p.x * inc, offsetY + p.y * inc);
        p.mult(radius);
        vertex(p.x + centerX, p.y + centerY);
    }
    endShape(CLOSE);
    float offset = 0.00385;//平移
    offsetX += offset; offsetY += offset;
    centerX += 1;
    if(centerX > width) {
        centerX = 0;
        background(0);
    }
}

经过很多次尝试,我发现了最影响图形的的两个参数:

  • i n c inc inc:即noise函数中圆的半径,这个很好理解,在noise中画的圆的大小越大,那么它所得到的值范围就越大,且起伏就越明显,绘制出来的图形棱角就比较多。相反, i n c inc inc值越小,画出来的图形就越"圆润"。
  • o f f s e t offset offset:即在noise函数中每次平移的距离。值越小,noise值变化的就越小,表现出来的结果就是重叠效果越明显;值越大,noise变化就越大,表现出来的结果就是画的圆比较分散。

代码

float centerX, centerY, offsetX, offsetY, inc, r, rd;
int segNumber;

void setup() 
{
    size(1920, 1080);
    background(0);
    noFill();
    colorMode(HSB);
    centerX = 0; centerY = height / 2;
    offsetX = offsetY = 0; 
    inc = 1; 
    segNumber = 500;
    r = 0; rd = 350;
}

void draw() 
{
    stroke((frameCount * 0.05) % 255, 180, 255, 64);
    beginShape();
    for(int i = 0; i < segNumber; i++) {
        float angel = TWO_PI * i / segNumber;
        PVector p = new PVector(cos(angel), sin(angel));
        float radius = r + rd * noise(offsetX + p.x * inc, offsetY + p.y * inc);
        p.mult(radius);
        vertex(p.x + centerX, p.y + centerY);
    }
    endShape(CLOSE);
    float offset = 0.006;
    offsetX += offset; offsetY += offset;
    centerX += 1;
    if(centerX > width) {
        centerX = 0;
        background(0);
    }
}

参考内容:

https://www.bilibili.com/video/BV1BA411i7t6

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值