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

Author Topic: Drawing Visual Noise Quickly  (Read 4608 times)

0 Members and 1 Guest are viewing this topic.

Blacksmith

  • Newbie
  • *
  • Posts: 2
    • View Profile
Drawing Visual Noise Quickly
« on: September 02, 2021, 11:15:53 pm »
Hello,

I'm currently working on a small game project to learn SFML. I would like (for stylistic purposes) for the background of every frame to be visual noise rather than a flat color. To do this, I am clearing the window with sf::Color::Black, and then drawing my chosen noise color to each pixel of an sf::Image with a pseudorandom alpha value, then copying that image into a texture and then finally into a sprite which is drawn to the window.

This seems to be the intended way to draw something to the screen that we want to be able to manipulate pixel by pixel, as sf::Image is not drawable. However, it is very slow. I am only managing ~20 FPS. Is there something I'm missing here that would greatly speed up the process of drawing visual noise?

Code:
(click to show/hide)

Paul

  • Jr. Member
  • **
  • Posts: 79
    • View Profile
Re: Drawing Visual Noise Quickly
« Reply #1 on: September 03, 2021, 08:12:19 pm »
You can fake it in some way, for example prerender noise into few textures and during game loop draw them randomly. Or use shaders.

Blacksmith

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Drawing Visual Noise Quickly
« Reply #2 on: September 03, 2021, 09:54:23 pm »
You're probably right. I like doing everything programmatically, but I guess I'll have to settle for using prebaked images.

fallahn

  • Sr. Member
  • ****
  • Posts: 492
  • Buns.
    • View Profile
    • Trederia
Re: Drawing Visual Noise Quickly
« Reply #3 on: September 05, 2021, 11:57:46 am »
Much of game making boils down to 'faking it' quite often ;) However the fastest way to do something like this programatically (and most fun way imo, cos shaders are awesome  8) ) is to use a noise shader like this:

namespace
{
    const std::string GreyFrag = R"(
        #version 120
        #define GREY

        )"
;

    const std::string ColourFrag = R"(
        #version 120

        )"
;

    const std::string NoiseFrag = R"(
        uniform float u_time;

        float rand(vec2 pos)
        {
            return fract(sin(dot(pos, vec2(12.9898, 4.1414) + u_time)) * 43758.5453);
        }

        void main()
        {
#if defined (GREY)
            gl_FragColor.rgb = vec3(rand(floor((gl_FragCoord.xy))));
#else
            // these are arbitrary numbers just to provide an offset.
            // you could use uniform values here for a variable effect
            gl_FragColor.r = rand(floor((gl_FragCoord.xy + 17.034765)));
            gl_FragColor.g = 1.0 - rand(floor((gl_FragCoord.xy)));
            gl_FragColor.b = rand(floor((gl_FragCoord.xy + 0.145)));
#endif

            gl_FragColor.a = 1.0;
        })"
;
}


int main()
{
    sf::RenderWindow window(sf::VideoMode(400, 200), "SFML works!");
    sf::CircleShape shape(100.f);

    sf::Shader greyShader;
    greyShader.loadFromMemory(GreyFrag + NoiseFrag, sf::Shader::Fragment);

    sf::Shader colourShader;
    colourShader.loadFromMemory(ColourFrag + NoiseFrag, sf::Shader::Fragment);

    sf::Clock shaderClock;

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                window.close();
            }
        }

        float shaderTime = shaderClock.getElapsedTime().asSeconds();
        greyShader.setUniform("u_time", shaderTime);
        colourShader.setUniform("u_time", shaderTime);

        window.clear();
        shape.setPosition(0.f, 0.f);
        window.draw(shape, &greyShader);
        shape.setPosition(200.f, 0.f);
        window.draw(shape, &colourShader);
        window.display();
    }

    return 0;
}