-
SOLUTION IS ON PAGE 3
I have had this bug for a while, but all my attempts to fix it have been null. I have a simple sf::View set up as a member of the player class, and here's some bits of code:
Game.cpp:
player -> Camera = window.getDefaultView();
Player.cpp:
void Player::updateCamera()
{
Camera.setCenter(pos); // pos is the position of the player
}
However when I zoom in the game, some pixels look distorted, you can see thin lines, wave pattern at the floor where there's only straight lines, etc.
(http://puu.sh/3I7zE)
-
It's hard to keep a pixel perfect rendering in this case: your world units no longer match the window's pixels, so OpenGL has to distort things to compensate.
There's no easy workaround, unfortunately. What you can do is to try different sizes for your view, and maybe you'll notice a rule for sizes that produce artifacts (typically, that would be non-integer or odd sizes), and avoid them.
-
It's hard to keep a pixel perfect rendering in this case: your world units no longer match the window's pixels, so OpenGL has to distort things to compensate.
There's no easy workaround, unfortunately. What you can do is to try different sizes for your view, and maybe you'll notice a rule for sizes that produce artifacts (typically, that would be non-integer or odd sizes), and avoid them.
I see, would there be any drastic change that I could do to keep a certain ratio in things? Surely someone must have had this problem before or there must be a cause
-
I forgot an important detail, which could be the problem!
My tiles are all 30x30. I'll try to make them 32x32 and get back to this thread to post the solution.
-
Distortions are unavoidable.
If your tiles are 32*32, when you zoom they are maybe displayed as 38*38, that's 6 rows and columns of new pixels so obviously the pixel patterns can't be the same.
You could allow only zoom values that keeps the pixel ratio where 32*32 tiles would become 64*64, then 96*96, etc. Pixel patterns would stay intact.
Or you could try to smooth them (using sf::Texture::setSmooth (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Texture.php#a0c3bd6825b9a99714f10d44179d74324)) but you may not like it.
-
OK I set the textures to 32:32, still the same distortion bug
-
There is literally no zoom level that actually doesn't make things distorted, I tried everything. Does anyone know the cause, or maybe a fix? :/
-
There is literally no zoom level that actually doesn't make things distorted
An exact x2 zoom doesn't give a perfect result?
-
There is literally no zoom level that actually doesn't make things distorted
An exact x2 zoom doesn't give a perfect result?
We have tried all sorts of methods, including just using a precise setSize, and we've set a very small scale for zooming so that we can find a good non-distorted version of the game as well but no results. We've tried zooming for a specific factor, like 2x, 3x, etc, but still, there is a noticeable distorsion. Changing the texture size to 32x32 did make things appear a bit better, but not by much.
-
You should try to reproduce this problem in a minimal app (just a sprite and a view). This way I (and others) can test it easily.
-
Okay, I've managed to reproduce this bug on a very small scale, it's not as serious as in the game but it's the same bug, you can clearly see a distortion when you zoom in or out. I didn't want to include our whole map system so I just made it load a picture of a map. I know it's not the same as a vertexarray, but it's as minimal as I can get.
-
I tested your code and I can't reproduce unexpected results.
The result is sometimes not a 1:1 rendering of the original image, but that's clearly because of what G. said.
If your tiles are 32*32, when you zoom they are maybe displayed as 38*38, that's 6 rows and columns of new pixels so obviously the pixel patterns can't be the same.
So, on my side, everything is ok.
-
Alright, I just thought that it wasn't supposed to be like that, because when I make the artwork and see it a bit distorted it ruins some of my plans.
-
Activating linear filtering (texture.setSmooth(true)) might give a better (smoother) result, but it would also ruin your pixel art.
-
We tried that, and it works, I'm not sure if we'll use the smoothening, we might just keep this small distortion right now, we're only worried because we plan to commercialize the game
-
A KISS solution would be just not to use zoom in pixel-art game and leave it for 3D games. It depends on the game design though.
-
A KISS solution would be just not to use zoom in pixel-art game and leave it for 3D games.
Not using the SFML view zooming functionality "for simplicity" is very questionable, I'm sure Octav has his reasons why he needs this feature. There are many use cases even for 2D games.
-
Yes, but zooming causes graphical glitches in pixel art. He wants to solve it and I just say that not using zoom is the simplest solution - sometimes we forget that we can remove a problematic feature and do great without it.
-
I wouldn't call "don't zoom" a solution to "how to avoid distortion when using zoom?". :D
-
You guys are saying this is normal, but just look at this image.
(http://puu.sh/3N0j2)
I want to release a game to a wider audience. Those are horizontal pixels. And no matter what I zoom, it stays distorted, we have tried the smallest scales possible. I have tried everything. There has to be a cause to this, because this is horrible. I spend hours on artwork, and to see it look like this in-game is so terrible :/
-
How are you drawing that? VertexArrays? Sprites? Something else?
-
How are you drawing that? VertexArrays? Sprites? Something else?
VertexArray. Also we tried setSmooth() but it doesn't help much. It still keeps some very ugly distorsion, it just messes it up even more.
void MapLayer::ConstructMap()
{
mapVertices.clear();
int index = 0;
int index_y = 0;
for(auto&& i : tileData)
{
for(auto&& j : i)
{
//====================================================================\\
// Figure showing the quad order. Important. \\
//====================================================================\\
// (up_l_point) (up_r_point) | \\
// +-----------+ | (1) (2) \\
// | | | +----+ \\
// | | | | | \\
// | | | +----+ \\
// | | | (4) (3) \\
// +-----------+ | \\
// (down_l_point) (down_r_point) | Order of the points \\
//====================================================================\\
// Declare 4 points of the quad
sf::Vertex up_l_point;
sf::Vertex up_r_point;
sf::Vertex down_r_point;
sf::Vertex down_l_point;
// Set their positions
up_l_point.position = sf::Vector2f((float)(index*tile_size), (float)(index_y*tile_size));
up_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size), (float)(index_y*tile_size));
down_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size), (float)(index_y*tile_size + tile_size));
down_l_point.position = sf::Vector2f((float)(index*tile_size), (float)(index_y*tile_size + tile_size));
// Set their texture bounding box
up_l_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size +0.5f, (j/tiles_per_row) * tile_size +0.5f);
up_r_point.texCoords = sf::Vector2f((j%tiles_per_row * tile_size) + tile_size-0.5f, (j/tiles_per_row) * tile_size+0.5f);
down_r_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size + tile_size-0.5f, (j/tiles_per_row * tile_size) + tile_size-0.5f);
down_l_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size +0.5f, (j/tiles_per_row * tile_size) + tile_size-0.5f);
mapVertices.append(up_l_point);
mapVertices.append(up_r_point);
mapVertices.append(down_r_point);
mapVertices.append(down_l_point);
index++;
}
index = 0;
index_y++;
}
}
-
Did you try adding and subtracting 0.5 to the positions like you do to textures so that positions too end with 0.5 and tile is tile_size-1.f wide and high?
-
Did you try adding and subtracting 0.5 to the positions like you do to textures so that positions too end with 0.5 and tile is tile_size-1.f wide and high?
Yes, I tried that as well, and the tile_size is 32x32
-
I mean like this so that it'd create 1:1 mapping between coordinates and texture pixels:
// Set their positions
up_l_point.position = sf::Vector2f((float)(index*tile_size) + 0.5f, (float)(index_y*tile_size)+0.5f);
up_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size)-0.5f, (float)(index_y*tile_size)+0.5f);
down_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size)-0.5f, (float)(index_y*tile_size + tile_size)-0.5f);
down_l_point.position = sf::Vector2f((float)(index*tile_size)+0.5f, (float)(index_y*tile_size + tile_size)-0.5f);
-
I mean like this so that it'd create 1:1 mapping between coordinates and texture pixels:
// Set their positions
up_l_point.position = sf::Vector2f((float)(index*tile_size) + 0.5f, (float)(index_y*tile_size)+0.5f);
up_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size)-0.5f, (float)(index_y*tile_size)+0.5f);
down_r_point.position = sf::Vector2f((float)(index*tile_size + tile_size)-0.5f, (float)(index_y*tile_size + tile_size)-0.5f);
down_l_point.position = sf::Vector2f((float)(index*tile_size)+0.5f, (float)(index_y*tile_size + tile_size)-0.5f);
That seems to produce a better result, however, it also creates a border between the tiles.
(http://puu.sh/3N1rQ.png)
-
:-\
What about removing all 0.5fs from both textures and positions?
-
:-\
What about removing all 0.5fs from both textures and positions?
Nope. Still horrible distorsion. Here's the code for my zooming:
if(sf::Keyboard::isKeyPressed(sf::Keyboard::F5) && zoomTimer < 0) {camera.zoom(0.9f); zoomTimer = 0.02f;}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::F6) && zoomTimer < 0) {camera.zoom(1.1f); zoomTimer = 0.02f;}
-
If it renders good with no zoom you could try to render it to a texture that has default view without zooms before drawing it to window with zoomed view, have you tried that?
-
If it renders good with no zoom you could try to render it to a texture that has default view without zooms before drawing it to window with zoomed view, have you tried that?
I don't quite understand this, however even without a zoom you can notice some strange graphical bugs
-
I don't quite understand this, however even without a zoom you can notice some strange graphical bugs
Then I really start to doubt, that it's an issue with SFML/OpenGL.
Are your graphics driver uptodate?
Can you put together a minimal and complete example that reproduces the problem, so we can test it on our own and see if it's related to your hardware, a mistake in the code or an actual OpenGL issue.
-
Can you try it with sf::Sprite, just to make sure there is no mistake in the computation of your texture and vertex coordinates?
Test it with the following code, store a single tile in the file "tile.png":
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(640, 480), "SFML Application");
window.setFramerateLimit(20);
sf::Texture texture;
texture.loadFromFile("tile.png");
sf::Sprite sprite(texture);
const float tileSize = texture.getSize().x;
sf::View view = window.getDefaultView();
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
return 0;
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::F)
view.zoom(1.f/0.9f);
else if (event.key.code == sf::Keyboard::D)
view.zoom(0.9f);
else if (event.key.code == sf::Keyboard::Escape)
return 0;
}
}
window.setView(view);
window.clear();
for (unsigned int x = 0; x < 10; ++x)
{
for (unsigned int y = 0; y < 10; ++y)
{
sprite.setPosition(x * tileSize, y * tileSize);
window.draw(sprite);
}
}
window.display();
}
}
You're aware that by using this approach, there will be rounding errors for the zoom? You should recompute the zoom factor based on an integer level, so that it is truly reversible.
-
I don't quite understand this, however even without a zoom you can notice some strange graphical bugs
Are your graphics driver uptodate?
Yes, and I don't work alone on this project, and my teammate and other people have had the same distorsion bug.
I don't quite understand this, however even without a zoom you can notice some strange graphical bugs
Can you put together a minimal and complete example that reproduces the problem, so we can test it on our own and see if it's related to your hardware, a mistake in the code or an actual OpenGL issue.
I already have, and it only uses a simple sprite, check page 1
-
Alright a person told me that for him, my code works fine, but he is using SFML 2.1 and I am using the old version. I will try to install 2.1 and get back to this thread.
-
I already have, and it only uses a simple sprite, check page 1
Oh I was looking for a code section and not a attachment. :D
Anyways, it works fine on my PC (AMD Radeon 7xxxM series) - except the obvious distortion when zooming out, due to the fact that not all pixel can be represented anymore.
I'm using my Nighlty Build, which is currently the same as SFML 2.1.
(http://i.imgur.com/NaBtADl.png)
(http://i.imgur.com/RCDOW6P.png)
Test it with the following code, store a single tile in the file "tile.png":
Works fine here as well.
-
Fixed it.
Earlier, I had this code:
// Set their texture bounding box
up_l_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size +0.5f, (j/tiles_per_row) * tile_size +0.5f);
up_r_point.texCoords = sf::Vector2f((j%tiles_per_row * tile_size) + tile_size-0.5f, (j/tiles_per_row) * tile_size+0.5f);
down_r_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size + tile_size-0.5f, (j/tiles_per_row * tile_size) + tile_size-0.5f);
down_l_point.texCoords = sf::Vector2f((j%tiles_per_row) * tile_size +0.5f, (j/tiles_per_row * tile_size) + tile_size-0.5f);
And removing 0.5f did the trick. Apparently that kills the whole thing. It wasn't a bug with the camera, it was a bug with the way I programmed the vertexarray. It looks perfect now. Thanks a lot everyone!
-
:-\
What about removing all 0.5fs from both textures and positions?
Nope. Still horrible distorsion.(...)
*grumble grumble* >:(
-
:-\
What about removing all 0.5fs from both textures and positions?
Nope. Still horrible distorsion.(...)
*grumble grumble* >:(
I'm sorry about that, silly mistake, because I didn't add the 0.5f and I didn't realize it was added to the X and Y coords. That position has two sizes, and I was only deleting the ones at the end, silly mistake ;D