ПрограммированиеФорумОбщее

Реализация процедурных текстур методом Шума Перлина. (Комментарии к статье) (2 стр)

Страницы: 1 2 3 Следующая »
#15
12:12, 27 фев 2004

2All :
простите, господа, а что вы все так всполошились?
статья имхо не стоит того... это вольный перевод Хьюго Элиаса, и btw шум тут маленько кучерявый...
лучше использовать препросчитанные градиенты вместо псевдо-рэндома...
про скорость я молчу...
и напоследок пара ссылок, думаю тогда вы оцените возможности шума по достоинству :

Perlin noise math FAQ
http://www.robo-murito.net/code/perlin-noise-math-faq.html#algorithm

Sky Rendering Techniques
http://www.gamedev.net/community/forums/topic.asp?whichpage=2&pag… opic_id=86024

#16
14:42, 28 фев 2004

to:Alexded
ИМХО для этого надо использовать либо алгоритм удаления шва,
либо зразу генерировать текстуру без шва
e.g http://www.gamedev.ru/download/?id=441  tnx to Mikle

Boo
Если хочеш написать лучше - сделай это , а критиковать каждый может ...
Таких ссылок есть полным полно - но стаття розсчитана на геймдев комюнити среди которых тех людей которые хотят углублятся в математику еденицы , а я пробовал сделать материал доступным для всех...Не знаю удалось ли мне это...

Прошло более 8 месяцев
#17
13:43, 17 ноя 2004

люди а у меня вот алгоритм не работает почему то...потоянно переполнение идет....скажите так вот правильно
n=pow(shl(n,13),n);

Прошло более 2 лет
#18
18:27, 1 дек 2006

to: Misterion
Pascal? Delphi?
Дело в том, что в C "a^b" означает не а в степени b, а побитовое исключающее ИЛИ. В общем я сделал так:

function Noise(x,y:integer):byte;
var p:integer;
begin
  p:=x+y*57;
  p:=not((p shl 13) or p);
  Noise:=round(((1-((p*(p*p*15731+789221)+1376312589) and $7fffffff)/1073741824)+1)*127.5);
end;

В любом случае получился повторяющийся шум, что меня конкретно не устроило.
Легче, по-моему, инициализировать в начале генерации шума 2-мерный массивчик - n-размерности (больше 1000 желательно), заполненный рандомом, а потом делать так:

NoiseArr:array[0..n,0..n] of byte;
...
function Noise(x,y:integer):byte;
begin
  if x>n then x:=x-n*(x div n);
  if y>n then y:=y-n*(y div n);
  Noise:=NoiseArr[x][y];
end;

Все отлично работает.

Прошло более 3 лет
#19
17:58, 11 окт 2010

Скопипастил сурсы и офигел от того какой затилиный оказался шум. Покопался на гугле, но нашел только статью, с которой перевели эту (т.е. ничего полезного)
Разобрался поподробнее и пришел к выводу, что использование составных чисел в псевдорандоме не есть гуд.
Заменил 57 на 97171 и стало счастье)

Было:

_inline float CMyNoise::Noise2D(int x, int y)
{
  int n = x + y * 57;
  n = (n<<13) ^ n;
  return ( 1.0f - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) /
      1073741824.0f);
}

Стало:

_inline float CMyNoise::Noise2D(int x, int y)
{
  __int64 n = x + y * 97171;
  n = (n<<13) ^ n;
  return ( 1.0f - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) /
      1073741824.0f);
}

PS автору спасибо за статью, пригодилась

#20
20:10, 13 янв 2011

Вопрос к автору:

google.ru Ken Perlin noise. Сразу же выдаётся статья Кена Перлина: http://www.noisemachine.com/talk1/14.html
В ней нет никаких частот - только игра с градиентами.

Чем отличается метод в статье от оригинального метода?

#21
21:12, 13 янв 2011

bruzo
> В ней нет никаких частот

это функция turbulance

#22
21:02, 2 фев 2011

спасибо.

Прошло более 6 месяцев
#23
11:53, 2 авг 2011

еще бы ты генерацию 3д шума показал и было бы еще лучше!!!!

и для облаков совершенно необязательно юзать перлин шум

вот тут показан левый соверщенно шум

http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series4/Perlin_noise.php

и облака на нем

...
или шумом перлина называется любой шум генерированный через рандом??

Прошло более 1 года
#24
12:33, 22 янв 2013

      float int_X    = int(x);//целая часть х
      float fractional_X = x - int_X;//дробь от х
//аналогично у
      float int_Y    = int(y);
      float fractional_Y = y - int_Y;

здесь ошибка при отрицательных числах надо так (эта ошибка видна при factor<0)

надо так  есть способ рациональнее (вместо if поставить ? но я так неумею...)
      float int_X;
      if (x>=0)
      {
      int_X    = int(x);
      }else{
      int_X    = int(x)-1;
      }
      float fractional_X = x - int_X;

      float int_Y;
      if (y>=0)
      {
      int_Y    = int(y);
      }else{
      int_Y    = int(y)-1;
      }
    float fractional_Y = y - int_Y;

#25
15:30, 12 апр 2013

Можно подробную реализацию данного класса и OpenGL со всеми вызовами функции данного класса? или это слишком?)

Прошло более 1 года
#26
3:52, 19 окт 2014
_inline float CMyNoise::Noise2D(int x, int y)
{
  int n = x + y * 57;
  n = (n<<13) ^ n;
  return ( 1.0f - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) /
      1073741824.0f);
}

