Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Turning values into pixels for perlin noise  (Read 2520 times)

0 Members and 1 Guest are viewing this topic.

JohnSnow007

  • Newbie
  • *
  • Posts: 15
    • View Profile
Turning values into pixels for perlin noise
« on: October 23, 2020, 02:21:15 am »
Hello, I'm working on a Perlin noise generator.
The following just draws a completely black window.

void drawNoise2d(int mapWidth, int mapHeight, float noise[], sf::RenderWindow& window)
{
        sf::Image image{};
        sf::Texture texture{};
        sf::Sprite sprite{};

        image.create(SCREEN_WIDTH, SCREEN_HEIGHT, sf::Color(0, 0, 0));
        sf::Color color{};

        for (int x{ 0 }; x < SCREEN_WIDTH; ++x)
        {
                for (int y{ 0 }; y < SCREEN_HEIGHT; ++y)
                {
                        int pixel_w = std::floor(noise[y * SCREEN_HEIGHT + x] * 4.0f);

                        switch (pixel_w)
                        {
                        case 0:
                                color.r = 0;
                                color.g = 0;
                                color.b = 0;
                                break;
                        case 1:
                                color.r = 105;
                                color.g = 105;
                                color.b = 105;
                                break;
                        case 2:
                                color.r = 128;
                                color.g = 128;
                                color.b = 128;
                                break;
                        case 3:
                                color.r = 169;
                                color.g = 169;
                                color.b = 169;
                                break;

                        case 4:
                                color.r = 192;
                                color.g = 192;
                                color.b = 192;
                                break;
                        }

                        image.setPixel(x, y, color);
                }
        }
        texture.update(image);
        sprite.setTexture(texture);
        window.draw(sprite);
}
 

The noise[] holds an array of values. For example:
std::cout << "Noise # " << y * mapWidth + x << ": " << noise[y * mapWidth + x] << '\n';
 

Noise # 0: 0.786747
Noise # 100: 0.770166
Noise # 200: 0.753585
Noise # 300: 0.737004
Noise # 400: 0.720423
Noise # 500: 0.703842
Noise # 600: 0.687262
Noise # 700: 0.67491
Noise # 800: 0.662559
Noise # 900: 0.650208
Noise # 1000: 0.637857
Noise # 1100: 0.625506
Noise # 1200: 0.613155
Noise # 1300: 0.605034
Noise # 1400: 0.596913
Noise # 1500: 0.588791
Noise # 1600: 0.58067
Noise # 1700: 0.572549
Noise # 1800: 0.564428
Noise # 1900: 0.556306
Noise # 2000: 0.548185
Noise # 2100: 0.540064
Noise # 2200: 0.531942
Noise # 2300: 0.523821
Noise # 2400: 0.5157
Noise # 2500: 0.507579
Noise # 2600: 0.503518
Noise # 2700: 0.499457
Noise # 2800: 0.495397
Noise # 2900: 0.491336
Noise # 3000: 0.487276
Noise # 3100: 0.483215
Noise # 3200: 0.479154
Noise # 3300: 0.475094
Noise # 3400: 0.471033
Noise # 3500: 0.466972
Noise # 3600: 0.462912
Noise # 3700: 0.458851
Noise # 3800: 0.454791
Noise # 3900: 0.45073
Noise # 4000: 0.446669
Noise # 4100: 0.442609
Noise # 4200: 0.438548
Noise # 4300: 0.434487
Noise # 4400: 0.430427
Noise # 4500: 0.426366
Noise # 4600: 0.422305
Noise # 4700: 0.418245
Noise # 4800: 0.414184
Noise # 4900: 0.410124
Noise # 5000: 0.406063
Noise # 5100: 0.410124
Noise # 5200: 0.414184
Noise # 5300: 0.418245
Noise # 5400: 0.422305
Noise # 5500: 0.426366
Noise # 5600: 0.430427
Noise # 5700: 0.434487
Noise # 5800: 0.438548
Noise # 5900: 0.442609
Noise # 6000: 0.446669
Noise # 6100: 0.45073
Noise # 6200: 0.454791
Noise # 6300: 0.458851
Noise # 6400: 0.462912
Noise # 6500: 0.466972
Noise # 6600: 0.471033
Noise # 6700: 0.475094
Noise # 6800: 0.479154
Noise # 6900: 0.483215
Noise # 7000: 0.487276
Noise # 7100: 0.491336
Noise # 7200: 0.495397
Noise # 7300: 0.499457
Noise # 7400: 0.503518
Noise # 7500: 0.507579
Noise # 7600: 0.5157
Noise # 7700: 0.523821
Noise # 7800: 0.531942
Noise # 7900: 0.540064
Noise # 8000: 0.548185
Noise # 8100: 0.556306
Noise # 8200: 0.564428
Noise # 8300: 0.572549
Noise # 8400: 0.58067
Noise # 8500: 0.588791
Noise # 8600: 0.596913
Noise # 8700: 0.605034
Noise # 8800: 0.613155
Noise # 8900: 0.621276
Noise # 9000: 0.629398
Noise # 9100: 0.637519
Noise # 9200: 0.64564
Noise # 9300: 0.653761
Noise # 9400: 0.661883
Noise # 9500: 0.670004
Noise # 9600: 0.678125
Noise # 9700: 0.686246
Noise # 9800: 0.694368
Noise # 9900: 0.702489
Noise # 1: 0.777325
Noise # 101: 0.761523
Noise # 201: 0.745722
Noise # 301: 0.72992
Noise # 401: 0.714118
Noise # 501: 0.698317
Noise # 601: 0.682515
Noise # 701: 0.670458
Noise # 801: 0.6584
Noise # 901: 0.646343
Noise # 1001: 0.634286
Noise # 1101: 0.622229
Noise # 1201: 0.610171
...CONTINUED...
 

