我需要为柏林噪声自定义随机数生成器吗?
Perlin在伪代码中做了解释:http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
这个教程给了我一个随机数生成函数,用伪代码写的。它会返回一个范围在(-1, 1)之间的浮点数。
function IntNoise(32-bit integer: x)
x = (x<<13) ^ x;
return ( 1.0 - ( (x * (x * x * 15731 + 789221) + 1376312589) & 7fffffff) / 1073741824.0);
end IntNoise function
所以如果这个函数返回的数字在(-1, 1)之间,我是不是可以直接用 random.uniform(-1, 1)
呢?但接下来我遇到了这个问题:
function Noise(x)
.
.
end function
function SmoothNoise_1D(x)
return Noise(x)/2 + Noise(x-1)/4 + Noise(x+1)/4
end function
我猜 Noise(x)
这个函数是用来生成一维噪声的随机数。
我似乎不太明白 x
这个参数是什么。它是一个种子吗?那我不能用 random.uniform(-1, 1)
吗?
1 个回答
在Perlin噪声中使用的噪声函数是一个带种子的随机数生成器。也就是说,每次用相同的参数X调用它时,它都必须返回相同的值。你可以把X想象成在你计算Perlin噪声的区域内某个维度上的一个位置。
如果你能根据给定的参数重置随机数生成器的状态,那么你可以使用Python的随机模块,这样它就能在给定的X下总是返回相同的值。
import random
rand_state = random.Random()
def Noise(x):
rand_state.seed(x)
return rand_state.random()
>>> Noise(1)
0.13436424411240122
>>> Noise(2)
0.9560342718892494
>>> Noise(1)
0.13436424411240122
注意,当第一次和第二次传入1时,Noise返回的是相同的值。而当输入其他值时,它返回的值就不同了。seed的参数可以是Python中任何可哈希的类型。对于你的需求,任何数字类型都可以。
通常在创建Perlin噪声时,会多次调用这个Noise函数,所以你希望它运行得快一点。在我的机器上,执行上面的函数大约需要14微秒。这大约是每秒70000次调用。可能实现IntNoise的伪代码会有更好的性能。实际上,下面这个方法:
MAX_INT = (1<<31)-1
def IntNoise(x):
x = int(x)
x = ((x << 13) & MAX_INT) ^ x
x = ( x * (x * x * 15731 + 789221) + 1376312589 ) & MAX_INT
return 1.0 - x / 1073741824.0
平均每次调用大约需要1.6微秒,速度比上面的Noise快了大约10倍。它返回的值范围是(-1, 1),但可以通过修改最后一行来改变。我不能保证它的分布均匀性,不过一张图胜过千言万语。下面的蓝点来自IntNoise,红点则来自Python的random.uniform函数。
上面的Noise函数可以在你提问中的平滑噪声算法中使用。你在问题中链接的URL对平滑函数的描述比我能说的更好。读完那段话后,看看旁边的1D和2D平滑图,帮助你更好地理解它们的用途。