คุณสร้างเสียงเพอร์ลินแบบเรียงต่อกันได้อย่างไร


127

ที่เกี่ยวข้อง:

ฉันต้องการสร้างเสียงเพอร์ลินแบบเรียงต่อกันได้ ฉันทำงานจากฟังก์ชั่นของ Paul Bourke PerlinNoise*()ซึ่งเป็นแบบนี้:

// alpha is the "division factor" (how much to damp subsequent octaves with (usually 2))
// beta is the factor that multiplies your "jump" into the noise (usually 2)
// n is the number of "octaves" to add in
double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
{
   int i;
   double val,sum = 0;
   double p[2],scale = 1;

   p[0] = x;
   p[1] = y;
   for (i=0;i<n;i++) {
      val = noise2(p);
      sum += val / scale;
      scale *= alpha;
      p[0] *= beta;
      p[1] *= beta;
   }
   return(sum);
}

ใช้รหัสเช่น:

real val = PerlinNoise2D( x,y, 2, 2, 12 ) ; // test

return val*val*skyColor + 2*val*(1-val)*gray + (1-val)*(1-val)*cloudColor ;

ให้ท้องฟ้าเหมือน

nontileable

ซึ่งไม่สามารถเรียงต่อกันได้

ค่าพิกเซลคือ 0-> 256 (ความกว้างและความสูง) และพิกเซล (0,0) ใช้ (x, y) = (0,0) และพิกเซล (256,256) ใช้ (x, y) = (1,1)

ฉันจะทำให้เป็นไทล์ได้อย่างไร


14
เพียงแค่ FYI สิ่งที่คุณมีก็คือไม่มีเสียงรบกวนจาก Perlin มันเป็นเสียงเศษส่วน เสียงเพอร์ลินน่าจะเป็นฟังก์ชั่น "noise2" ที่จะสร้างเสียงเศษส่วนคู่
นาธานรีด

คำตอบ:


80

มีสองส่วนในการสร้างเสียง fBm ที่เรียงต่อกันได้อย่างไร้รอยต่อเช่นนี้ ก่อนอื่นคุณต้องทำให้ฟังก์ชั่นเสียง Perlin เป็นแบบเรียงต่อกันได้ นี่คือบางส่วนของรหัส Python สำหรับฟังก์ชั่นลดเสียงรบกวน Perlin ที่ใช้งานได้กับทุกช่วงเวลาสูงสุด 256 (คุณสามารถขยายได้มากเท่าที่คุณต้องการโดยการแก้ไขส่วนแรก):

import random
import math
from PIL import Image

perm = range(256)
random.shuffle(perm)
perm += perm
dirs = [(math.cos(a * 2.0 * math.pi / 256),
         math.sin(a * 2.0 * math.pi / 256))
         for a in range(256)]

def noise(x, y, per):
    def surflet(gridX, gridY):
        distX, distY = abs(x-gridX), abs(y-gridY)
        polyX = 1 - 6*distX**5 + 15*distX**4 - 10*distX**3
        polyY = 1 - 6*distY**5 + 15*distY**4 - 10*distY**3
        hashed = perm[perm[int(gridX)%per] + int(gridY)%per]
        grad = (x-gridX)*dirs[hashed][0] + (y-gridY)*dirs[hashed][1]
        return polyX * polyY * grad
    intX, intY = int(x), int(y)
    return (surflet(intX+0, intY+0) + surflet(intX+1, intY+0) +
            surflet(intX+0, intY+1) + surflet(intX+1, intY+1))

เสียงเพอร์ลินนั้นเกิดจากการรวมกันของ "surflets" เล็ก ๆ น้อย ๆ ซึ่งเป็นผลมาจากการไล่ระดับสีแบบสุ่มและฟังก์ชั่น falloff แบบแยกส่วนได้ สิ่งนี้ให้พื้นที่เป็นบวก (สีเหลือง) และพื้นที่ลบ (สีน้ำเงิน)

เมล็ด

กระดานโต้คลื่นมีขนาดเท่า 2x2 และอยู่กึ่งกลางของจุดขัดแตะจำนวนเต็มดังนั้นค่าของเสียงเพอร์ลินในแต่ละจุดในอวกาศจึงเกิดจากการรวมกระดานโต้คลื่นที่มุมเซลล์ที่มันครอบครอง

