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

Author Topic: [Closed. Intended behaviour] Rendering bug when upscaling smoothed texture  (Read 2707 times)

0 Members and 1 Guest are viewing this topic.

santiaboy

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Hey guys, I think I found a bug when upscaling a smoothed texture. I tried replicating with a small example: The attached "upscalingBug.png" can be seen as three 64x64 squares. I render the middle square twice.

As far as I can see, if the RectangleShape is bigger than the textureRect it causes to render part of the neighbour if and only if the texture is smoothed. It results in this:



I saw a couple of threads in this vein, and those threads had movement and floating point error. I am rendering the squares on ints, and their size is ints.

Any idea what may be causing this? I thought about:
  • Something about smoothing texture and floating point arithmetic?
  • The image is wrong (unlikely as I tried a couple different, but hey it is a possibility)
  • This is "intented", as it is what OpenGL does.
  • An actual SFML bug

Cheers!

Example code:
#include <SFML/Graphics.hpp>

int main()
{
    int tilesize = 64;
    sf::RenderWindow window(sf::VideoMode(1280, 720), "upscaleBug?");

    sf::Texture texture;
    texture.loadFromFile("upscalingBug.png");
    ///Comment to watch the line dissapear
    texture.setSmooth(true);

    ///Setting up rectangles. Uncomment if you want to see 1:1 and 0.5:1
/*
    sf::RectangleShape rectSmall(sf::Vector2f(tilesize / 2,tilesize / 2));
    rectSmall.setPosition(50,50);
    rectSmall.setTexture(&texture);
    rectSmall.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));

    sf::RectangleShape rectSmall2(sf::Vector2f(tilesize / 2,tilesize / 2));
    rectSmall2.setPosition(82,50);
    rectSmall2.setTexture(&texture);
    rectSmall2.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));

    sf::RectangleShape rect(sf::Vector2f(tilesize,tilesize));
    rect.setPosition(50,100);
    rect.setTexture(&texture);
    rect.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));

    sf::RectangleShape rect2(sf::Vector2f(tilesize,tilesize));
    rect2.setPosition(114,100);
    rect2.setTexture(&texture);
    rect2.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));
*/

    sf::RectangleShape rectBig(sf::Vector2f(tilesize * 2,tilesize * 2));
    rectBig.setPosition(50,200);
    rectBig.setTexture(&texture);
    rectBig.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));

    sf::RectangleShape rectBig2(sf::Vector2f(tilesize * 2,tilesize * 2));
    rectBig2.setPosition(178,200);
    rectBig2.setTexture(&texture);
    rectBig2.setTextureRect(sf::IntRect(tilesize,0,tilesize,tilesize));

    ///Regular SFML Loop
    while (window.isOpen()){
        sf::Event event;
        while (window.pollEvent(event)){
            if (event.type == sf::Event::Closed)
                window.close();
        }

        window.clear(sf::Color::White);
        /*window.draw(rectSmall);
        window.draw(rectSmall2);
        window.draw(rect);
        window.draw(rect2);*/

        window.draw(rectBig);
        window.draw(rectBig2);
        window.display();
    }

    return 0;
}
 
« Last Edit: September 12, 2015, 07:45:06 pm by santiaboy »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Rendering bug when upscaling smoothed texture
« Reply #1 on: September 12, 2015, 12:56:09 am »
This is what happens when you tell OpenGL to apply bilinear filtering to textures. It will sample neighbouring texels as well when applying the texture to the primitive. If you don't want this to happen, either add a transparent border around each element in your texture or just place them in their own separate textures, or you could just disable smoothing.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

santiaboy

  • Full Member
  • ***
  • Posts: 118
    • View Profile
Re: Rendering bug when upscaling smoothed texture
« Reply #2 on: September 12, 2015, 01:49:54 am »
Is there a reason why it only "happens" if the rectangle size is larger than texture rect? Is it because it actually happens all the time, but it doesn't render to the screen because it's less than 1 pixel width?


binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Rendering bug when upscaling smoothed texture
« Reply #3 on: September 12, 2015, 03:28:53 pm »
When mapping a texture in OpenGL, there are 2 options to choose from when the texture is smaller than the actual object it is applied to: either it is repeated, or the edges are clamped and the pixels around the edges are used to "extend" the texture infinitely.

The important thing to remember is that what I just said applies to whole textures. OpenGL doesn't have any concept of specifying texture source rectangles like SFML does. All of that is done in SFML by translating your rectangle to texture coordinates. If your object is larger than the source rectangle, OpenGL just goes: "Hmm... well there is more texture data beyond what was specified using those coordinates, so I'll just use that instead of clamping or repeating.". OpenGL doesn't "see" the rectangle you specify. All it understands is that we are applying a part of the whole texture to a primitive. If that part is too small, it will just extrapolate by itself if there is more data available.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).