julia - 在 Julia 中插入梯度噪声

标签 julia perlin-noise

我正在尝试实现和学习 here 中的代码但我在插值时遇到问题。这是我在 Julia 中实现的代码:

lerp(a, b, w) = a * (1 - w) + b * w

function Noise(x, y)
    n = x + y * 53;
    n = (n << 13) $ n;
    return (1.0 - ( (n * ((n * n * 15731) + 789221) +  1376312589) & 0x7fffffff) / 1073741824.0);
end

function coherentNoise(x,y)
   x₁ = convert(Int64,modf(x)[2])
   y₁ = convert(Int64,modf(y)[2])
   xᵣ = x - x₁
   yᵣ = y - y₁
   q1 = Noise(x₁-1,y₁+1)
   q2 = Noise(x₁+1,y₁+1)
   q3 = Noise(x₁-1,y₁-1)
   q4 = Noise(x₁-1,y₁+1)

   v = lerp(q1,q2,xᵣ)
   v1 = lerp(q3,q4,xᵣ)
   return abs(lerp(v,v1,yᵣ))
   #value = bilinear(q1,q2,q3,q4,x₁,x₁-1,x₁+1,y₁,y₁-1,y₁+1)
   #return abs(value)
end


arr = Array{Float64}(height,width)

for x = 1:height
    for y = 1:width
        nx = x/60
        ny = y/60
        arr[x,y]=coherentNoise(nx,ny)
    end
end

这是结果:

enter image description here

我也尝试使用这个双线性插值函数,但得到的结果更糟糕。

# bilinear interpolation
function bilinear(Q1,Q2,Q3,Q4,x,x1,x2,y,y1,y2)
    R1 = ((x2-x)/(x2-x1))*Q3 + ((x-x1)/(x2-x1))*Q4
    R2 = ((x2-x)/(x2-x1))*Q1 + ((x-x1)/(x2-x1))*Q2
    P = ((y2-y)/(y2-y1))*R1 + ((y-y1)/(y2-y1))*R2
    return P
end

结果:

enter image description here

我不知道是Noise功能有问题还是其他问题。

更新

我使用双线性插值和下一个噪声生成器函数获得了最佳结果:

function coherentNoise(x,y,n::Int64)
    #octa3e
    o = 0.25
    #octave x and y
    x /=n
    y /=n 
    #decimal value
    x₁ = x < 0 ? x : x-o
    y₁ = y < 0 ? y : y-o
    x₂ = x+o
    y₂ = y+o
    #calculate corners data
    q1 = abs(Noise(floor(Int64,x₁),floor(Int64,y₂)))
    q2 = abs(Noise(floor(Int64,x₂),floor(Int64,y₂)))
    q3 = abs(Noise(floor(Int64,x₁),floor(Int64,y₁)))
    q4 = abs(Noise(floor(Int64,x₂),floor(Int64,y₁)))
    #bilenear interpolation

    value = bilinear(q2,q1,q4,q3,x,x₁,x₂,y,y₁,y₂)
    return abs(value)
end

结果:

enter image description here

我认为问题在于我如何选择点来进行双线性插值,不知道如何正确执行。

更新 2:

这是生成图像的代码:

for x = 1:height
    for y = 1:width
        arr[x,y]=coherentNoise(x,y,50)
    end
end

imwrite(convert(Image,arr),"desktop/projects/julia/Noise/test2.png")

更新 3

感谢Dan Getz的解答我得到了更好的输出,但有一些奇怪的“蠕虫”

输出:

enter image description here

最佳答案

如果没有能力测试代码,这应该需要验证。基本上,我认为您对问题出在插值点的选择上的直觉是正确的。这是修复它的尝试(另请参阅评论)。

function coherentNoise(x,y)
   x₁,xᵣ = floor(Int64,x),mod(x,1)
   y₁,yᵣ = floor(Int64,y),mod(y,1)
   q00 = Noise(x₁,y₁)
   q10 = Noise(x₁+1,y₁)
   q01 = Noise(x₁,y₁+1)
   q11 = Noise(x₁+1,y₁+1)

   v0 = lerp(q00,q10,xᵣ)
   v1 = lerp(q01,q11,xᵣ)
   noise = lerp(v0,v1,yᵣ)
   return noise
end

注释:

  • q 重命名为 q00 等,以指示 X(第一个数字)和 Y(第二个数字)的偏移量是哪个角。
  • 相同的 q1q4 已修复。
  • floormod( ,1) 使用而不是 modf 因为它们选择一致的舍入方向(向下),而不管符号如何。<
  • Noise 函数应对其参数进行类型注释以限制为 Int32 值,并且不需要此函数行尾的 ;。这是一个哈希函数,使用 Julia 哈希函数和一个小包装器可以轻松编码相同的效果。

例如:

Noise(x,y) = 1.0-2.0*hash((x,y))/typemax(UInt)

Noise 的一个更具 Julia 风格的直接替代品。

如果您尝试此操作并评论错误,我们可以尝试修复功能。

关于julia - 在 Julia 中插入梯度噪声,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40067227/

相关文章:

perlin-noise - 柏林与。分形与。湍流噪音

algorithm - 包装 2D 柏林噪声

julia - 将文本文件存储为二进制文件以加快读/写速度

julia - 如何识别不同的成员(member)?

multithreading - 将任务添加到特定线程的队列中

performance - 为什么我的 Julia 代码运行速度比 javascript 慢?

c# - Perlin 地形页面不匹配 : elusive bug

opengl - 如何创建分形立方体?

Julia 处理 void 返回类型

c++ - 是什么导致我的 2D Perlin 噪声中出现这些伪像?