ผลบวก

หากคุณกำหนดทิศทางการไล่ระดับสีในบางช่วงเวลาเสียงจะดังขึ้นเองในช่วงเวลาเดียวกัน นี่คือเหตุผลที่รหัสข้างต้นใช้เวลาโมดูโลประสานงานระยะเวลาก่อนที่จะ hashing มันผ่านตารางการเปลี่ยนแปลง

ขั้นตอนอื่นคือเมื่อรวมผลอ็อกเทฟคุณจะต้องการปรับช่วงเวลาด้วยความถี่ของอ็อกเทฟ โดยพื้นฐานแล้วคุณจะต้องการให้แต่ละอ็อกเทฟแต่ละภาพเรียงภาพทั้งหมดเพียงครั้งเดียวแทนที่จะเป็นหลาย ๆ ครั้ง:

def fBm(x, y, per, octs):
    val = 0
    for o in range(octs):
        val += 0.5**o * noise(x*2**o, y*2**o, per*2**o)
    return val

นำมารวมกันและคุณจะได้รับสิ่งนี้:

size, freq, octs, data = 128, 1/32.0, 5, []
for y in range(size):
    for x in range(size):
        data.append(fBm(x*freq, y*freq, int(size*freq), octs))
im = Image.new("L", (size, size))
im.putdata(data, 128, 128)
im.save("noise.png")

เสียง fBm ที่ต่อเนื่องได้

อย่างที่คุณเห็นนี่มันจะเรียงต่อกันอย่างแท้จริง:

fBm เสียง, กระเบื้อง

ด้วยการปรับแต่งขนาดเล็กและการทำแผนที่สีนี่คือภาพเมฆที่เรียงต่อกัน 2x2:

เมฆ!

หวังว่านี่จะช่วยได้!


3
ฉันไม่ใช่ผู้ชายงูใหญ่ดังนั้นฉันถามแล้วx*2**oแปลงเป็น C ได้อย่างไร มันคือx*pow(2,o)หรือpow(x*2,o)?
idev

7
x*pow(2, o)เนื่องจากการยกกำลังมีความสำคัญมากกว่าการคูณ
John Calsbeek

1
ใครสามารถแปลงสิ่งนี้เป็น C ได้? ฉันมีปัญหามากมายในการทำความเข้าใจโค้ดนี้เนื่องจากฉันไม่เคยทำอะไรกับงูหลามเลย เช่นaค่าคืออะไร และฉันไม่แน่ใจว่าฟังก์ชั่นแปลงเป็น C ... ฉันได้เส้นตรงในเอาต์พุตเท่านั้น
idev

1
นี่เป็นทางออกที่ดีที่สุดอย่างแน่นอนตราบใดที่คุณไม่ต้องกังวลกับเสียงรบกวนที่เกิดขึ้นกับรูปทรงของกระเบื้อง ตัวอย่างเช่นสิ่งนี้ไม่อนุญาตให้มีการหมุนโดยพลการ แต่ถ้าคุณไม่ต้องการสิ่งใดสิ่งนี้นี่คือคำตอบที่ดีที่สุด
John Calsbeek

1
หมายเหตุ: หากคุณต้องการสร้างขนาดอื่น ๆ กว่า 128 im.putdata(data, 128, 128)ไม่เปลี่ยนค่าตัวเลขในบรรทัด (สำหรับผู้ที่ไม่คุ้นเคยกับ python หรือ PIL: หมายถึงการปรับขนาดและการชดเชยไม่ใช่ขนาดภาพ)
Antti Kissaniemi

87

นี่เป็นวิธีที่ค่อนข้างฉลาดที่ใช้เสียง 4D Perlin

โดยทั่วไปแผนที่พิกัด X ของพิกเซลของคุณไปยังวงกลม 2D และพิกัด Y ของพิกเซลของคุณไปยังวงกลม 2D ที่สองและวางทั้งสองวงกลมมุมฉากซึ่งกันและกันในพื้นที่ 4D พื้นผิวที่เกิดขึ้นนั้นสามารถเรียงต่อกันได้ไม่มีการบิดเบือนที่ชัดเจนและไม่ทำซ้ำในลักษณะที่พื้นผิวที่ทำมิเรอร์

