[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上.

下次見!

相關文章
相關標籤/搜索