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

Author Topic: Weird lines in particle test  (Read 3036 times)

0 Members and 1 Guest are viewing this topic.

Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Weird lines in particle test
« on: December 01, 2013, 05:40:23 pm »
Hello, I've wanted to make a small particle system in SFML. I created the first version using the sf::RectangleShape class to make the little particles and it worked fine but was quite slow (started impacting FPS at around 1500 particles) so I re-wrote a bit of it using vertex arrays which appears to be much faster but the actual window has weird black lines in it:



Here's my source file, please note that this is only a rough experiment and so is a bit messy:

Code: [Select]
#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
using namespace std;
sf::Vector2f Randomize(int Boundary1, int Boundary2)
{
    return sf::Vector2f((0 +((rand() % Boundary1))), (0 +((rand() % Boundary2))));
}

int RandomizeInt(int Boundary1, int Boundary2)
{
    return (Boundary1 +((rand() % Boundary2)));
}

struct PI
{
    sf::Color Colour = sf::Color::Yellow;
    int X = 0;
    int Y = 0;
    int LifeTime = 20000;
};

int main()
{
    int FPS = 0; //Setting up variables for measuring the FPS
    sf::Clock FPSClock;
    sf::Time FPSTime;

sf::Music music;
if (!music.openFromFile("sound.ogg"))
    return -1; // error
music.play();



    bool MousePressed = false;
    sf::Clock EffectClock;
    sf::Time EffectTime;

    int ActiveParticles = 0; //How many particles are active

    int ParticleCap = 0; //The limit of how many particles can be placed
    cout << "\nParticle Cap: ";
    cin >> ParticleCap;

    PI ParticleInfo[ParticleCap]; //Our particle information such as colour and lifetime.

    sf::VertexArray Pixel(sf::Points, ParticleCap);

    sf::RenderWindow window(sf::VideoMode(800, 600), "Partical System");
    window.setVerticalSyncEnabled(true);

    while (window.isOpen())
    {
        sf::Vector2i MousePosition = sf::Mouse::getPosition(window); //Storing mouse coords for later use

        if (sf::Mouse::isButtonPressed(sf::Mouse::Left) && MousePressed == false) //Checking if mouse is pressed
        {
            for(int a = 0; a < ParticleCap; a++) //Updating particle information
            {
                Pixel[a].position = sf::Vector2f(MousePosition.x,MousePosition.y);
                ParticleInfo[a].X = MousePosition.x;
                ParticleInfo[a].Y = MousePosition.y;
            }
            MousePressed = true;

            EffectClock.restart();
        }
        else if(!sf::Mouse::isButtonPressed(sf::Mouse::Left) && MousePressed == true)
        {
            MousePressed = false;
        }

        sf::Event event; //Polling window events to check for user input
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        EffectTime = EffectClock.getElapsedTime();
        for(int a = 0; a < ParticleCap; a++) //Updating particle information
        {

            ParticleInfo[a].LifeTime = RandomizeInt(0,40);
            ParticleInfo[a].X = ParticleInfo[a].X + RandomizeInt(0,6) - 3;
            ParticleInfo[a].Y = ParticleInfo[a].Y + RandomizeInt(0,6) - 3;
            Pixel[a].color = ParticleInfo[a].Colour;
            if(EffectTime.asMilliseconds() > ParticleInfo[a].LifeTime)
            {
                //Pixel[a].position = sf::Vector2f(-1,-1);
                ParticleInfo[a].X = MousePosition.x;
                ParticleInfo[a].Y = MousePosition.y;
                Pixel[a].position = sf::Vector2f(ParticleInfo[a].X, ParticleInfo[a].Y);
                EffectClock.restart();
            }
            else
            {
                Pixel[a].position = sf::Vector2f(ParticleInfo[a].X, ParticleInfo[a].Y - 6);
                ParticleInfo[a].Y = ParticleInfo[a].Y - 6;
            }
        }


        window.clear(sf::Color::Black);
        window.draw(Pixel);
        window.display();


        FPS++; //Calculating FPS and displaying it
        FPSTime = FPSClock.getElapsedTime();
        if(FPSTime.asSeconds() >= 1)
        {
            cout << "\nFPS: " << FPS << endl;
            FPSClock.restart();
            FPS = 0;
        }
    }

    return 0;
}


