Qbasicnews.com

Full Version: Best algorithm for a 2D Perlin Noise ?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
The only good explanations I can find on the web are:

1 - Hugo Elias page:
http://freespace.virgin.net/hugo.elias/m...perlin.htm

2 - a java page, that says, roughly: if you want your prog to make coffee, then call "public class coffee"
http://prografix.games-creators.org/document/129

This last page confirms the prog I have already built to generate fractal landscapes : http://mandelbrot.dazibao.free.fr/Ground/Ground.htm was not that bad, but this technique, relying on bitmaps, cannot be used in a raytracer (far too slow and heavy).

Did someone ever prog something with QB, based on additions and multiplications, that can be used as Perlin (x!,y!), Perlin being a function that can be called at each pixel ?
Check toshi horie's page, http://www.ocf.berkeley.edu/~horie/
he once did Perlin clouds in a QB demo, he must have some code there. If not, tell it to me, i have a copy of the demo somewhere (60K of source, too big to post it here...)
Failed my first try miserably. ;*(

Random noise function gives me overflows. Then a stroke of luck!!!

I used the SIN and Cosine functions to generate noise. ;*)
Well, Toshi's prog seems to be, as usual, a gold mine. But...

It's Screen 13 oriented, that means all the logics of the prog is based on integers, medium size arrays, etc...

Antoni, if you saw my landscapes page, you have seen that I can generate Hi-Res cloud pics as large as 2048x2048...

The function I'd like to have must work with real numbers, which means it must interpolate the discrete values of a "cloud" array to provide Perlin! = F(x!,y!) instead of Perlin% = f(n%,p%)...

I can't think about 2048x2048 polynomial interpolation, I need something more efficient.

Maybe this will end with a Fast Fourier Transform written in pure QB :rotfl:
One idea:
When doing a plasma effect, three linear tables are generated, one for x, one for y and one for time (so the plasma moves) . When drawing the plasma one gets one coefficient for each table, does a simple operation for the three and voilà...the palette index for the color of the point. Maybe you could do the same for hues...
I managed to extract the perlin routines from the FX.bas by Toshi.

Of course, it's super-fast (in the original version), because of all the tricks around integers and direct acess to the memory. But it was quite disappointing from a mathematical point of view.

My project is to re-use the cloud generator I developped, and to add a parabolic interpolation to get a smoothed value for (x!,y!):

1- Round (x!,y!) to (x%,y%), get the Perlin value for (x%,y%)
2- Get the Perlin value of the 8 surrounding points and interpolate parabols along x and y (or directly a paraboloid from the 9 points).

This should be fairly easy to develop, and give correct results. Of course, without XMS or EMS, I need to keep the bitmap principle...
I managed to get perfect tiling clouds just with a slight modification in Qbground.bas...

I'm going to adapt it to arrays now (128x128 max Cry )
This is what I call live programming...
In 1/3 of second (1.8 GHz machine):

Code:
Iter = 7
BumpFactor = 2
CloudWidth% = 2 ^ Iter + 1
CloudHeight% = 2 ^ Iter + 1

DIM Cloud%(CloudWidth%, CloudHeight%)

RANDOMIZE TIMER
T0 = TIMER
' Init the corners
Cloud%(1, 1) = 128
Cloud%(1, CloudHeight%) = 128
Cloud%(CloudWidth%, 1) = 128
Cloud%(CloudWidth%, CloudHeight%) = 128

' Init the edges
FOR Rank% = 1 TO Iter

dx = 2 ^ (Iter - Rank% + 1)
dy = 2 ^ (Iter - Rank% + 1)
Nx% = 2 ^ (Rank% - 1) + 1
Ny% = 2 ^ (Rank% - 1) + 1

FOR kx = 1 TO Nx% - 1
x% = (kx - 1) * dx + 1: y% = 1
Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%)) / 2
zNew% = Bump%(Alt%, Rank%, BumpFactor)
Cloud%(x% + dx / 2, 1) = zNew%
Cloud%(x% + dx / 2, CloudHeight%) = zNew%
NEXT kx

FOR ky = 1 TO Ny% - 1
x% = 1: y% = (ky - 1) * dy + 1
Alt% = (Cloud%(x%, y%) + Cloud%(x%, y% + dy)) / 2
zNew% = Bump%(Alt%, Rank%, BumpFactor)
Cloud%(1, y% + dy / 2) = zNew%
Cloud%(CloudWidth%, y% + dy / 2) = zNew%
NEXT ky

NEXT Rank%


' Fill the clouds
FOR Rank% = 1 TO Iter

dx = 2 ^ (Iter - Rank% + 1): dy = dx
Nx% = 2 ^ (Rank% - 1) + 1: Ny% = Nx%

FOR kx = 1 TO Nx% - 1
FOR ky = 1 TO Ny% - 1
x% = (kx - 1) * dx + 1
y% = (ky - 1) * dy + 1

Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%) + Cloud%(x%, y% + dy) + Cloud%(x% + dx, y% + dy)) / 4
Cloud%(x% + dx / 2, y% + dy / 2) = Bump%(Alt%, Rank%, BumpFactor)
Alt% = (Cloud%(x%, y%) + Cloud%(x% + dx, y%)) / 2
IF y% <> 1 THEN Cloud%(x% + dx / 2, y%) = Bump%(Alt%, Rank%, BumpFactor)
Alt% = (Cloud%(x%, y%) + Cloud%(x%, y% + dy)) / 2
IF x% <> 1 THEN Cloud%(x%, y% + dy / 2) = Bump%(Alt%, Rank%, BumpFactor)
Alt% = (Cloud%(x% + dx, y%) + Cloud%(x% + dx, y% + dy)) / 2
IF (x% + dx) <> CloudWidth% THEN Cloud%(x% + dx, y% + dy / 2) = Bump%(Alt%, Rank%, BumpFactor)
Alt% = (Cloud%(x%, y% + dy) + Cloud%(x% + dx, y% + dy)) / 2
IF (y% + dy) <> CloudHeight% THEN Cloud%(x% + dx / 2, y% + dy) = Bump%(Alt%, Rank%, BumpFactor)

NEXT ky
NEXT kx

NEXT Rank%
dt = TIMER - T0
CLS
PRINT dt

FUNCTION Bump% (Alt%, Rank%, BumpFactor)

ReBump:
dAlt = (RND - .5) / (BumpFactor ^ Rank%) * Alt%
IF Alt% + dAlt < 0 OR Alt% + dAlt > 255 THEN GOTO ReBump
Bump% = INT(Alt% + dAlt)

END FUNCTION
Jark:
You seem to forget in all your programs that QB arrays are dimensioned starting at index 0 unless you specify otherwise.
As you are always using your arrays starting at index 1, you should dimension them as DIM a(1 to 127,1 to 127) or put OPTION BASE 1 at the start of the program.
When you hit the 64 k limit this additional index can be helpful...

Edited:
Ok, forget it, i looked at it twice.

New edit:
It's really fast!
Pages: 1 2