griffenjam 193 Report post Posted November 17, 2003 Right now I am using perlin noise to generate clouds but it takes forever to generate them, is this common or am I doing something wrong? Do you generate your noise everytime your app starts? 0 Share this post Link to post Share on other sites

Ilici 862 Report post Posted November 17, 2003 quote:Original post by griffenjam Right now I am using perlin noise to generate clouds but it takes forever to generate them, is this common or am I doing something wrong?Do you generate your noise everytime your app starts? how long?i generate a 1024x1024 texuture with exponential clouds + alpha in aboug 1.5s with a rip of Ken Perlins original code. at the loading i generate 7 1024x1024 texutres for my clouds for different weathers and i interpolate them. post your code here so we can see where is the bottleneck. 0 Share this post Link to post Share on other sites

griffenjam 193 Report post Posted November 17, 2003 This is my perlin noise code.float CPerlin_Parent::Noise2d(int x, int y){ long int n = x + y * 57; n = (n<<13) ^ n; float ret = (float)( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff ) / 1073741824.0); return ret;}float CPerlin_Parent::SmoothNoise2d(int x, int y){ float corners = ( Noise2d(x-1, y-1) + Noise2d(x+1, y-1) + Noise2d(x-1, y+1) + Noise2d(x+1, y+1) ) / 16.0f; float sides = ( Noise2d(x-1, y) +Noise2d(x+1, y) + Noise2d(x, y-1) + Noise2d(x, y+1) ) / 8.0f; float center = Noise2d(x, y) / 4.0f; return corners + sides + center;}float CPerlin_Parent::Interpolate(float x, float y, float a){ float fac1 = (float) (3*pow((1-a), (double)2) - 2*pow((1-a) ,(double)3)); float fac2 = (float) (3*pow(a,2) - 2*pow(a,3)); return x*fac1 + y*fac2; //add the weighted factors}float CPerlin_Parent::GetValue(float x, float y) { int Xint = (int)x; int Yint = (int)y; float Xfrac = x - Xint; float Yfrac = y - Yint; float x0y0 = SmoothNoise2d(Xint, Yint); //find the noise values of the four corners float x1y0 = SmoothNoise2d(Xint+1, Yint); float x0y1 = SmoothNoise2d(Xint, Yint+1); float x1y1 = SmoothNoise2d(Xint+1, Yint+1); //interpolate between those values according to the x and y fractions float v1 = Interpolate(x0y0, x1y0, Xfrac); //interpolate in x direction (y) float v2 = Interpolate(x0y1, x1y1, Xfrac); //interpolate in x direction (y+1) float fin = Interpolate(v1, v2, Yfrac); //interpolate in y direction return fin;}float CPerlin_Parent::Cosine_Interpolation(float a, float b, float x){ double ft = (x+1) * 3.1415927; double f = (1 - cos(ft)) * 0.5; return (float)a*(1-f) + (float)b*f;}float CPerlin_Parent::Cosine_Interpolate2D(float x, float y, int i){ int integer_X = (int)x; float fractional_X = x - integer_X; int integer_Y = (int)y; float fractional_Y = y - integer_Y; float v1 = SmoothNoise2d(integer_X, integer_Y); float v2 = SmoothNoise2d(integer_X + 1, integer_Y); float v3 = SmoothNoise2d(integer_X, integer_Y + 1); float v4 = SmoothNoise2d(integer_X + 1, integer_Y + 1); float i1 = Cosine_Interpolation(v1 , v2 , fractional_X); float i2 = Cosine_Interpolation(v3 , v4 , fractional_X); return Cosine_Interpolation(i1 , i2 , fractional_Y);}float CPerlin_Parent:erlinNoise2D(float x, float y){ float total = 0; fFreq = 1; float fPersistance = 1.0f; //The "weight" each octave will have for(int i=0; i { total += GetValue((x/64.0f)*fFreq, (y/64.0f)*fFreq) * fPersistance; fFreq *= 2; fPersistance *= fPersistanceMod; }// total = total*0.5 + 0.5; if(total < 0) total = -total; if(total > 1.0f) total = 1.0f; return total;} I would post my cloud code as well, but everything thaty uses perlin noise takes forever*, including landscape. *forever is 5 minutes for a 512x512 texture. 0 Share this post Link to post Share on other sites

Eelco 301 Report post Posted November 17, 2003 thats indeed long. try inlineing all those functions. or the inner loop ones at least. 0 Share this post Link to post Share on other sites

Chaucer 122 Report post Posted November 17, 2003 You need to try a different approach...Instead of using the perlinnoise function that does all the smoothing and everything, just use your basic noise function. That will give you a texture that looks like static on a tv screen. Then render this to a larger texture using bilinear filtering. This will smooth it out faster for you and you can still get the same effect by starting with a small noise texture(16x16 or 32x32) and rendering it to your final sized texture(1024x1024 prob.). Then move up a size and do the same. Then combine them all.Like this:1)16x16 render to 1024 w/ bilinear filtering32x32 render to 1024 w/ bilinear filtering64x64 render to 1024 w/ bilinear filtering128x128 render to 1024 w/ bilinear filtering 256x256 render to 1024 w/ bilinear filtering512x512 render to 1024 w/ bilinear filtering2)combine all textures3)subtract a value using the texturestagestate d3dtop_subtract (ibelieve) and subtract a gray texture from it in order to get more clear areas. 0 Share this post Link to post Share on other sites

outRider 852 Report post Posted November 17, 2003 Perlin Noise can get a little expensive, especially since you're doing lots of dividing, float-int conversion, and sampling. The usual optimizations are to use fixed point and use the old scaling-the-number-range tricks to get rid of the divides in the inner loops, that way you're working strictly with integers and without dividing a whole lot.Or do it using the method above with hardware. There was a thread about this a while back that I posted in (did you start it?) about HW PN.------------- outRider - [edited by - outRider on November 17, 2003 12:22:31 AM] 0 Share this post Link to post Share on other sites

Guest Anonymous Poster Report post Posted November 19, 2003 Some improvement techniques : 1/ as Eelco said, inline some functions : Noise2d() and Interpolate() are good candidates.2/ do not use "double". When you write "1.0" or "1073741824.0" your *are* using double. The compiler will not optimize this. Instead of this you can use "1.0f" and "1073741824.0f" - these are floats (32 bits). They are *a lot* faster. 3/ starting with VC.NET a lot of floating point functions are SSE-enabled (I d not have the list here ; at least I''m sure it''s in the last MSDN library chm files). Instead of using "pow()" or "cos()" you''ll have to use "powf()" and "cosf()". 4/ use your own "ftol()" function : when you transform an float value to an integer value, the compiler implicitely calls "ftol()". This function is precise but slow. You can get nearly the same results by using a small inlined function (don''t have it here : I''m at home )5/ the pow() function is a no-no. Use a look up table. 6/ you can do the same for the cos() function if you want.This should speed up your implementation. Another solution is to take the basic Ken Perlin code and to tweak it until you get decent results. You should be able to do a 512x512 texture in less than 500 ms without any kind of super-genious_optimization. A third solution, as Chaucer proposed, is to use multiple simple noise layers (this is what you do with your loop). I believe that clanlib as a noise function which work like that (very fast). Hope it helps,--Emmanuel Deloget 0 Share this post Link to post Share on other sites

Fingers_ 410 Report post Posted November 19, 2003 You don''t need a look-up table or pow() when you''re doing x^2 or x^3. Just use (x*x) or (x*x*x), it''s probably faster than a table look-up. I''d also try using a non-smoothed noise function and linear interpolation and see if the quality is good enough for your application. 0 Share this post Link to post Share on other sites