[MetalKit]20-Using-MetalKit-part-14使用MetalKit14

本系列文章是对 metalkit.org 上面MetalKit内容的全面翻译和学习.c++

MetalKit系统文章目录git


让咱们从第13部分 Part 13继续.使用上次咱们用的playground,咱们今天将学习noise.摘自Wikipedia:github

Noise refers to any random fluctuations of data that makes the perception of an expected signal, difficult. Value noise is a type of noise commonly used as a procedural texture primitive in computer graphics. This method consists of the creation of a lattice of points which are assigned random values. The noise function then returns the interpolated number based on the values of the surrounding lattice points. Multiple octaves of this noise can be generated and then summed together in order to create a form of fractal noise. Noise噪声指任何随机涨落的数据,它使感知指望信号变得困难.Value noise值噪声是一种常常用在计算机图形学中做为程序纹理基元.这种方法由被赋于了随机值的网格点建立而成.接着噪声函数返回基于网格周围点的插值数据.能够生成多个这种类型的噪声并相加来建立一种分形噪声.api

噪声最明显的特征就是随机.由于MSL没有提供随机函数,因此咱们本身建立一个.咱们须要的是 [0,1] 之间的随机数.咱们能够用fract函数来返回一个数的小数部分:less

float random(float2 p) {
    return fract(sin(dot(p, float2(15.79, 81.93)) * 45678.9123));
}
复制代码

noise() 函数将双线性插值一个格子(网格)并返回一个平滑的值.双线性内插容许咱们基于2D网格变换1D随机函数到一个值:dom

float noise(float2 p) {
    float2 i = floor(p);
    float2 f = fract(p);
    f = f * f * (3.0 - 2.0 * f);
    float bottom = mix(random(i + float2(0)), random(i + float2(1.0, 0.0)), f.x);
    float top = mix(random(i + float2(0.0, 1.0)), random(i + float2(1)), f.x);
    float t = mix(bottom, top, f.y);
    return t;
}
复制代码

咱们首先用i来移动格点,并用f作为网格点间的偏移.而后咱们用公式3f^2 - 2f^3计算一个Cubic Hermite Spline,它建立一个S型曲线,值在 [0,1] 之间.下一步咱们沿着网格底部和顶部作内插值,最终内插出两个水平点间的垂线,并获得咱们的最终值做为噪声.函数

下一步咱们建立一个Fractional Brownian Motion微小布朗运行函数调用noise()函数若干次并将结果相加.post

float fbm(float2 uv) {
    float sum = 0;
    float amp = 0.7;
    for(int i = 0; i < 4; ++i)
    {
        sum += noise(uv) * amp;
        uv += uv * 1.2;
        amp *= 0.4;
    }
    return sum;
}
复制代码

经过添加若干(本例中为四)次噪声在不一样幅度(开头解释的那样)的octaves倍频,咱们能够产生一个简单的云状图案.咱们还有一件事要作:在内核中,用下面几行替换distance定义后的全部行:学习

uv = fmod(uv + float2(timer * 0.2, 0), float2(width, height));
float t = fbm( uv * 3 );
output.write(distance < 0 ? float4(float3(t), 1) : float4(0), gid);
复制代码

为了好玩,咱们添加timeruniform来让内容动起来.输出的图像看起来应该像这样:ui

chapter14.gif

它看起来很酷,可是仍然不够真实.为了让它看起来更真实一些,咱们须要学习并使用纹理.若是你感兴趣的话,你能够阅读更多关于 bilinear filtering, 关于value noise 以及关于Fractional Brownian motion的内容.也能够看一个 Cubic Hermit Spline的例子.

源代码source code 已发布在Github上.

下次见!

相关文章
相关标签/搜索