รหัสการคัดลอกวางจากบทความ:

for x=0,bufferwidth-1,1 do
    for y=0,bufferheight-1,1 do
        local s=x/bufferwidth
        local t=y/bufferheight
        local dx=x2-x1
        local dy=y2-y1

        local nx=x1+cos(s*2*pi)*dx/(2*pi)
        local ny=y1+cos(t*2*pi)*dy/(2*pi)
        local nz=x1+sin(s*2*pi)*dx/(2*pi)
        local nw=y1+sin(t*2*pi)*dy/(2*pi)

        buffer:set(x,y,Noise4D(nx,ny,nz,nw))
    end
end

3
นี่คือคำตอบที่ถูกต้องอย่างแน่นอน เพิ่มมิติเป็นกลอุบายนักคณิตศาสตร์เก่า Olinde Rodrigues docet (Sir WR Hamilton docet เหมือนกัน แต่น้อยกว่าเล็กน้อย)
FxIII

@FxIII คุณรู้ไหมว่าควรใช้ Noise4D () นี้อย่างไร ฉันต้องการลองสิ่งนี้ แต่ฉันไม่มีเงื่อนงำว่า Noise4D นี้ควรทำงานได้อย่างไร
idev

4
คุณสามารถใช้ฟังก์ชั่นลดเสียงรบกวน 4D เสียงรบกวน Simplex จะเป็นคำแนะนำของฉัน webstaff.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
John Calsbeek

2
ขอบคุณ john! มันทำงานได้หวาน! ไม่มีใครพูดถึงมัน แต่: x1, y1, x2, y2 ดูเหมือนว่าจะเป็นการปรับขนาดระยะทางที่ใหญ่ขึ้น ถ้าสิ่งนี้ช่วยทุกคน
idev

5
โปรดทราบว่านี่เทียบเท่ากับทอพอโลยีคำตอบของ bobobobo: การทำแผนที่ของคุณฝัง 2-torus ไว้ในℝ⁴ซึ่งเป็นไปได้โดยไม่มีการบิดเบือนเมตริกที่คุณได้รับเมื่อฝังลงในℝ³
leftaroundabout

22

โอเคเข้าใจแล้ว. คำตอบคือเดินในพรูในเสียง 3 มิติสร้างพื้นผิว 2D จากมัน

พรูห่อ 2 dirs

รหัส:

Color Sky( double x, double y, double z )
{
  // Calling PerlinNoise3( x,y,z ),
  // x, y, z _Must be_ between 0 and 1
  // for this to tile correctly
  double c=4, a=1; // torus parameters (controlling size)
  double xt = (c+a*cos(2*PI*y))*cos(2*PI*x);
  double yt = (c+a*cos(2*PI*y))*sin(2*PI*x);
  double zt = a*sin(2*PI*y);
  double val = PerlinNoise3D( xt,yt,zt, 1.5, 2, 12 ) ; // torus

  return val*val*cloudWhite + 2*val*(1-val)*gray + (1-val)*(1-val)*skyBlue ;
}

ผล:

เมื่อ:

ท้องฟ้าที่สงบ

และปูกระเบื้อง:

แสดงกระเบื้อง


6
มันใช้งานได้ แต่ดูเหมือนว่าคุณจะได้รับการบิดเบือนเนื่องจากความโค้งของพรู
นาธานรีด

1
คุณสามารถโมดูโลตำแหน่งได้ แต่ฉันชอบคำตอบที่สร้างสรรค์ / ยอดเยี่ยมสำหรับคำถามนี้ วิธีที่แตกต่างมากมายในการทำสิ่งเดียวกัน

ฉันสังเกตว่าคุณไม่ต้องการใช้ค่า 0-1 แต่สำหรับ 0-0.9999 ... ค่า! ดังนั้นคุณจะใช้: x / ความกว้าง, y / ความสูง ฯลฯ มิฉะนั้นตะเข็บไม่ตรงกัน (ทำให้ขอบตรงข้ามพิกเซลเดียวกันแน่นอน) ดูเหมือนว่าฟังก์ชั่น PerlinNoise3D () ต้องการการหนีบสำหรับค่าผลลัพธ์เช่นกันหรือค่าพิกเซลบางค่าล้น
idev

@ นาธานคุณรู้วิธีแก้ไขความผิดเพี้ยนหรือไม่
idev

