Estou brincando com o Perlin Noise depois de algum trabalho com a Diamond Square. Segui a implementação de Hugo Elias que, basicamente, faz uma série de funções com x, y como entrada para lançar cada valor de coordenada.
Meu código PHP está aqui :
Eu tenho duas perguntas:
Como uso o algoritmo para gerar um mapa de altura em uma matriz? Eu não o entendi completamente e apenas mudei para o pseudocódigo do PHP, mas fiz a última função (map_perlined) depois de ler em algum lugar que o algoritmo "magicamente" fornece valores de transição para cada ponto x, y dado (aparentemente, sem precisar ler seu valores adjacentes), eu apenas recebo isso ao usar como função aleatóriamt_rand(-100,100)/100;
E isso ao usar o criptográfico: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;
(que, BTW, pode ser implementado "como está" no PHP?):
Então, resumindo, três perguntas:
- Meu código está correto?
- A função aleatória pode ser portada para PHP, conforme descrito no código? Não gera erros, mas os resultados não estão lá.
- Como eu realmente uso o algoritmo?
ATUALIZAR
Ok, criou uma porta PHP do código mostrado no artigo de Gustavson e, como outro codificador disse, apenas gera uma oitava. Existe algum outro site / documento / guia útil sobre como usar isso com os conceitos de múltiplas oitavas, amplitude, frequência etc. para controlar a função de ruído? No artigo de Gustavson, apenas mostra os resultados, não a implementação real do algoritmo, talvez esteja faltando alguma coisa?
ATUALIZAÇÃO 2
@NATHAN
Eu fiz algo como:
$persistence = 0.5;
for ($j = 0; $j < $size; $j++) {
for ($i = 0; $i < $size; $i++) {
for ($o = 0; $o < 8; $o++) {
$frequency = pow(2,$o);
$amplitude = pow($persistence, $o);
$value += SimplexNoise($i*$frequency, $j * $frequency) * $amplitude;
}
//$value = SimplexNoise($i, $j) + 0.5 * SimplexNoise($i, $j) + 0.25 * SimplexNoise($i, $j);
$this->mapArray[$i][$j] = new Cell($value);
E depois de normalizar os valores para 0..1, recebo um mapa de altura bastante monótono, como:
Como proponho o mapa? Talvez o que eu preciso implementar seja a versão 3D com o terceiro valor, uma altura aleatória? Mas, nesse caso, eu precisaria descobrir os valores dos vizinhos, que terminariam com algo como um algoritmo de diamante quadrado, exatamente o que não quero fazer.
ATUALIZAÇÃO 3
Mais trabalho de Perlin. Ainda não encontrei uma maneira de orientar o ruído para meus resultados. Verifique estas oitavas e o resultado final:
Oitava I a IV
Resumido
Cada oitava é praticamente a mesma. Verifique o código:
$persistence = 0.5;
for ($j = 0; $j < $size; $j++) {
for ($i = 0; $i < $size; $i++) {
$value = 0;
for ($o = 0; $o < 4; $o++) {
$frequency = pow(2,$o);
$amplitude = pow($persistence, $o);
$value += improved_noise($i*$frequency, $j*$frequency, 0.5)*$amplitude;
}
$this->map[$i][$j] = new Cell($value);
Os resultados são normalizados. O que você usaria tem uma forte influência no desenvolvimento do ruído? Vejo exemplos em que a alteração da amplitude fornece superfícies suaves ou ásperas, mas mesmo se eu der uma enorme amplitude, vejo pouca diferença.
Respostas:
O que você implementou não é o ruído Perlin. Não sei por que Hugo Elias diz que é, mas ele está confuso. Aqui está a implementação de referência de Ken Perlin. Na verdade, ele não chama nenhum gerador externo de números aleatórios, mas usa uma função de hash embutida para produzir os vetores de gradiente pseudo-aleatórios.
Observe também que o ruído Perlin consiste em apenas uma oitava. Resumir várias oitavas (instâncias em escala da função de ruído), como sugere Hugo Elias, é uma técnica útil, mas não faz parte do ruído da Perlin. O que você consegue com isso é chamado de ruído fractal, às vezes "ruído browniano fractal" (devido à suposta semelhança com o movimento browniano).
Se você quiser entender geometricamente o que o algoritmo está fazendo, tente este documento . Trata-se de um tipo diferente de ruído chamado "ruído simplex", mas também inclui uma explicação do ruído Perlin clássico. Aliás, o ruído simplex também foi inventado por Perlin e deve ser uma melhoria em relação ao ruído clássico, portanto, você pode tentar implementá-lo também se estiver interessado em tocar com funções de ruído.
fonte
Esse é um equívoco comum. O que Hugo Elias chama de ruído "Perlin" é, na verdade, ruído fractal ou rosa. Para entender melhor o que é o ruído Perlin, você pode ler o artigo de Perlin, vinculado na resposta de Nathan Reed, ou documentos libnoise (existe o mesmo erro: o ruído Perlin é o que eles chamam de ruído Gradiente) ou documentos CoherentNoise .
Agora, para realmente responder à sua pergunta: você não obteve o resultado esperado porque a frequência do ruído é muito alta. Suas frequências começam com 1 e aumentam, o que significa que cada pixel no mapa resultante tem um valor aleatório. Para ver a estrutura mais fina do mapa, você precisa "aumentar o zoom" no ruído. Eu realmente não falo PHP, mas acho que o código deve ficar assim:
Ou seja, você "estica" um período de ruído por todo o mapa. Obviamente, você pode usar outros coeficientes - tente diferentes, veja o que acontece.
fonte