2017-06-03 94 views
1

我發現了兩個教程,解釋了柏林噪聲是如何工作的,但在第一個教程,我發現沒有梯度的理解謎,而在第二個,我發現surflets的神祕面紗。柏林噪聲理解

第一種情況

第一個教程在這裏catlikecoding.com/unity/tutorials/noise所在。起初,作者解釋了價值噪音是完全可以理解的,因爲我們需要做的是繪製一個隨機顏色的網格,然後插入顏色之間。

但是,當涉及到柏林噪聲,我們必須處理的梯度,而不是與單個顏色。起初,我想過gradiens顏色,所以如果我們有兩個梯度,我們要在它們之間進行插值,我們必須採取第一梯度的相應點與第二梯度的各個點插值它。但是如果梯度相同,我們將得到與梯度相同的結果。

在本教程中作者提出另一種說法。如果我們有一個由填充相同梯度的列組成的1d網格,並且每個漸變可以表示爲從0到1的過渡(這裏0是黑色,1是白色)。然後作者說

現在每個條紋具有相同的梯度,除了它們相互抵消 。因此,對於每個t0,其右側的梯度爲 t1 = t0 - 1.讓我們平滑地插值它們。

因此,這意味着,我們有其被表示爲從0到1的轉變的梯度之間進行內插,並且其被表示爲過渡從-1到的梯度爲0。

它意味着每梯度不是從值爲0的位置開始,並且不在值爲1的位置停止。它從-1處開始,在某處結束於2,或者它沒有開始點和結束點。我們只能看到0到1的範圍,我不明白爲什麼它是這樣的。我們從哪裏採用連續漸變的想法?我認爲我們對每個地帶只有從0到1的梯度,這就是所有,不是嗎? continuous gradient

當我問筆者這一切,他回答類似這樣的東西明顯

梯度右邊是一個視覺參考。這是 下一個較大整數的梯度。你是對的,它左轉 。他們都這樣做。

所以T0是,在兩個整數之間的區域的左側 側格點的零梯度。並且t1是在相同區域的右側的格點處的零點的梯度。 梯度噪聲是通過在晶格點之間的這兩個 梯度之間進行插值獲得。是的,這可能會產生 負面結果,最終黑色。這就是爲什麼下一步是 比例和抵消結果。

現在,我覺得這是不可能的,我理解它是如何工作的,所以我只有去相信,更聰明的傢伙後重復。但是希望終歸持久,所以我請求你以某種方式向我解釋。

第二種情況

第二教程這裏eastfarthing.com/blog/2015-04-21-noise/定位和它比前一個複雜得多。 我遇到的唯一問題是,我無法理解一個段落,這

因此,考慮在此之後發生了什麼事情,我們只要專注於G的方向和總是使用 單位長度向量。如果我們將衰減內核的產品和 的梯度在2×2方格之外的所有點上的梯度都設爲0,則這給了我們在該隱含句子中提到的surflet。

我不確定問題出在我的數學還是英語知識上,所以我想請你解釋一下這個問題在簡單的語言中究竟意味着什麼。

下面是一些代碼,到目前爲止我已經寫了,它涉及到第二個案例

import sys 
import random 
import math 
from PyQt4.QtGui import * 
from PyQt4.QtCore import pyqtSlot 