The window screen is completely black but running. Where is it wrong or could it be a poor implementation elsewhere in the code. I don't think its the latter, because before this function, I was able to draw randomly picked sample of values of noise[] on a 1D plane, but translating that into 2D isn't working. So I think the error is due to this function. 

I'm really new to SFML so I'd really appreciate some help. :-[
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Turning values into pixels for perlin noise
« Reply #1 on: October 23, 2020, 07:22:04 am »
The sf::Texture instance must not be destroyed at the end of the function -- OpenGL works asynchronously, so the texture data may be used after the draw call. And you must call texture.create, texture.update alone won't do anything.
Laurent Gomila - SFML developer

JohnSnow007

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Turning values into pixels for perlin noise
« Reply #2 on: October 23, 2020, 04:20:35 pm »
Thanks. I changed it to
void drawNoise2d(int mapWidth, int mapHeight, float noise[], sf::RenderWindow& window, sf::Texture& texture);

int main()
{
        // do stuff here

        sf::Texture texture{};
        texture.create(SCREEN_WIDTH, SCREEN_HEIGHT);

        // do stuff here
}
 
Note how I added sf::Texture &texture to the parameter. However the images that are generated look incredibly ugly. I configured button presses to change the scale and number of octaves. I'm using the same algorithm used in OneLoneCoder's video on perlin noise.

Here  are some of the results:





They all are very similar, like it produces a "shark-head" shape and I am never able to achieve the "television" noise and they produces a thin line of the colours.

void drawNoise2d(int mapWidth, int mapHeight, float noise[], sf::RenderWindow& window, sf::Texture& texture)
{
        sf::Image image{};
        sf::Sprite sprite{};

        image.create(SCREEN_WIDTH, SCREEN_HEIGHT, sf::Color(0, 0, 0));
        sf::Color color{};
        for (int x{ 0 }; x < SCREEN_WIDTH; ++x)
        {
                for (int y{ 0 }; y < SCREEN_HEIGHT; ++y)
                {
                        int pixel_w = (int)(noise[y * SCREEN_HEIGHT + x] * 12.0f);

                        switch (pixel_w)
                        {
                        case 0: // GREY was black before
                                color.r = 128;
                                color.g = 128;
                                color.b = 128;
                                break;
                        case 1: // DIM GREY
                                color.r = 105;
                                color.g = 105;
                                color.b = 128;
                                break;
                        case 2: // GREY
                                color.r = 128;
                                color.g = 128;
                                color.b = 128;
                                break;
                        case 3: // DARK GREY
                                color.r = 169;
                                color.g = 169;
                                color.b = 169;
                                break;

                        case 4: // SILVER
                                color.r = 192;
                                color.g = 192;
                                color.b = 192;
                                break;
                        case 5:
                                color.r = 0;
                                color.g = 0;
                                color.b = 255;
                                break;
                        case 6: // Lawn green
                                color.r = 124;
                                color.g = 252;
                                color.b = 0;
                                break;
                        case 7:
                                color.r = 32;
                                color.g = 178;
                                color.b = 170;
                                break;
                        case 8:  // Forest Green
                                color.r = 34;
                                color.g = 139;
                                color.b = 34;

                                break;
                        case 9:
                                color.r = 0;
                                color.g = 0;
                                color.b = 128;
                                break;
                        case 10: // SNOW
                                color.r = 255;
                                color.g = 250;
                                color.b = 250;
                                break;
                        case 11: // LAVENDER
                                color.r = 255;
                                color.g = 240;
                                color.b = 245;
                                break;
                        case 12: // White
                                color.r = 255;
                                color.g = 255;
                                color.b = 255;
                                break;
                        }

                        image.setPixel(x, y, color);
                }
        }
        texture.update(image);
        sprite.setTexture(texture);
        window.draw(sprite);
}
 

I'm not sure as to why.
« Last Edit: October 23, 2020, 04:22:16 pm by JohnSnow007 »

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Turning values into pixels for perlin noise
« Reply #3 on: October 23, 2020, 06:20:27 pm »
int pixel_w = (int)(noise[y * SCREEN_HEIGHT + x] * 12.0f);

probably ought to be

int pixel_w = (int)(noise[y * SCREEN_WIDTH + x] * 12.0f);

Also it's more memory access friendly if you loop like this:
for (int y{ 0 }; y < SCREEN_HEIGHT; ++y)
{
    for (int x{ 0 }; x < SCREEN_WIDTH; ++x)
    {

    }
}
 

as you're not skipping SCREEN_WIDTH values at a time, you'll be accessing your array sequentially. If you print pixel_w to the console you'll see what I mean  ;D

JohnSnow007

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Turning values into pixels for perlin noise
« Reply #4 on: October 23, 2020, 08:04:34 pm »
Thanks I can get really nice terrain
probably ought to be

int pixel_w = (int)(noise[y * SCREEN_WIDTH + x] * 12.0f);

Also it's more memory access friendly if you loop like this:
for (int y{ 0 }; y < SCREEN_HEIGHT; ++y)
{
    for (int x{ 0 }; x < SCREEN_WIDTH; ++x)
    {

    }
}
 

as you're not skipping SCREEN_WIDTH values at a time, you'll be accessing your array sequentially. If you print pixel_w to the console you'll see what I mean  ;D

Thanks I'm getting some nice looking terrain however I'm still unable to produce the "tv" set noise. Sometimes i get really obscure looking images like for example at the 5th octave and scaling at: 0.4f :



I'm using
std::mt19937 mersenne{ static_cast<std::mt19937::result_type>(std::time(nullptr)) };
the to produce the seeds.

I'm not sure how to fix it.  :-\

JohnSnow007

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Turning values into pixels for perlin noise
« Reply #5 on: October 25, 2020, 02:22:01 am »
Thanks for the help guys anyway. I've been able to fix it. The problem was the size of the pixels compared to the screen size. I've adjusted them and I can get that greyscale perlin noise image and produce nice looking maps without the weird bits.

 

anything