How to Create the Noise Effect

Noise is another special effect to emulate an old TV without a signal. A naive approach to do this graphic effect is to create a double for-loop and randomize the color of the pixel being placed on each of the coordinates of the screen.

for (y = 0; y < MAX_SCREEN_HEIGHT; ++y)
    for (x = 0; x < MAX_SCREEN_WIDTH; ++x)
        putPixel(x, y, RBGA(rand()%256, rand()%256, rand()%256, rand()%256));

This will work but not as fast as we would like it to be due to the following reasons:

  • putPixel is a function, and most probably not inline due to the nature of its process. A regular function call goes to the system's stack call, which makes the program slower.
  • RGBA is another function in the system stack call, which combines the random values of RGBA into one unsigned long value.
  • rand() is called four times.

An alternative to this approach is implementing your own random number generator using Linear Congruential Method and converting all function calls to draw a pixel local to the main loop. The concept behind Linear Congruential Method for generating random numbers will be discussed in a separate article.

The following program is implemented using C/C++ and SDL2.0.

    // Pixel Vars
    Uint32  pDataSize = surface->h * surface->w;
    Uint32* ePtr = (Uint32*)surface->pixels + pDataSize;

    // Linear Congruential Method for generating Random numbers
    Uint32 m = 0xffffffff, a = 12345, b = 1103515245, rnd = a;

 

    do
    {
        Uint32* pPtr = (Uint32*)surface->pixels;
        do
        {
            rnd = (b * rnd + 1); // Omitted % m;
            *pPtr = rnd;
        } while (++pPtr < ePtr);
        SDL_UpdateWindowSurface(window);
     } while (true);

Explanation of program:

Uint32  pDataSize = surface->h * surface->w;
Uint32* ePtr = (Uint32*)surface->pixels + pDataSize;

pDataSize is the size of the pixel buffer in memory. ePtr is the boundary of pixel data in memory.

Uint32 m = 0xffffffff, a = 12345, b = 1103515245, rnd = a;

Initialization of LGM using arbitrary values. 

Uint32* pPtr = (Uint32*)surface->pixels;

Set pPtr at the start of pixel bufffer.

rnd = (b * rnd + 1); // Omitted % m;

Get the next random number value. Since where expecting a 4 byte random number for RGBA, there's no need to filter out the result with modulo m.

*pPtr = rnd;

Assign the value of the unsigned long random number to the pixel buffer.

while (++pPtr < ePtr);

Assign random values until the loop reaches the end of the memory buffer. The size of the memory buffer is equal to the product of MAX_SCREEN_HEIGHT and MAX_SCREEN_WIDTH and 4 in bytes. But since we're using a four-byte pointer *pPtr, we can omit the multiplication by 4.

SDL_UpdateWindowSurface(window);

Copy the result of the pixel buffer to the screen. It is important to note that this is done after preprocessing the pixel buffer to prevent flickering of the screen.

Try it now!

Now is the time to see it for yourself and try it on your own. Experiment and hope you can include this effect on your next game development project.

Attachments: 

Tags: