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

Author Topic: Graphical glicth: horizontal lines in SFML2  (Read 4887 times)

0 Members and 1 Guest are viewing this topic.

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
Graphical glicth: horizontal lines in SFML2
« on: August 19, 2011, 01:38:43 pm »
Hello!

The level is made of 32x32 sprites, and they all share a texture (a tileset). I use no smoothing on the texture, but a camera (a view) to adjust where to render the tilemap.

Sometimes it renders with a horizontal lines under the tiles (see the screenshot), and this glitch remains while moving the camera horizontally.



I guess it's related to the floating-point rendering, how can I avoid it?

Thanks in advance,
easy

P.S. My operating system is Linux Mint Debian.

Haikarainen

  • Guest
Graphical glicth: horizontal lines in SFML2
« Reply #1 on: September 05, 2011, 02:52:52 pm »
Same issue here: http://sfml-dev.org/forum/viewtopic.php?p=37862, found this after i posted other. Laurent please do something!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Graphical glicth: horizontal lines in SFML2
« Reply #2 on: September 05, 2011, 02:55:47 pm »
It's a known limitation of the rendering system in SFML 2, you must use integer coordinates to get a pixel perfect rendering. Unfortunately this is very hard to achieve with a custom view: it's not the coordinates in the 2D scene that must be integer, but the coordinates after being transformed by the current view. The simplest workaround is to manage to keep the view at integer coordinates too.
Laurent Gomila - SFML developer

Haikarainen

  • Guest
Graphical glicth: horizontal lines in SFML2
« Reply #3 on: September 05, 2011, 03:04:02 pm »
Quote from: "Laurent"
It's a known limitation of the rendering system in SFML 2, you must use integer coordinates to get a pixel perfect rendering. Unfortunately this is very hard to achieve with a custom view: it's not the coordinates in the 2D scene that must be integer, but the coordinates after being transformed by the current view. The simplest workaround is to manage to keep the view at integer coordinates too.


So you're saying its either smooth movement och proper drawing ? :/ Is there any upcoming fix  for this ? Like a .. sf::View::ForceInteger(true); or something?

Guess ill have to go back to saving each tile as a separate image for now.

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
Graphical glicth: horizontal lines in SFML2
« Reply #4 on: September 05, 2011, 03:09:46 pm »
Thanks Laurent!

So the solution is:
- To have a vector for smooth movement: "sf::Vector2f cameraPosition;"
- And to convert floats to integers when repositioning the view: "view.setCenter(sf::Vector2i(cameraPosition));"

That will work! :)

Haikarainen

  • Guest
Graphical glicth: horizontal lines in SFML2
« Reply #5 on: September 05, 2011, 03:13:26 pm »
Quote from: "easy"
Thanks Laurent!

So the solution is:
- To have a vector for smooth movement: "sf::Vector2f cameraPosition;"
- And to convert floats to integers when repositioning the view: "view.setCenter(sf::Vector2i(cameraPosition));"

That will work! :)


It does not for my case tho, since i magnify the view 2x, so the following will be really choppy. Tested this, also, it would work if i used integer types for playermovement as well, but i really need float types for precise hw-independent movement/collision detection etc.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Graphical glicth: horizontal lines in SFML2
« Reply #6 on: September 05, 2011, 03:16:24 pm »
Quote
So you're saying its either smooth movement och proper drawing ?

Absolutely.

Quote
Is there any upcoming fix for this ? Like a .. sf::View::ForceInteger(true); or something?

There's no possible fix, it depends on:
- the entity's transformations
- the view
- the viewport

Quote
So the solution is:
- To have a vector for smooth movement: "sf::Vector2f cameraPosition;"
- And to convert floats to integers when repositioning the view: "view.setCenter(sf::Vector2i(cameraPosition));"

That should work, but be careful with odd sizes, since the view's position is its center, maybe you need a +0.5 sometimes.
Laurent Gomila - SFML developer

Haikarainen

  • Guest
Graphical glicth: horizontal lines in SFML2
« Reply #7 on: September 05, 2011, 03:25:47 pm »
Ohwell, conclusion; If you are in the same position I am in, do what I just did;
Cache your tiles with as an sf::Texture that is WHOLE of your tile(part of your tileset), and just draw that instead. Took the opportunity to fit this into my Tile::GenerateCache() (for collisionmap etc), it eats a little bit more memory but for these kind of projects it should be all right!

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
Graphical glicth: horizontal lines in SFML2
« Reply #8 on: September 05, 2011, 03:58:36 pm »
Quote from: "Laurent"
That should work, but be careful with odd sizes, since the view's position is its center, maybe you need a +0.5 sometimes.


Thanks for the hint!

Quote from: "Haikarainen"
Ohwell, conclusion; If you are in the same position I am in, do what I just did;
Cache your tiles with as an sf::Texture that is WHOLE of your tile(part of your tileset), and just draw that instead. Took the opportunity to fit this into my Tile::GenerateCache() (for collisionmap etc), it eats a little bit more memory but for these kind of projects it should be all right!


I've got all my tile textures on one tileset texture already, and all the sprites has this large texture applied, and I call .SetSubRect on them. So just packing all the small textures into a big one does not help; you'll need to do the convert-to-integer trick above.

Haikarainen

  • Guest
Graphical glicth: horizontal lines in SFML2
« Reply #9 on: September 05, 2011, 04:12:25 pm »
Quote from: "easy"

I've got all my tile textures on one tileset texture already, and all the sprites has this large texture applied, and I call .SetSubRect on them. So just packing all the small textures into a big one does not help; you'll need to do the convert-to-integer trick above.