2
@idev ฉันเชื่อว่าวิธีแก้ไขความผิดเพี้ยนคือใช้วิธี 4D ในคำตอบอันดับต้น ๆ ของคำถามนี้ ;)
Nathan Reed

16

วิธีง่าย ๆ อย่างหนึ่งที่ฉันสามารถนึกได้ก็คือการเอาท์พุทของฟังก์ชั่นรบกวนและกระจก / พลิกให้เป็นภาพที่มีขนาดใหญ่เป็นสองเท่า เป็นการยากที่จะอธิบายดังนั้นนี่คือภาพ: ป้อนคำอธิบายรูปภาพที่นี่

ในกรณีนี้มันค่อนข้างชัดเจนว่าคุณทำอะไรเมื่อดูที่นี้ ฉันคิดได้สองวิธีในการ (อาจ :-)) แก้ไขสิ่งนี้:

  1. คุณสามารถถ่ายภาพที่มีขนาดใหญ่ขึ้นจากนั้นก็จะสร้างจุดรบกวนบนด้านบนได้ แต่ (และฉันไม่แน่ใจว่าเป็นไปได้หรือไม่) มุ่งเน้นไปที่ตรงกลาง (เพื่อให้ขอบคงเดิม) มันสามารถเพิ่มความแตกต่างเล็กน้อยที่จะทำให้สมองของคุณคิดว่าไม่ใช่แค่ภาพสะท้อน

  2. (ฉันยังไม่แน่ใจว่าเป็นไปได้หรือไม่) คุณสามารถลองเล่นซอกับอินพุตของฟังก์ชั่นลดจุดรบกวนเพื่อสร้างภาพเริ่มต้นที่แตกต่างกัน คุณต้องทำสิ่งนี้ด้วยการลองผิดลองถูก แต่มองหาฟีเจอร์ที่ดึงดูดสายตาคุณเมื่อคุณเรียงภาพ / มิเรอร์แล้วลองแล้วทำให้มันไม่สร้าง

หวังว่านี่จะช่วยได้


3
ดีมาก แต่สมมาตรเกินไป!
bobobobo

1
@bobobobo นั่นคือสิ่งที่ฉันคิดว่าขั้นตอนอื่น ๆ จะบรรเทา ดังนั้นคุณสามารถสร้าง "ฐาน" โดยใช้วิธีนี้แล้วเพิ่มรายละเอียดเพิ่มเติมเพื่อทำให้ดูเหมือนว่าไม่ใช่มิเรอร์
Richard Marskell - Drackir

คุณเริ่มได้รูปแบบแปลก ๆ เมื่อคุณทำสิ่งนี้ โดยเฉพาะอันนี้มีลักษณะเหมือนผีเสื้อ ทางออกที่ง่ายแม้ว่า
notlesh

นี่เป็นวิธีแรกของฉันเช่นกัน แต่มันมีปัญหามองเห็นได้ที่นี่: dl.dropbox.com/u/6620757/noise_seam.png เมื่อคุณข้ามเขตแดนพลิกคุณทำให้เกิดการแยกเสียงรบกวนในฟังก์ชั่นเสียงโดยทันทีในการเปลี่ยนความลาดชันของ ฟังก์ชัน แม้ว่าคุณจะใช้ฟังก์ชั่นสัญญาณรบกวนที่สองที่ด้านบนซึ่งอาจยังสามารถมองเห็นได้ในผลลัพธ์
Jherico

ความคิดที่ดี. ซึ่งสามารถทำได้อย่างง่ายดายใน Pixel Shader ใช้คลื่นสามเหลี่ยมฟังก์ชั่น:tex2d(abs(abs(uv.x)%2.0-1.0), abs(abs(uv.y)%2.0-1.0))
tigrou

10

รุ่นแรกของคำตอบนี้ผิดฉันได้อัปเดตแล้ว

วิธีที่ผมใช้ประสบความสำเร็จคือทำให้เสียงโดเมนกระเบื้อง กล่าวอีกนัยหนึ่งทำให้noise2()ฟังก์ชันพื้นฐานของคุณเป็นระยะ ถ้าnoise2()เป็นระยะและเป็นจำนวนเต็มทำให้เกิดเสียงจะมีช่วงเวลาเดียวกับที่betanoise2()