class Example(QWidget): 

    def __init__(self): 
     super(Example, self).__init__() 
     self.gx=1 
     self.gy=0 
     self.lbl=QLabel() 
     self.tlb = None 
     self.image = QImage(512, 512, QImage.Format_RGB32) 
     self.hbox = QHBoxLayout() 
     self.pixmap = QPixmap() 
     self.length = 1 
     self.initUI() 

    def mousePressEvent(self, QMouseEvent): 
     px = QMouseEvent.pos().x() 
     py = QMouseEvent.pos().y() 

     size = self.frameSize() 

     self.gx = px-size.width()/2 
     self.gy = py-size.height()/2 

     h = (self.gx**2+self.gy**2)**0.5 

     self.gx/=h 
     self.gy/=h 

     self.fillImage() 

    def wheelEvent(self,event): 
     self.length+=(event.delta()*0.001) 
     print(self.length) 


    def initUI(self):  
     self.hbox = QHBoxLayout(self) 
     self.pixmap = QPixmap() 
     self.move(300, 200) 
     self.setWindowTitle('Red Rock') 

     self.addedWidget = None 

     self.fillImage() 

     self.setLayout(self.hbox) 

     self.show() 

    def fillImage(self): 

     step = 128 
     for x in range(0, 512, step): 
      for y in range(0, 512, step): 

       rn = random.randrange(0, 360) 
       self.gx = math.cos(math.radians(rn)) 
       self.gy = math.sin(math.radians(rn)) 

       for x1 in range(0, step): 

        t = -1+(x1/step)*2 
        color = (1 - (3 - 2*abs(t))*t**2) 

        for y1 in range(0, step): 

         t1 = -1+(y1/step)*2 
         color1 = (1 - (3 - 2*abs(t1))*t1**2) 
         result = (255/2)+(color * color1 * (t*self.gx+t1*self.gy))*(255/2) 
         self.image.setPixel(x+x1, y+y1, qRgb(result, result, result)) 


     self.pixmap = self.pixmap.fromImage(self.image) 

     if self.lbl == None: 
      self.lbl = QLabel(self) 
     else: 
      self.lbl.setPixmap(self.pixmap) 

     if self.addedWidget == None: 
      self.hbox.addWidget(self.lbl) 
      self.addedWidget = True 

     self.repaint() 
     self.update() 


def main(): 

    app = QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 


if __name__ == '__main__': 
    main()  

回答

0
float Noise::perlin1D(glm::vec3 point, float frequency) 
{ 
    // map the point to the frequency space 
    point *= frequency; 

    // get the base integer the point exists on 
    int i0 = static_cast<int>(floorf(point.x)); 

    // distance from the left integer to the point 
    float t0 = point.x - static_cast<float>(i0); 

    // distance from the right integer to the point 
    float t1 = t0 - 1.f; 

    // make sure the base integer is in the range of the hash function 
    i0 &= hashMask; 

    // get the right integer (already in range of the hash function) 
    int i1 = i0 + 1; 

    // choose a pseudorandom gradient for the left and the right integers 
    float g0 = gradients1D[hash[i0] & gradientsMask1D]; 
    float g1 = gradients1D[hash[i1] & gradientsMask1D]; 

    // take the dot product between our gradients and our distances to 
    // get the influence values. (gradients are more influential the closer they are to the point) 
    float v0 = g0 * t0; 
    float v1 = g1 * t1; 

    // map the point to a smooth curve with first and second derivatives of 0 
    float t = smooth(t0); 

    // interpolate our influence values along the smooth curve 
    return glm::mix(v0, v1, t) * 2.f; 
} 

這裏是有問題的代碼的註釋版本。但改寫爲C++。顯然所有功勞都歸功於catlikecoding

我們已給函數一個點p。假設點p是小數如此,例如,如果p是0.25,則整數的p是0左側和整數p的右爲1。讓我們把這些整數升分別爲r

然後t0爲從p t1爲- [Rp的距離的距離。 t1的距離爲負值,因爲您必須向負方向移動以獲取rp

如果我們繼續討論這個實現的perlin噪聲部分,g0和g1是1維中的僞隨機梯度。由於g0和g1是漂浮物,再一次的梯度可能會令人困惑,但梯度只是一個方向,在一個維度上只能是正值或負值,所以這些梯度是+1和-1。我們在梯度和距離之間取點積,但在一個維度上,這只是乘法。點積的結果是兩個浮點數v0和v1。這些是我們perlin噪聲實現的影響值。最後,我們在這些影響值之間平滑插值以產生平滑的噪聲函數。讓我知道如果這有幫助! This perlin noise explanation對我對此代碼的理解非常有幫助。