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

Author Topic: fastPixelRendering  (Read 4107 times)

0 Members and 1 Guest are viewing this topic.

milen

  • Newbie
  • *
  • Posts: 8
    • View Profile
fastPixelRendering
« on: August 10, 2015, 04:26:04 pm »
I just start to play with C++ and SFML.
I use Code::Blocks with  TDM-GCC 4.9.2, 64 bit and SFML-2.3.1-windows-gcc-4.8.1-tdm-64-bit.zip.
My system is: Windows 7 64 bit, NVIDIA GeForce GT610

I try to make window with effect of snowflakes as on the old televisions. Make two variants. The PROBLEMS are the same:
- flickering
- when I set texture (window) size - power of 2 (as I read that this is faster for the graphic card), on the screen are almost static image of dots, more or less grouped in rows or columns.
- at different size of the screen - the effects are different - flickering (the best case, shown in the next examples), or "moving" random pixels...

The VerticalSync or FrameRate do not change anything special.

Is proper this my code or I make some error logic?

First variant:
----------------
(with Texture from Image)

#include <sstream>
#include <time.h>
#include <stdlib.h>

using namespace std;

string num2str(int i){
    stringstream s;
    s << i;
    return s.str();
}

int main()
{
    const unsigned int s = 500;
    unsigned char c;


    sf::RenderWindow window(sf::VideoMode(s, s),
                            "Random",
                            sf::Style::Close);
    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

    sf::Image img;
    img.create(s, s, sf::Color(0, 0, 0));

    sf::Texture texture;
    sf::Sprite sprite;
    //window.setTitle(num2str(sf::Texture::getMaximumSize())); // for my card this is 16384
    texture.loadFromImage(img);
    sprite.setTexture(texture, true);

    srand(time(0));

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

        for (unsigned int i=0; i<s; i++)
            for (unsigned int j=0; j<s; j++){
                c = (rand()%2 == 0) ? 0 : 255;
                img.setPixel(i, j, sf::Color(c, c, c));
            }

        texture.update(img);

        window.clear();
        window.draw(sprite);
        window.display();
    }
    return 0;
}
 


Second variant:
--------------------
(with Texture from Array)

#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <time.h>
#include <stdlib.h>

using namespace std;

string num2str(int i){
    stringstream s;
    s << i;
    return s.str();
}

int main()
{
    const unsigned int s = 500;
    const unsigned int sz = s*s*4;
    sf::Uint8 px[sz];

    for (unsigned int i=3; i<sz; i+=4) px[i] = 255; // set alfa once


    sf::RenderWindow window(sf::VideoMode(s, s),
                            "Random",
                            sf::Style::Close);
    window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

    sf::Texture texture;
    texture.create(s, s);

    sf::Sprite sprite;
    //window.setTitle(num2str(sf::Texture::getMaximumSize()));
    //window.setTitle(num2str(RAND_MAX));
    sprite.setTexture(texture);

    srand(time(0));

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
            if (event.type == sf::Event::Closed) window.close();
/* [b]I try this to optimize the random fast pixel choice, but the screen become black with only little white random dots[/b]
        for (unsigned int i=0; i<sz-2*16*4; i+=16*4){
                c = rand();
                for (unsigned int j=0; j<16; j++){
                    px[i+j] = (((c >> j) & 1u) == 0) ? 0 : 255;
                    px[i+j+1] = px[i+j]; px[i+j+2] = px[i+j];
                    px[i+j+3] = 255;
                }
        }
*/

        for (unsigned int i=0; i<sz-4; i+=4){
            px[i] = (rand()%2 == 0) ? 0 : 255;
            px[i+1] = px[i]; px[i+2] = px[i];
        }

        texture.update(px);

        window.clear();
        window.draw(sprite);
        window.display();
    }
    return 0;
}
 

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: fastPixelRendering
« Reply #1 on: August 10, 2015, 05:29:26 pm »
Modifying the texture and uploading it to the GPU every frame is going to be very slow. This kind of effect would be much better off done in a shader. There are a few glsl examples on Google.

milen

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: fastPixelRendering
« Reply #2 on: August 10, 2015, 06:25:47 pm »
The Shaders are out of my knowledge.

BUT the code is sooo fast, the dots moves very fast. It will be very good, if there are not the described strange effects. I thing that the problem is specifically hardware - why the power of 2 size (for example 512) do not work, but size 500 work almost fine?!....

Fumasu

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: fastPixelRendering
« Reply #3 on: August 10, 2015, 07:16:02 pm »
Hello.
I just start to play with C++ and SFML.
I use Code::Blocks with  TDM-GCC 4.9.2, 64 bit and SFML-2.3.1-windows-gcc-4.8.1-tdm-64-bit.zip.
My system is: Windows 7 64 bit, NVIDIA GeForce GT610
The versions of your compiler and SFML-package do not match. There is no official package for the TDM-GCC 4.9.2 compiler so you have to compile SFML from the source yourself (it is very easy). Just follow this tutorial.
http://www.sfml-dev.org/tutorials/2.3/compile-with-cmake.php

Quote
window.setVerticalSyncEnabled(true);
window.setFramerateLimit(60);
 
You should not use window.setVerticalSyncEnable and window.setFramerateLimit at the same time.

The problem seems to be the rand() random number generator. When i use the c++11 rng the problem disapears.
#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <time.h>
#include <stdlib.h>

using namespace std;

string num2str(int i){
    stringstream s;
    s << i;
    return s.str();
}