เราจะทำให้noise2()เป็นระยะได้อย่างไร ในการใช้งานส่วนใหญ่ฟังก์ชั่นนี้ใช้เสียงขัดแตะบางชนิด นั่นคือมันจะได้รับตัวเลขสุ่มที่พิกัดจำนวนเต็มและสอดแทรกพวกมัน ตัวอย่างเช่น:

function InterpolatedNoise_1D(float x)

  integer_X    = int(x)
  fractional_X = x - integer_X

  v1 = SmoothedNoise1(integer_X)
  v2 = SmoothedNoise1(integer_X + 1)

  return Interpolate(v1 , v2 , fractional_X)

end function

ฟังก์ชันนี้สามารถแก้ไขได้เล็กน้อยเพื่อให้เป็นงวดกับช่วงจำนวนเต็ม เพียงเพิ่มหนึ่งบรรทัด:

integer_X = integer_X % Period

ก่อนที่จะคำนวณและv1 v2ด้วยวิธีนี้ค่าที่พิกัดจำนวนเต็มจะทำซ้ำทุกหน่วยของระยะเวลาและการแก้ไขจะทำให้แน่ใจว่าฟังก์ชันที่ได้จะเป็นไปอย่างราบรื่น

อย่างไรก็ตามโปรดทราบว่าวิธีนี้ใช้ได้เฉพาะกับช่วงเวลาที่มีค่ามากกว่า 1 เท่านั้นดังนั้นหากต้องการใช้สิ่งนี้ในการสร้างพื้นผิวที่ไร้รอยต่อคุณจะต้องลองสี่เหลี่ยมจตุรัส x เป็นระยะเวลาไม่ใช่ 1x1


แต่คุณจะสร้างnoise2เป็นงวดได้อย่างไร (ด้วยช่วงเวลาสั้น ๆ เช่น 1 หน่วย) ฉันคิดว่านั่นคือคำถามที่ถามในท้ายที่สุด สัญญาณรบกวน Perlin มาตรฐานเป็นระยะโดยมีคาบ 256 แต่ละแกน แต่คุณต้องการเสียงรบกวนที่ปรับเปลี่ยนในช่วงเวลาที่สั้น
นาธานรีด

@Nathan Reed ถ้าคุณโทรnoise2ตามที่แนะนำคุณจะได้ผลลัพธ์เป็นระยะ ๆ ไม่ว่าจะเป็นฟังก์ชันนั้นเป็นระยะหรือไม่ก็ตาม เพราะข้อโต้แย้งล้อมรอบทุก 1 หน่วย
ไม่เป็นไร

1
แต่คุณจะได้ตะเข็บที่เส้นกริดใช่ไหม? เนื่องจากไม่มีการรับประกันว่า noise2 (0, 0.999) เป็นสิ่งที่อยู่ใกล้กับ noise2 (0, 0) เว้นแต่ว่าฉันจะพลาดอะไรบางอย่างไป
Nathan Reed

1
@ นาธานรีดนั่นเป็นจุดที่ดี อันที่จริงฉันเพิ่งตรวจสอบรหัสเดิมของฉันอีกครั้งและปรากฎว่าฉันผิด ฉันจะแก้ไขคำตอบทันที
ไม่เป็นไร

ที่ดี! นี่เป็นคำตอบที่ดีจริงๆ +1 :)
นาธานรีด

6

อีกทางเลือกหนึ่งคือการสร้างเสียงรบกวนโดยใช้ไลบรารี libnoise คุณสามารถสร้างเสียงรบกวนในพื้นที่ทางทฤษฎีที่ไม่มีที่สิ้นสุดอย่างราบรื่น

ดูที่ต่อไปนี้: http://libnoise.sourceforge.net/tutorials/tutorial3.html#tile

นอกจากนี้ยังมีพอร์ต XNA ด้านบนที่: http://bigblackblock.com/tools/libnoisexna

หากคุณลงเอยด้วยการใช้พอร์ต XNA คุณสามารถทำสิ่งนี้ได้:

Perlin perlin = new Perlin();
perlin.Frequency = 0.5f;                //height
perlin.Lacunarity = 2f;                 //frequency increase between octaves
perlin.OctaveCount = 5;                 //Number of passes
perlin.Persistence = 0.45f;             //
perlin.Quality = QualityMode.High;
perlin.Seed = 8;