Why is this?

Sqasher

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Weird lines in particle test
« Reply #1 on: December 01, 2013, 06:35:04 pm »
I don't have those weird lines, so it could be a driver issue.



If you don't want the particles to form a yellow block, you can increase the spawning area and the lifetime and decrease the number of particles.
ParticleInfo[a].LifeTime = RandomizeInt(15,40);
ParticleInfo[a].X = ParticleInfo[a].X + RandomizeInt(0,20) - 10;
ParticleInfo[a].Y = ParticleInfo[a].Y + RandomizeInt(0,20) - 10;


Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Re: Weird lines in particle test
« Reply #2 on: December 01, 2013, 07:26:52 pm »
Hm, what compiler are you using?

Altering the way that the particles are spread does not alter the lines in the window and the lines don't move with the particles, they stay stationary. All of my drivers are up to data.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Weird lines in particle test
« Reply #3 on: December 01, 2013, 07:33:54 pm »
What if you minimize the code example to a sf::Points vertex array that contains static points? For example if you build a rectangle out of points, do the black lines still appear? Avoid everything that's not directly necessary, and keep the code as small as possible.

If they do not, the problem may also be related to the random generator. Linear congruential generators produce extremely bad random numbers, recognizable patterns are typical for them. You could try with an engine from <random> instead.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Re: Weird lines in particle test
« Reply #4 on: December 01, 2013, 08:34:40 pm »
Oh, I've made shapes out of vertexes before and they do not appear. I've tried seeding the generator and that hasn't changed it.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Weird lines in particle test
« Reply #5 on: December 01, 2013, 08:59:59 pm »
It's not about seeding, the regular patterns are an inherent property of linear congruential generators.

I'm not sure if it's that in your case -- that's why I stated you should try the random engines from the <random> header and see if they change something. If you happen use Thor, you could also call thor::random().
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Sqasher

  • Newbie
  • *
  • Posts: 19
    • View Profile
Re: Weird lines in particle test
« Reply #6 on: December 01, 2013, 09:03:06 pm »
I'm using MinGW 4.8 32bit on Windows 7 with a nVidia GeForce GTX 680 and the latest drivers.

I commented the music part out, but that shouldn't make any difference.

This code should give you a completely white window:
#include <SFML/Graphics.hpp>

int main() {
        int windowWidth = 800;
        int windowHeight = 600;

        sf::VertexArray vertices(sf::PrimitiveType::Points);

        for (int y = 0; y <= windowHeight; ++y) {
                for (int x = 0; x <= windowWidth; ++x) {
                        vertices.append(sf::Vertex(sf::Vector2f(x, y), sf::Color::White));
                }
        }

        sf::RenderWindow window(sf::VideoMode(windowWidth, windowHeight), "Test", sf::Style::Close);
        window.setVerticalSyncEnabled(true);

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

        return 0;
}

Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Re: Weird lines in particle test
« Reply #7 on: December 01, 2013, 09:36:39 pm »
Interesting...


Why's this?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Weird lines in particle test
« Reply #8 on: December 01, 2013, 09:42:21 pm »
Probably a driver issue. Can you try the same test, but with sf::Vector2f(x + 0.5, y + 0.5) for coordinates?
Laurent Gomila - SFML developer

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Weird lines in particle test
« Reply #9 on: December 01, 2013, 09:44:25 pm »
Strange. What if you choose the correct vertex positions (i.e. center of pixels, not left-upper corner) and don't draw vertices outside the window? That is:
    for (int y = 0; y < windowHeight; ++y) {
        for (int x = 0; x < windowWidth; ++x) {
            vertices.append(sf::Vertex(sf::Vector2f(x+0.5f, y+0.5f), sf::Color::White));
        }
    }
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Re: Weird lines in particle test
« Reply #10 on: December 01, 2013, 09:59:41 pm »
It is a completely white screen if I do that.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Weird lines in particle test
« Reply #11 on: December 01, 2013, 10:09:47 pm »
Ok, then do it like that :)

(It's a result of the pixel rasterization. OpenGL leaves some freedom to the decision how pixels "on the border" are handled. Usually however, drivers act consistently -- I'm not sure to what degree they have to).

Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Cl9

  • Newbie
  • *
  • Posts: 21
    • View Profile
    • Email