int main()
{
    const unsigned int s = 512;
    const unsigned int sz = s*s*4;
    sf::Uint8 px[sz];

    //for (unsigned int i=3; i<sz; i+=4) px[i] = 255; // set alfa once


    sf::RenderWindow window(sf::VideoMode(s, s),
                            "Random",
                            sf::Style::Close);
    //window.setVerticalSyncEnabled(true);
    window.setFramerateLimit(60);

    sf::Texture texture;
    texture.create(s, s);

    sf::Sprite sprite;
    //window.setTitle(num2str(sf::Texture::getMaximumSize()));
    //window.setTitle(num2str(RAND_MAX));
    sprite.setTexture(texture);

   // use the c++11 random number generator
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(1, 2);
       
    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
                {
            if (event.type == sf::Event::Closed)
                                window.close();
                }

        for (unsigned int i=0; i<sz-4; i+=4){
            //px[i] = (rand()%2 == 0) ? 0 : 255;
                        px[i] = (dis(gen)%2 == 0) ? 0 : 255;
            px[i+1] = px[i]; px[i+2] = px[i]; px[i+3] =255;
        }

        texture.update(px);

        window.clear();
        window.draw(sprite);
        window.display();
    }
    return 0;
}
 

Hapax

  • Hero Member
  • *****
  • Posts: 3383
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: fastPixelRendering
« Reply #4 on: August 10, 2015, 11:44:47 pm »
The problem seems to be the rand() random number generator. When i use the c++11 rng the problem disapears.
I agree that "rand() is evil" and <random> is much better. However, it seems more likely that what made a bigger difference was your addition of the statement:
px[i+3] =255;
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

milen

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: fastPixelRendering
« Reply #5 on: August 11, 2015, 05:22:24 pm »
Fumasu, thank you very much!

Your code works! And for some optimization I return the:

for (unsigned int i=3; i<sz; i+=4) px[i] = 255; // set alfa once

and delete the:

px[i+3] = px[i];

It works very well for almost any different sizes (do not see any difference if there are power of two).

BUT, there are still two problems:

- flickering! I thing that on every some seconds (1-3), the rendering stops for a blink, and then continue. This is very strange, such any buffer overflows or ... I have no idea.

- when I set big size of the screen - over 700 pixels - all compiles good, but starting the result exe says - "name.exe stopped working". And Windows suggest to Close. This is completely understandable. I have large amounts of RAM (10GB!, and 1GB Video), the Maximum Texture size, as I mentioned is 16384... I do not know.

But Thanks, for me now is interesting another question - what is wrong with the old well known rand()? Is it bad also in other compilers, or in GCC only?...

P.S. Thenks also for advise about to make my compiled version for SFML!!! I try - it indeed is very simple - I play now with SFML 2.3.1 64bit for TDM 5.1 64bit!!!

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: fastPixelRendering
« Reply #6 on: August 11, 2015, 05:29:29 pm »
But Thanks, for me now is interesting another question - what is wrong with the old well known rand()? Is it bad also in other compilers, or in GCC only?...
There are quite a few things wrong with rand():
 - very short period.
 - very short seed.
 - very bad distribution of numbers.
And more.
For a very detailed walk-through of the problems with rand() and why you should use <random> instead, watch this 31min talk by the exceptional Mr. Stephan T. Lavavej - rand() Considered Harmful.

Edit: Just leaving an additional link here since I believe you may find it interresting ;) http://www.redblobgames.com/articles/probability/damage-rolls.html
« Last Edit: August 11, 2015, 06:12:22 pm by Jesper Juhl »

milen

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: fastPixelRendering
« Reply #7 on: August 11, 2015, 06:19:53 pm »
Jesper Juhl, thanks, I will learn about the computer random generators.

About the flickering problem:

I try another my code with fast sinusoid moving:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <sstream>
#include <cmath>

using namespace std;

constexpr double pi() { return atan(1)*4; }

int main()
{
    const unsigned int s = 500u;
    const unsigned int N = 1000u;

    sf::RenderWindow window(sf::VideoMode(s, s),
                            "Osc",
                            sf::Style::Close);
    //window.setVerticalSyncEnabled(true);
    //window.setFramerateLimit(60);

    sf::VertexArray chart(sf::LinesStrip, N+1);
    for (unsigned int i=0; i<=N; i++){
        unsigned int x = i*s/N;
        unsigned int y = s/2 - (s/2-100)*sin(i*2*pi()/N);
        chart[i].position = sf::Vector2f(x, y);
        chart[i].color = sf::Color::Blue;
    }

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

        unsigned int tmpy = chart[0].position.y;
        for (unsigned int i=0; i<N; i++)
            chart[i].position.y = chart[i+1].position.y;
        chart[N].position.y = tmpy;

        window.clear(sf::Color::Yellow);
        window.draw(chart);
        window.display();
    }
    return 0;
}
 

The speed of sinusoid depends on framerate, therefore I do not use verticalSync or FrameRate, to see maximum speed of my PC.
AND - the same problem - sinusoid moves indeed very fast, and on every 2-3 seconds - STOPS for a very little time, and starts moving again.

Just like some buffer overflows... I can try my code on another hardware. Interesting where is the problem - compiler, SFML or hardware, may be video-driver (it is updated)?

Hapax

  • Hero Member
  • *****
  • Posts: 3383
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: fastPixelRendering
« Reply #8 on: August 11, 2015, 07:55:03 pm »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*