//Create our 2d map
Noise2D _map = new Noise2D(CHUNKSIZE_WIDTH, CHUNKSIZE_HEIGHT, perlin);

//Get a section
_map.GeneratePlanar(left, right, top, down);

GeneratePlanar เป็นฟังก์ชั่นการโทรเพื่อรับหัวข้อในแต่ละทิศทางที่จะเชื่อมต่ออย่างราบรื่นกับพื้นผิวที่เหลือ

แน่นอนว่าวิธีนี้มีค่าใช้จ่ายสูงกว่าการมีพื้นผิวเดียวที่สามารถใช้ได้กับหลายพื้นผิว หากคุณกำลังมองหาการสร้างพื้นผิวแบบสุ่มขึ้นมาได้สิ่งนี้อาจเป็นสิ่งที่คุณสนใจ


6

แม้ว่าจะมีคำตอบบางส่วนที่จะใช้ได้ แต่ส่วนใหญ่มีความซับซ้อนช้าและมีปัญหา

สิ่งที่คุณต้องทำคือใช้ฟังก์ชั่นสร้างเสียงรบกวนเป็นระยะ แค่นั้นแหละ!

การดำเนินงานที่ดีเยี่ยมโดเมนสาธารณะบนพื้นฐานของ "ขั้นสูง" อัลกอริทึมเสียง Perlin สามารถพบได้ที่นี่ ฟังก์ชั่นที่คุณต้องการคือ pnoise2 รหัสนี้เขียนขึ้นโดย Stefan Gustavson ซึ่งได้แสดงความคิดเห็นที่ชัดเจนเกี่ยวกับปัญหานี้และวิธีการที่คนอื่นใช้วิธีการที่ผิด ฟังกุสตาฟสันเขารู้ว่าเขากำลังพูดถึงอะไร

เกี่ยวกับการคาดการณ์ทรงกลมต่าง ๆ ที่บางคนแนะนำ: เอาล่ะพวกมันทำงานในสาระสำคัญ (ช้าๆ) แต่พวกมันยังผลิตพื้นผิว 2D ที่เป็นทรงกลมแบนเพื่อที่ขอบจะควบแน่นมากขึ้น แน่นอนถ้าคุณตั้งใจให้พื้นผิว 2D ของคุณถูกฉายบนทรงกลมนั่นเป็นวิธีที่จะไป แต่นั่นไม่ใช่สิ่งที่ถูกถาม


4

นี่เป็นวิธีที่ง่ายกว่ามากในการทำเสียงกระเบื้อง:

ปูกระเบื้อง perlin noise จากรหัส shadertoy

คุณใช้การพันแบบแยกส่วนสำหรับแต่ละสเกลของเสียง สิ่งเหล่านี้พอดีกับขอบของพื้นที่ไม่ว่าคุณจะใช้สเกลความถี่ใดก็ตาม ดังนั้นคุณจะต้องใช้เสียง 2D ปกติซึ่งเร็วกว่ามาก นี่คือรหัส WebGL สดซึ่งสามารถดูได้ที่ ShaderToy: https://www.shadertoy.com/view/4dlGW2

ฟังก์ชันสามอันดับแรกทำงานทั้งหมดและ fBM ผ่านเวกเตอร์ x / y ในช่วง 0.0 ถึง 1.0

// Tileable noise, for creating useful textures. By David Hoskins, Sept. 2013.
// It can be extrapolated to other types of randomised texture.

#define SHOW_TILING
#define TILES 2.0

//----------------------------------------------------------------------------------------
float Hash(in vec2 p, in float scale)
{
    // This is tiling part, adjusts with the scale...
    p = mod(p, scale);
    return fract(sin(dot(p, vec2(35.6898, 24.3563))) * 353753.373453);
}

//----------------------------------------------------------------------------------------
float Noise(in vec2 x, in float scale )
{
    x *= scale;

    vec2 p = floor(x);
    vec2 f = fract(x);
    f = f*f*(3.0-2.0*f);
    //f = (1.0-cos(f*3.1415927)) * .5;
    float res = mix(mix(Hash(p,                  scale),
        Hash(p + vec2(1.0, 0.0), scale), f.x),
        mix(Hash(p + vec2(0.0, 1.0), scale),
        Hash(p + vec2(1.0, 1.0), scale), f.x), f.y);
    return res;
}