Well I explained above why I cant use the integertrick, also it works kinda fine . Resource for textures loads in the tilesheet, every tile from that sheet caches their tile as a texture. No big graphics were talking here.

easy

  • Full Member
  • ***
  • Posts: 146
    • MSN Messenger - easy82.contact@gmail.com
    • View Profile
    • Email
Graphical glicth: horizontal lines in SFML2
« Reply #10 on: September 05, 2011, 04:26:55 pm »
Here comes my solution:

Code: [Select]
/* Hack to get rid of the annoying horizontal and vertical
   lines that are caused by floating point rendering */

sf::Vector2f correction = sf::Vector2f((int(view.GetSize().x) % 2 == 0 ? 0 : 1) * 0.5f,
                                       (int(view.GetSize().y) % 2 == 0 ? 0 : 1) * 0.5f);

view.SetCenter(floor(position.x) + correction.x, floor(position.y) + correction.y);


This works, and the choppiness of the movement is barely noticable.

Quote
Well I explained above why I cant use the integertrick, also it works kinda fine . Resource for textures loads in the tilesheet, every tile from that sheet caches their tile as a texture. No big graphics were talking here.


Oh then I've misunderstood you. I thought you're talking about using a tileset texture. But honestly I still don't get it what you're doing :D

zeruel

  • Newbie
  • *
  • Posts: 4
    • View Profile
Graphical glicth: horizontal lines in SFML2
« Reply #11 on: October 31, 2011, 06:47:37 pm »
Hello everyone, this is my first post. I've been using SFML for a while now and I love it. Thanks for your hard work, Laurent.

I have this unwanted line problem also. I'm confused as to what I need to do. Using easy's advice to convert the view to integer coordinates doesn't work for me. And Haikarainen, I don't understand what you have suggested. Could you clarify please?

My view never moves. I render my game at 1280x720 and use the view to scale it up or down, depending on the resolution. Here is where I set my view:

Code: [Select]
MainView->Reset(sf::FloatRect(0, 0, 1280, 720));
MainView->SetViewport(sf::FloatRect(0.0f, 0.0f, 1.0f, 1.0f));
MainWindow->SetView(*MainView);


That never changes. I get the lines when I'm not rendering to a native 1280x720 resolution or window size. Does that mean I'm out of luck? Is there any hack I can apply? Am I doing this completely wrong and should I be using another technique instead of using the view to scale my game?

Edit: I just looked into RenderTexture. Would this be the correct way? I could render the entire scene into a texture and then scale that to the window? Would there be a performance hit for that?

Edit again: I just tried the RenderTexture. It was so easy to change over. It works perfect now. I can scale my game to any resolution without the lines showing up. I'd still like to know if I have the right idea though.

codergopher

  • Newbie
  • *
  • Posts: 1
    • View Profile
    • Email
Re: Graphical glicth: horizontal lines in SFML2
« Reply #12 on: December 16, 2019, 01:11:01 am »
Hey everybody! I know this thread is quite old, but I found a solution that solves the problem perfectly, while maintaining floating point movement.

Laurent suggested that we round our movements units to ints in order to achieve pixel perfect rendering, and (s)he is about half right.

Rounding to ints works if we haven't zoomed our view at all, because at this point

1 pixel = 1 movement unit

Sounds simple, right?
Well, this all craps the bed if we zoom in our view, let's say by 4.

view.zoom(1/4.f);

What we've just done here is made the width and height of each pixel = 4 pixels. As a result of that,

1 movement unit = 4 pixels

or

1 pixel = .25 movement unit

If we were to say

player.move(1, 0);

our player would actually move 4 pixels to the right instead of just 1. This looks choppier than a hyperventilating  ninja on redbull. Here's where we need floating point precision so that we can move our player 1 pixel at a time instead of 4. Now,

1 pixel = .25 movement unit

So if we wanted to move our player just 1 pixel to the right, we would say

player.move(.25, 0);

But what happens if our players movement isn't exactly equal to the amount required to move 1 pixel?

ie

player.move(.16, 0);

In that case, our view might draw the player at the screen pixel location of 0, 0 or 1, 0, depending on if we've moved our camera(sf::View) at any time in the game. If we went

view.setCenter(somenumber.14, someothernumber.0);

then it would place our player at 1, 0 because .16 +.14 = .31 which is > .25.
This is where the weird vertical lines come into play, because SFML isn't really sure in which pixel to place our scene.

To solve the problem, all we have to do is keep our movements at multiples of our scaling factor. In our case, we just round our movements to multiples of .25, which is 1/4, and this will achieve pixel perfect rendering.

To implement:

#include <bits/stdc++.h> //for fmod

float ZOOM_SCALE = 4;

sf::Vector2f roundVector2f(sf::Vector2f p_vector, float p_scale)
{
   sf::Vector2f diff = sf::Vector2f(fmod(p_vector.x, 1/p_scale), fmod(p_vector.y, 1/p_scale));
   p_vector.x -= diff.x;
   p_vector.y -= diff.y;

   return p_vector;
}

int main()
{
        //some code
        sf::View view(sf::Vector2f(0.f, 0.f), sf::Vector2f(1280, 720));
   view.zoom(1/ZOOM_SCALE);
       
        //if we move the camera
        sf::Vector2f camPos = sf::Vector2f(234.12, 434.45);
        view.setCentre(roundVector2f(camPos, ZOOM_SCALE);

        //if we move our player
        sf::Vector2f vel = sf::Vector2f(1.1, 2.6);
        player.move(roundVector2f(vel, ZOOM_SCALE);
}

Hope this helps :)