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

Author Topic: Sprite alignment with shrunk view  (Read 2733 times)

0 Members and 1 Guest are viewing this topic.

Avonclese

  • Newbie
  • *
  • Posts: 7
    • View Profile
Sprite alignment with shrunk view
« on: July 15, 2016, 04:12:33 pm »
Hello!

I thought I would ask a quick question to see if there is an alternative solution to my problem.

In a nutshell:

Game is isometric, contains objects which fit together per-pixel to create seamless walls/tilemaps/environments etc.
Native game resolution is 800x600 (an arbitrary value for the purposes of this discussion).
Users can change the resolution to suit their device, and my code uses sf::View to scale everything nicely.

The problem is that when the user goes above or below the native resolution, View seems to scale each object individually? So as the picture shows, these 2 wall objects no longer appear seamless when the user sets their resolution to 640x480.

My only successful solution so far is to render everything to an off-screen texture, where things draw perfectly in native resolution, and then draw that to the window.  Looks perfect but the entire process is CPU/GPU consuming to perform every frame, so I'm looking for alternatives.

FYI:
 - the 2 wall objects are being drawn in a single call via vertex array
 - texture smoothing on or off has absolutely no impact on the image

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Sprite alignment with shrunk view
« Reply #1 on: July 15, 2016, 04:17:55 pm »
Quote
Looks perfect but the entire process is CPU/GPU consuming to perform every frame, so I'm looking for alternatives.
I wouldn't say that, since it is just an extra sprite to draw. Or maybe you're making it more complicated than needed?
Laurent Gomila - SFML developer

Avonclese

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Sprite alignment with shrunk view
« Reply #2 on: July 16, 2016, 03:25:47 am »
It's possible I am over-complicating it, I'm not an expert so I may be missing something obvious! If you don't mind looking, here is a quick snippet of my canvas (offscreen texture) code I use to achieve the desired results. You say it's just an extra sprite to draw, but I thought it was a lot more?

//Clear the canvas
canvas.clear(Color::Black);                             //equivalent to drawing an entire window of pixels?

//Here I would draw all my things - normally to the window but needs to be the canvas now.  No change between techniques.
canvas.draw(stuff);

//Display the canvas
canvas.display();                                       //seems to be taxing to the framerate?

//Window clear, draw canvas sprite, and display
window.clear(Color::Black);                             //equivalent to drawing an entire window of pixels?
window.draw(canvas_sprite);                             //draws an entire window of pixels
window.display();                                       //as above
 

In a normal renderwindow-only setup, I just have the last 3 lines (except drawing objects instead of the canvas sprite), achieving ~500fps.  With the canvas code it drops to 250fps, even with no object drawing (only 2 tiny objects so I'm not surprised). So is the canvas process alone adding 3 extra full window pixel fills for the gpu, I think?  I was expecting some performance hit, but not this much.

I'm not particularly upset with the outcome, I'm mainly curious if I missed something obvious?

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: Sprite alignment with shrunk view
« Reply #3 on: July 16, 2016, 06:53:40 am »
The performance hit vary depending on your graphic card.

But think that, the more pixel you draw, the more time it will take.

500 fps = 1/500 = 0.002 render time per frame.
250 fps = 1/250 = 0.004 render time per frame.

More info here.

Only its take twice of render time to complete each frame.

But remember to test performance on release mode and all optimizations enabled in you compiler.

But if you read the sfml view's tutorial carefully you can solve your problem without having to use a RenderTexture.
I would like a spanish/latin community...
Problems building for Android? Look here

Avonclese

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Sprite alignment with shrunk view
« Reply #4 on: July 16, 2016, 08:10:58 am »
Thanks DarkRoku for the link about FPSvsTime, I have a much better understanding of that now. Great resource!

I have read the view tutorial very carefully (I even spotted the incorrect values in the code examples) I'm not sure what I have missed? :(

I want the user to see the exact same amount of the world at ANY resolution.
I set my View size to 800x600.  I call this my native resolution and will never change because I only want them to see 800x600 of the world, ever.
So when I play the game in windowed 640x480 it will take my larger View size and squash it into the window.
Likewise if they set the resolution to 1920x1080, thanks to View it will stretch the 800x600 size into the window (yes the aspect ratio will be wrong).

This is a great system and works perfectly, until I add my isometric objects. When it stretches or squashes...I get the artifacting in the picture of my original post.
How can I solve this using only Views?

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Sprite alignment with shrunk view
« Reply #5 on: July 16, 2016, 08:42:04 am »
How about drawing to a 800x600 rendertexture first. Then when everything in the frame is drawn, draw the rendertexture to the screen using the view.

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: Sprite alignment with shrunk view
« Reply #6 on: July 16, 2016, 08:51:06 pm »
The trick is.

If your window is smaller than your view's size: Things affected by the view will seems to be smaller. (zoom out)
If your window is bigger than your view's size: Things affected by the view will seems to be bigger. (zoom in)
If your window is the same size than your view's size: no zoom.

If you want to zoom in the view, without change the view size.
Use the zoom method:
float zoom = 2.0f ;
view.zoom( 1.0f / zoom ) // Zoom in.
view.zoom( zoom ) // Zoom out.
 

Anothers views methods here.
« Last Edit: July 16, 2016, 08:56:58 pm by DarkRoku »
I would like a spanish/latin community...
Problems building for Android? Look here

Avonclese

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: Sprite alignment with shrunk view
« Reply #7 on: July 17, 2016, 04:27:02 am »
Jesper, yes in my original post I described that my current solution is to use a RenderTexture. Visually it's perfect but I was concerned about the performance hit, I think it's not a big issue now :)