//----------------------------------------------------------------------------------------
float fBm(in vec2 p)
{
    float f = 0.4;
    // Change starting scale to any integer value...
    float scale = 14.0;
    float amp = 0.55;
    for (int i = 0; i < 8; i++)
    {
        f += Noise(p, scale) * amp;
        amp *= -.65;
        // Scale must be multiplied by an integer value...
        scale *= 2.0;
    }
    return f;
}

//----------------------------------------------------------------------------------------
void main(void)
{
    vec2 uv = gl_FragCoord.xy / iResolution.xy;

#ifdef SHOW_TILING
    uv *= TILES;
#endif

    // Do the noise cloud (fractal Brownian motion)
    float bri = fBm(uv);

    bri = min(bri * bri, 1.0); // ...cranked up the contrast for no reason.
    vec3 col = vec3(bri);

#ifdef SHOW_TILING
    vec2 pixel = (TILES / iResolution.xy);
    // Flash borders...
    if (uv.x > pixel.x && uv.y > pixel.y                                        // Not first pixel
    && (fract(uv.x) < pixel.x || fract(uv.y) < pixel.y) // Is it on a border?
    && mod(iGlobalTime-2.0, 4.0) < 2.0)                 // Flash every 2 seconds
    {
        col = vec3(1.0, 1.0, 0.0);
    }
#endif
    gl_FragColor = vec4(col,1.0);
}

1
ลิงค์รูปภาพของคุณเสียชีวิต ฉันเดาได้ดีที่สุดและแทนที่ด้วยภาพหน้าจอของผลลัพธ์จากโค้ด shadertoy ที่คุณโพสต์ หากไม่ถูกต้องโปรดอัปโหลดรูปภาพที่คุณต้องการโดยตรงไปยังเซิร์ฟเวอร์ Stack Exchange
Pikalek

3

ฉันมีผลลัพธ์ที่ไม่เลวร้ายสอดแทรกอยู่ใกล้กับขอบของแผ่นกระเบื้อง (ขอบห่อ) แต่ขึ้นอยู่กับเอฟเฟกต์ที่คุณพยายามจะทำและพารามิเตอร์เสียงรบกวน ใช้งานได้ดีสำหรับเสียงที่ค่อนข้างพร่ามัวไม่ค่อยดีนักกับ spikey / fine-grained


0

ฉันกำลังตรวจสอบหัวข้อนี้เพื่อค้นหาคำตอบของปัญหาที่คล้ายกันจากนั้นฉันได้โซลูชันที่สะอาดและกะทัดรัดจากผู้พัฒนาโค้ดไพ ธ อนนี้เพื่อสร้างเสียงเศษส่วนจากเสียงเพอร์ลิน / ซิมเพล็กซ์ รหัสที่อัปเดตมีให้ในปัญหานี้ (ปิด)และสามารถดำเนินการต่อในการตั้งค่าการไล่ระดับสีสำหรับด้านขวาของ "ตัวสร้าง" เท่ากับที่อยู่ทางด้านซ้าย (และเหมือนกันสำหรับด้านบนและด้านล่าง) เช่นใน

# Gradients
angles = 2*np.pi*np.random.rand(res[0]+1, res[1]+1)
gradients = np.dstack((np.cos(angles), np.sin(angles)))
# Make the noise tileable
gradients[-1,:] = gradients[0,:]
gradients[:,-1] = gradients[:,0]

ดูเหมือนว่าเป็นโซลูชันที่หรูหราและสะอาดฉันหลีกเลี่ยงการคัดลอกรหัสทั้งหมดที่นี่ (เนื่องจากไม่ใช่โซลูชันของฉันเอง) แต่มีลิงก์ที่ให้ไว้ด้านบน หวังว่าสิ่งนี้จะเป็นประโยชน์กับคนที่ต้องการสร้างภาพเศษส่วน 2 มิติแบบเศษกระเบื้องที่เป็นรูปเหมือนที่ฉันต้องการนี้โดยปราศจากสิ่งประดิษฐ์หรือการบิดเบือน

ภูมิประเทศเศษส่วนแบบต่อเนื่อง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.