2012-06-24 123 views
0

我創建了佩林噪聲函數。我的問題是,當我從噪音中產生的地形圖產生塊狀時,就像我見過的雲狀圖像一樣。我很好奇我做錯了什麼(如果有的話)。 這裏是我的代碼:佩林噪聲問題

的main.cpp

#include "PerlinNoise.h" 
#include <stdio.h> 
#include <SDL/SDL.h> 

void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B); 
SDL_Surface *Render_Noise(int w, int h, int r, int g, int b); 
PerlinNoise noiseGen(2,.5,25); 

int main(int argc, char **argv) 
{ 
    SDL_Init(SDL_INIT_EVERYTHING); 
    SDL_Surface *screen = SDL_SetVideoMode(500,500,32,SDL_SWSURFACE); 
    SDL_Surface *noise = Render_Noise(500,500,255,255,255); 

    SDL_SaveBMP(noise, "noise.bmp"); 

    bool quit = false; 

    while(!quit) 
    { 
     SDL_Event e; 

     SDL_WaitEvent(&e); 

     switch(e.type) 
     { 
     case SDL_QUIT: 
      quit = true; 
     } 

     SDL_BlitSurface(noise,NULL,screen,NULL); 
     SDL_Flip(screen); 
     SDL_Delay(2000); 
    } 

    SDL_FreeSurface(noise); 
    SDL_Quit(); 

    return 0; 
} 

void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B) 
{ 
    Uint32 color = SDL_MapRGB(screen->format, R, G, B); 

    if(SDL_MUSTLOCK(screen)) 
    { 
     if(SDL_LockSurface(screen) < 0) 
     { 
      return; 
     } 
    } 

    switch(screen->format->BytesPerPixel) 
    { 
    case 1: 
     { 
     Uint8 *bufp; 

     bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; 
     *bufp = color; 
     } 
     break; 

    case 2: 
     { 
     Uint16 *bufp; 
     bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x; 
     *bufp = color; 
     } 
     break; 

    case 3: 
     { 
     Uint8 *bufp; 

     bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; 
     *(bufp+screen->format->Rshift/8) = R; 
     *(bufp+screen->format->Bshift/8) = B; 
     *(bufp+screen->format->Gshift/8) = G; 
     } 
     break; 

    case 4: 
     { 
     Uint32 *bufp; 

     bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x; 
     *bufp = color; 
     } 
     break; 
    } 

    if(SDL_MUSTLOCK(screen)) 
    { 
     SDL_UnlockSurface(screen); 
    } 
    SDL_UpdateRect(screen, x, y, 1, 1); 
} 

SDL_Surface *Render_Noise(int w, int h, int r, int g, int b) 
{ 
    SDL_Surface *ret = SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,32,0,0,0,0);   //create an empty image 

    for(int y = 0; y < h; y++) 
    { 
     for(int x = 0; x < w; x++) 
     { 
      double getnoise = 0; 
      for(int a = 0; a < noiseGen.n; a++) 
      { 
       getnoise += noiseGen.generateNoise(x,y); 
       noiseGen.z = rand() % 100; 
      } 

      getnoise/noiseGen.n; 

      int color = (int)((getnoise * 128.0) + 128.0);  //convert noise to 0-256 value 

      if (color > 255) 
       color = 255; 
      if (color < 0) 
       color = 0; 

      DrawPixel(ret, x, y, (int)((r/255.0) * (double)color), (int)((g/255.0) * (double)color), (int)((b/255.0) * (double)color)); 
     } 
    } 
    return ret; 
} 

perlinnoise.cpp

#include "PerlinNoise.h" 

PerlinNoise::PerlinNoise(int octaves, double persistence, int zoom) 
{ 
    p = persistence; 
    n = octaves - 1; 
    z = zoom; 
} 

PerlinNoise::~PerlinNoise() 
{ 

} 

///<summary>Gets a random number using x and y as seeds </summary> 
///<param name = x> A double value </param> 
///<param name = y> A double value </param> 
///<returns> A random number between -1.0 and 1.0 </returns> 
inline double PerlinNoise::noise(double x, double y) 
{ 
    int n = x + y * 57; 
    n = (n << 13)^n; 

    return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0); 
} 

///<summary> Smooths out noise values </summary> 
///<param name = x> a double value </param> 
///<param name = y> a double value </param> 
///<returns> a smoothed value between -1.0 and 1.0 </returns> 
double PerlinNoise::smoothNoise(double x, double y) 
{ 
    double corners = (noise(x+1, y+1) + noise(x+1,y-1) + noise(x-1,y+1) + noise(x-1,y-1))/16; 
    double sides = (noise(x,y+1) + noise(x,y-1) + noise(x+1,y) + noise(x-1,y))/8; 
    double center = noise(x,y)/4; 

    return corners + sides + center; 
} 

///<summary> Cosine Interpolation </summary> 
///<param name = a> The low value to be interpolated </param> 
///<param name = b> The high value to be interpolated </param> 
///<param name = x> A value between -1.0 and 1.0 </param> 
///<returns> Interpolated value between a and b </returns> 
double PerlinNoise::cosineInterpolation(double a, double b, double x) 
{ 
    double ft = x * 3.1415927; 
    double f = (1.0 - cos(ft)) * .5; 

    return a * (1.0 - f) + b * f; 
} 

///<summary> Gets smoothed noise values and interpolates them </summary> 
///<param name = x> a double value </param> 
///<param name = y> a double value </param> 
///<returns> a value between -1 and 1 that's been smoothed and interpolated </returns> 
double PerlinNoise::interpolatedNoise(double x, double y) 
{ 
    double integer_x = (int)x; 
    double fractional_x = x - integer_x; 

    double integer_y = (int)y; 
    double fractional_y = y - integer_y; 

    double v1 = smoothNoise(integer_x, integer_y); 
    double v2 = smoothNoise(integer_x + 1, integer_y); 
    double v3 = smoothNoise(integer_x, integer_y + 1); 
    double v4 = smoothNoise(integer_x + 1, integer_y + 1); 

    double inter1 = cosineInterpolation(v1, v2, fractional_x); 
    double inter2 = cosineInterpolation(v3, v4, fractional_x); 

    return cosineInterpolation(inter1, inter2, fractional_y); 
} 

double PerlinNoise::generateNoise(double x, double y) 
{ 
    double total = 0; 

    for(int i = 0; i < n; i++) 
    { 
     frequency = pow(2.0,i); 
     amplitude = pow(p,i); 

     total = total + interpolatedNoise(x * frequency/z, y * frequency/z) * amplitude; 
    } 

    return total; 
} 
+2

發佈您的輸出圖像將是非常很有幫助。 – Pubby

+0

考慮到你的代碼不能編譯(列表不完整),提供任何有用的評論是相當具有挑戰性的。也就是說,塊狀輸出表明噪聲太少,而粗糙的輸出表明需要某種過濾。請鏈接一些輸出。 – Rook

+0

[這裏是](http://imgur.com/zfyTU)我得到了什麼。要進行編譯,您需要SDL和[this](http://pastie.org/4144014)頭文件。我選擇了2個最重要的文件上傳,因爲堆棧溢出只會允許我2 – Zacharias3960

回答

0

發現了問題,我的堅持是遠遠低於它應該是,正在增加,我得到了我期望的雲狀圖像