SFML community forums

Help => Graphics => Topic started by: cire on October 14, 2012, 02:41:23 am

Title: Unexpected result using sf::Lines primitive.
Post by: cire on October 14, 2012, 02:41:23 am
I'm not sure why the 'gaps' appear when I'm using the code below.  At first I thought perhaps it might be some float rounding thing, but that doesn't seem to be the case.


You can see the gaps (black lines) here:
(http://imageshack.us/a/img203/3576/liness.png)


Here is the (minimal, compilable) code that produces it on my system.  You'll have to pardon the naming style mismatch.

#include <SFML/Graphics.hpp>

const unsigned win_height = 600 ;
const unsigned win_width  = 800 ;
const unsigned line_height = 300 ;

void draw_vertical_line(sf::RenderTexture& t, unsigned x) ;
void update_texture(sf::RenderTexture& t) ;
void wait_for_close(sf::RenderWindow& window) ;

int main()
{
    sf::RenderWindow window(sf::VideoMode(win_width, win_height), "Vertical Lines") ;

    sf::RenderTexture texture ;
    if (texture.create(win_width, win_height))
    {
        update_texture(texture) ;
        window.clear() ;
        window.draw(sf::Sprite(texture.getTexture())) ;
        window.display() ;
    }
    wait_for_close(window) ;
}

void draw_vertical_line(sf::RenderTexture& t, unsigned x)
{
     sf::VertexArray line(sf::Lines, 2) ;

    line[0].position = sf::Vector2f(x, win_height) ;
    line[1].position = sf::Vector2f(x, win_height - line_height) ;
    line[0].color = line[1].color = sf::Color(0, 255, 256 * x / win_width) ;

    t.draw(line) ;
}

void wait_for_close(sf::RenderWindow& window)
{
    sf::Event event ;

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

void update_texture(sf::RenderTexture& t)
{
    t.clear() ;
    for ( unsigned i=0; i<win_width; ++i)
        draw_vertical_line(t, i) ;
    t.display() ;
}

Can anyone see what I'm doing wrong here?



Title: Re: Unexpected result using sf::Lines primitive.
Post by: Laurent on October 14, 2012, 09:02:32 am
It works perfectly for me, so this might be a driver issue. Make sure that your graphics drivers are up to date.

You can also try to add 0.5 to your the x coordinates of your lines.
Title: Re: Unexpected result using sf::Lines primitive.
Post by: Laurent on October 14, 2012, 09:05:30 am
By the way, your code would be much more efficient like this:
void draw_vertical_line(sf::RenderTexture& t, unsigned x)
{
    sf::Color color(0, 255, 256 * x / win_width);

    sf::Vertex lines[2] =
    {
        sf::Vertex(sf::Vector2f(x + 0.5f, win_height), color),
        sf::Vertex(sf::Vector2f(x + 0.5, win_height - line_height), color)
    };

    t.draw(lines, 2, sf::Lines) ;
}

This way you avoid allocating a small amount of heap memory on every call.
Title: Re: Unexpected result using sf::Lines primitive.
Post by: cire on October 14, 2012, 10:58:35 am
The drivers did need updating (in fact, they jumped up a major version,) but unfortunately it didn't resolve the problem.  Adding .5 to the x value does mask the problem though, so I can work with that for the time being.  It does have me wondering how else the problem might manifest.

That version of the function is certainly cleaner, but I don't think there's actually any heap memory involved is there?  It avoids calling the default constructor for the objects in the lines array in favor of direct initialization, but heap?  Maybe I'm misunderstanding.

In the "real" code,  the function looks a bit different.

Thanks for the assist!
Title: Re: Unexpected result using sf::Lines primitive.
Post by: Nexus on October 14, 2012, 11:20:58 am
sf::VertexArray is an encapsulated std::vector<sf::Vertex>, i.e. it allocates a dynamic array. When you have only few elements and you know in advance how many, a static array is more appropriate.

I however would use std::array (http://en.cppreference.com/w/cpp/container/array) (or std::tr1::array, if you don't have C++11): It is much safer, more comfortable, and as efficient as C arrays.
std::array<sf::Vertex, 2> lines =
{
    sf::Vertex(sf::Vector2f(x + 0.5f, win_height), color),
    sf::Vertex(sf::Vector2f(x + 0.5, win_height - line_height), color)
};

t.draw(lines.data(), lines.size(), sf::Lines);
Title: Re: Unexpected result using sf::Lines primitive.
Post by: Laurent on October 14, 2012, 11:36:58 am
Quote
Adding .5 to the x value does mask the problem though
It doesn't mask it, it solves it. Since your lines are 1-pixel wide, their position must be the center of the pixels so that they cover them completely.
Title: Re: Unexpected result using sf::Lines primitive.
Post by: cire on October 14, 2012, 01:54:50 pm
Quote from: Nexus
sf::VertexArray is an encapsulated std::vector<sf::Vertex>, i.e. it allocates a dynamic array.

Aha.  For some reason the array type didn't even occur to me.  Now that you point it out, it's pretty obvious.  Thanks!


Quote from: Laurent
It doesn't mask it, it solves it. Since your lines are 1-pixel wide, their position must be the center of the pixels so that they cover them completely.

That's good news, then!   :D