А у меня не работает эта функция. Она должна возвращать псевдо-случайные числа, а возвращает для большинства аргументов константное значение, вот пример:
http://jsfiddle.net/byoybjkw/
Кто знает, в чем подвох?

Xegby, магическая замена 57 на 97171 не помогла. :)

#27
20:35, 17 фев 2015

//здесь можно перевести значения цвета  по какой-то формуле
...
total=fabsf(total);
int res=int(total*255.0f);//приводим цвет к значению 0-255…
return res;

Вообще лучше приводить total к диапазону [-1; 1] или [0; 1]. Для [-1; 1] надо разделить на максимальное значение шума. Максимальное значение вычисляется так:

1f - Mathf.Pow( 0.5f, octaves );

Можно как-то оптимизировать вычисление шума?
У меня шум для массива 512x512 считается 0.25 - 0.3 сек.
Если распараллелить в 4 потока, то 0.14 - 0.15 сек.
Если еще и на fixed point переделать, то 0.8 - 0.13 сек.
Но все равно медленно. Хотелось бы 1024x1024 считать меньше, чем 0.1 сек.

Мой PerlinNosie FastPerlinNoise2D
И с Fixel Point FastPerlinNoise2D

При низкой частоте шума получается, что много раз считаются одни и те же псевдо-рандомное значение, между которыми производится интерполяция.
Надо не вычислить каждый раз заново значение, а вычислять сначала в 4х ключевых точках, а потом интерполировать между ними и записывать в массив. Никто так не делал?

#28
23:02, 17 фев 2015

WISHMASTER35
У тебя ведь тоже не Перлин, так (отсутствие градиентов)?

Работает заметно быстрее, чем например stb_perlin (на C++), где градиенты есть (ну и он 3d).

А так, наверно, разбить на кусочки, хорошо влезающие в L1-кеш, для каждого кусочка сказать:

for( int i = 0; i < octaves; i++ ) {
    for( int y = tile_start_y; y < tile_end_y; y++ ) {
        for( int x = tile_start_x; x < tile_end_x; x++ ) {
// ...

то будет, надо думать, побыстрее. Т. к. внутри можно меньше считать (fy, y0, y1 не меняются, и т. д.).
Ну и для ситуации, когда Mathf.FloorToInt( tile_start_y*freq )==Mathf.FloorToInt( (tile_start_y-1)*freq )&&Mathf.FloorToInt( tile_start_x*freq )==Mathf.FloorToInt( (tile_start_x-1)*freq ) - отдельную ветку, тоже пригодится, пожалуй.

Но это я не проверял, так говорю.

И преобразований int<->float, вроде, можно меньше делать.

#29
2:09, 18 фев 2015

Написал такое:

    public void Compute() {
        System.Array.Clear(texture, 0, texture.Length);
        
        int freq = 1;
        float amp = 1;
        for( int i = 0; i < noise.octaves; i++ ) {
            Compute( noise.scale * freq, noise.offset * freq, amp );
            freq *= 2;
            amp *= 0.5f;
        }

        for( int i = 0; i < texture.Length; i++ ) {
            texture[i] *= noise.invMaxValue;
        }
    }

    private void Compute(float scale, Vector2 offset, float amp) {
        int step = Mathf.CeilToInt( 1f/scale );

        int NX = (int) (offset.x * step); // noise offset
        int NY = (int) (offset.y * step);

        int TX = NX - (Mathf.FloorToInt( offset.x ) * step); // texture offset
        int TY = NY - (Mathf.FloorToInt( offset.y ) * step);

        for( int y = -TY; y < height; y+=step ) {
            for( int x = -TX; x < width; x+=step ) {
                int nx = x + NX;
                int ny = y + NY;

                Compute( x, y, nx, ny, step, amp );
            }
        }
    }

    private void Compute(int x, int y, int nx, int ny, int step, float amp) {
        float v0 = FastPerlinNoise2D.Random( nx,      ny );
        float v1 = FastPerlinNoise2D.Random( nx+step, ny );
        float v2 = FastPerlinNoise2D.Random( nx,      ny+step );
        float v3 = FastPerlinNoise2D.Random( nx+step, ny+step );

        int x0 = Mathf.Max( x, 0 );
        int x1 = Mathf.Min( x+step, width );
        int y0 = Mathf.Max( y, 0 );
        int y1 = Mathf.Min( y+step, height );

        for( int iy = y0; iy < y1; iy++ ) {
            int index = ToIndex( x0, iy );
            for( int ix = x0; ix < x1; ix++, index++ ) {
                float tx = FastPerlinNoise2D.SmoothStep( (float) (ix-x)/step );
                float ty = FastPerlinNoise2D.SmoothStep( (float) (iy-y)/step );

                float a = FastPerlinNoise2D.Lerp( v0, v1, tx );
                float b = FastPerlinNoise2D.Lerp( v2, v3, tx );
                float c = FastPerlinNoise2D.Lerp( a, b, ty );

                texture[index] += c * amp;
            }
        }

    }

Текстура 512x512. Время: 0.13 - 0.15 сек. И это без многопоточности.
Только если бы избавится от SmoothStep и Lerp.
Если бы просто Lerp использовал, то прибавлял бы dx и dy. А из-за SmoothStep интерполяция не линейная.
Можно как-то оптимизировать это место?

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.