Re: Weird lines in particle test
« Reply #12 on: December 01, 2013, 10:24:36 pm »
Thankyou for your help everyone :D

Do I have to add the +0.5f after every movement or is there a quicker way of doing it?

Here's what I have now which works great:
Code: [Select]
#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
using namespace std;
sf::Vector2f Randomize(int Boundary1, int Boundary2)
{
    srand(time(NULL));
    return sf::Vector2f((0 +((rand() % Boundary1))), (0 +((rand() % Boundary2))));
}

int RandomizeInt(int Boundary1, int Boundary2)
{
    return (Boundary1 +((rand() % Boundary2)));
}

struct PI
{
    sf::Color Colour = sf::Color::Yellow;
    int X = 0;
    int Y = 0;
    int LifeTime = 20000;
};

int main()
{
    int FPS = 0; //Setting up variables for measuring the FPS
    sf::Clock FPSClock;
    sf::Time FPSTime;

sf::Music music;
if (!music.openFromFile("sound.ogg"))
    return -1; // error
music.play();



    bool MousePressed = false;
    sf::Clock EffectClock;
    sf::Time EffectTime;

    int ActiveParticles = 0; //How many particles are active

    int ParticleCap = 0; //The limit of how many particles can be placed
    cout << "\nParticle Cap: ";
    cin >> ParticleCap;

    PI ParticleInfo[ParticleCap]; //Our particle information such as colour and lifetime.

    sf::VertexArray Pixel(sf::Points, ParticleCap);

    sf::RenderWindow window(sf::VideoMode(800, 600), "Partical System", sf::Style::Default);
    window.setVerticalSyncEnabled(true);

    while (window.isOpen())
    {
        sf::Vector2i MousePosition = sf::Mouse::getPosition(window); //Storing mouse coords for later use

        if (sf::Mouse::isButtonPressed(sf::Mouse::Left) && MousePressed == false) //Checking if mouse is pressed
        {
            for(int a = 0; a < ParticleCap; a++) //Updating particle information
            {
                Pixel[a].position = sf::Vector2f(MousePosition.x+0.5f,MousePosition.y+0.5f);
                ParticleInfo[a].X = MousePosition.x+0.5f;
                ParticleInfo[a].Y = MousePosition.y+0.5f;
            }
            MousePressed = true;

            EffectClock.restart();
        }
        else if(!sf::Mouse::isButtonPressed(sf::Mouse::Left) && MousePressed == true)
        {
            MousePressed = false;
        }

        sf::Event event; //Polling window events to check for user input
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                window.close();
        }

        EffectTime = EffectClock.getElapsedTime();
        for(int a = 0; a < ParticleCap; a++) //Updating particle information
        {

            ParticleInfo[a].LifeTime = RandomizeInt(0,40);
            ParticleInfo[a].X = ParticleInfo[a].X + RandomizeInt(0,6) - 3;
            ParticleInfo[a].Y = ParticleInfo[a].Y + RandomizeInt(0,6) - 3;
            Pixel[a].color = ParticleInfo[a].Colour;
            if(EffectTime.asMilliseconds() > ParticleInfo[a].LifeTime)
            {
                //Pixel[a].position = sf::Vector2f(-1,-1);
                ParticleInfo[a].X = MousePosition.x;
                ParticleInfo[a].Y = MousePosition.y;
                Pixel[a].position = sf::Vector2f(ParticleInfo[a].X+0.5f, ParticleInfo[a].Y+0.5f);
                EffectClock.restart();
            }
            else
            {
                Pixel[a].position = sf::Vector2f(ParticleInfo[a].X+0.5f, (ParticleInfo[a].Y - 6)+0.5f);
                ParticleInfo[a].Y = (ParticleInfo[a].Y - 6)+0.5f;
            }
        }


        window.clear(sf::Color::Black);
        window.draw(Pixel);
        window.display();


        FPS++; //Calculating FPS and displaying it
        FPSTime = FPSClock.getElapsedTime();
        if(FPSTime.asSeconds() >= 1)
        {
            cout << "\nFPS: " << FPS << endl;
            FPSClock.restart();
            FPS = 0;
        }
    }

    return 0;
}

Thanks, and sorry for the late replies... I've been filling in college application forms...

 

anything