DarkRoku I have experimented with zooming but I wasn't able to find a solution that solves my issue :(  Thank you for your help I really appreciate it!

If anyone is curious I thought I would share my very small basic example to illustrate my problem. Hit Q to switch between window only and rendertexture.  If anyone if bored enough to check it out I'm always open for feedback. Thanks everyone!

//in main.cpp
#include <SFML/Graphics.hpp>

//program entry point and loops
int main(int argc, char* args[]){
    //view setup
    sf::Vector2f native_res={800,600};
    sf::View view;
    view.setSize(native_res);
    view.setCenter(native_res.x/2,native_res.y/2);

    //window setup
    sf::Vector2f user_res={640,480};
    sf::RenderWindow window(sf::VideoMode(user_res.x, user_res.y),"View testing",sf::Style::Titlebar|sf::Style::Close);

    //apply view with zoom here??
    //float zoom=native_res.x/user_res.x; //assumes matching ratios
    //view.zoom(zoom);

    //apply view
    window.setView(view);

    //textures
    sf::Texture walltex;
    sf::Texture backingtex;
    walltex.loadFromFile("wall.png");
    backingtex.loadFromFile("backing.png");
    walltex.setSmooth(true);
    backingtex.setSmooth(true);

    //sprites
    sf::Sprite backing(backingtex);
    sf::Sprite wall1(walltex);
    sf::Sprite wall2(walltex);
    wall1.setPosition(100,100);
    wall2.setPosition(132,116);

    //off-screen canvas via rendertexture
    sf::RenderTexture canvas;
    canvas.create(native_res.x,native_res.y);
    canvas.setSmooth(true);
    sf::Sprite canvas_sprite(canvas.getTexture());

    //loop
    bool drawcanvas=true;
    while(window.isOpen()){
        //sole event check for closing window
        sf::Event event;
        while(window.pollEvent(event)){
            if(event.type==sf::Event::Closed){
                window.close();
            }
            if(event.type==sf::Event::KeyPressed){
                if(event.key.code==sf::Keyboard::Q){
                    drawcanvas=!drawcanvas;
                }
            }
        }
        if(drawcanvas==true){
            //WINDOW ONLY DRAWS
            window.clear(sf::Color::Black);
            window.draw(backing);
            window.draw(wall1);
            window.draw(wall2);
            window.display();
        } else {
            canvas.clear(sf::Color::Black);
            canvas.draw(backing);
            canvas.draw(wall1);
            canvas.draw(wall2);
            canvas.display();
            window.clear(sf::Color::Black);
            window.draw(canvas_sprite);
            window.display();
        }
    }
    return 0;
}
 

DarkRoku12

  • Full Member
  • ***
  • Posts: 203
  • Lua coder.
    • View Profile
    • Email
Re: Sprite alignment with shrunk view
« Reply #8 on: July 17, 2016, 06:14:54 am »
I tested your code, probably its a openGL related theme.
Zoom its not perfect, even less when things are too shorts.

But if the RenderTexture phase does not affect the gameplay don't worry if yes, enable and option to eliminate it, like you did in the example.

I would like a spanish/latin community...
Problems building for Android? Look here

 

anything