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

Author Topic: How to use shaders more efficiently in c++/sfml?  (Read 4576 times)

0 Members and 1 Guest are viewing this topic.

loubeasley

  • Newbie
  • *
  • Posts: 4
    • View Profile
How to use shaders more efficiently in c++/sfml?
« on: September 03, 2016, 11:34:23 am »
I'm working on a sort of ascii canvas for a game. I assumed it would be more efficient to to use a spritesheet of ascii glyphs in cp437 style to draw the ascii art. I needed a way to color the background and foreground of the glyphs so I'm using a fragment shader. Using the shader drops me to 7 fps. Not using the shader, I get about 131.

Am I doing something incorrectly? Is it just too expensive to loop through a vector of strings (and each character in the string), calculate the position of the glyph on the sheet, set the texture position, and then draw the sprite with a shader for each character?

int main() {
        sf::RenderWindow renderWindow(sf::VideoMode(1280, 720), "Demo Game");
       
        sf::Texture texture;
        texture.loadFromFile("Resources/courier_8x16.png");
        texture.setSmooth(false);
        sf::Sprite sprite(texture);
        sf::Shader shader;
        m_shader.loadFromFile("cycle.frag", sf::Shader::Fragment);
        m_shader.setUniform("texture", sf::Shader::CurrentTexture);
       
        sf::Clock clock;
        sf::Time timeSinceLastUpdate = sf::Time::Zero;
       
        std::vector<std::string> chars = std::vector<std::string>(50, std::string(100, 'X'));
        while (renderWindow.isOpen())
        {
                processEvents();

                timeSinceLastUpdate += clock.restart();

                while (timeSinceLastUpdate > TimePerFrame)
                {
                       
                        timeSinceLastUpdate -= TimePerFrame;
                        processEvents();
                        update(TimePerFrame);
                }
               
                //render();
        renderWindow.clear();
                for (int y = 0; y < chars.size(); y++)
                {
                        for (int x = 0; x < chars[y].size(); x++)
                        {
                                //bg and fg colors will be in a 2D vector and used here
                                shader.setUniform("foreground", sf::Glsl::Vec4(std::Color.White));
                                shader.setUniform("background", sf::Glsl::Vec4(std::Color.Black));
                               
                                //uses decimal value of char and dimensions
                                //to find location of appropriate glyph in sprite sheet
                                sprite.setTextureRect(sf::IntRect((chars[y][x] % 16) * 8, (chars[y][x] / 16) * 16, 8, 16));
                                sprite.setPosition(x * 8, y * 16);
                               
                                renderWindow.draw(sprite, &shader);
                        }

                }
        renderWindow.display();
               
        }
       
       
}

shader code:

uniform vec4 foreground;
uniform vec4 background;
uniform sampler2D texture;



void main()
{
        vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
        if (pixel.r < .1)
                pixel = background;
        else
                pixel = foreground;
                               
        gl_FragColor = pixel;
}

Here's the sprite sheet: (all the paragraph symbols are just placeholders)

« Last Edit: September 03, 2016, 11:36:53 am by loubeasley »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to use shaders more efficiently in c++/sfml?
« Reply #1 on: September 03, 2016, 08:45:10 pm »
Not sure exactly what you're trying to do but it does seem like you're drawing many sprites to represent a multitude of characters in a grid. Is that right?

Firstly, I'd highly recommend using a single vertex array instead of so many sprites and draw everything at once with just one call.

Secondly, you might find a lot of use out of Selba Ward's Console Screen. It already does what you seem to be looking for.
e.g.



There is even a simple tutorial to get you started ;)
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

loubeasley

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to use shaders more efficiently in c++/sfml?
« Reply #2 on: September 03, 2016, 09:13:42 pm »
Thank you for the link. This is exactly what I'm trying to do. I will definitely try it out.   :)

loubeasley

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to use shaders more efficiently in c++/sfml?
« Reply #3 on: September 03, 2016, 11:20:33 pm »
Can you possibly point me in the direction of how to build the library so I can link it in my project?

Edit: I was able to make it work by adding the entire library to my project working directory. However, I feel like this set up is kind of messy.
« Last Edit: September 04, 2016, 12:46:45 am by loubeasley »

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to use shaders more efficiently in c++/sfml?
« Reply #4 on: September 05, 2016, 09:44:55 pm »
How you build is dependant on your toolchain. Are you using an IDE? Which one?

To build the entire collection, build it all together - separated from your project.
It will need to built as a library, not as an executable.
Then, include and link to the source/built library files as you would with other libraries (such as SFML).

If you would prefer to throw the source into your project and build it with it, you don't need the entire collection. No drawables require other drawables so you can just add the drawable that you want to use. However, as explained in the Setup section of Selba Ward's wiki, all drawables require the "Common.hpp" and "Exception.hpp" headers so you can include any drawable without the others as long as those two headers are also included (they're both small). I've combined the two recently so when I get chance to upload the update, only one of these headers will be required :) [EDIT] all drawables require the "Common.hpp" header so you can include any drawable without the others as long as that header is also included (it is small) :)

Hope that answers your questions and I hope you enjoy the collection ;)

Feedback is always welcome. There is a Selba Ward thread here on the SFML forums if you have any further problems or suggestions.
« Last Edit: September 08, 2016, 10:19:48 pm by Hapax »
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

loubeasley

  • Newbie
  • *
  • Posts: 4
    • View Profile
Re: How to use shaders more efficiently in c++/sfml?
« Reply #5 on: September 11, 2016, 12:28:02 pm »
I just now noticed your reply. I appreciate it.

I am using Visual Studio 2015.

The console screen is very quick! I am impressed. I was able to get about 30 fps on a grid of 150x50 characters (7x12 pixels for each character) running the crash method on every iteration of the game loop.

It's kind of ironic how taxing using ASCII graphics can be if you aren't careful with all the nested loops.  :P

Thanks again! If I stick with SFML and C++, I will definitely be using this.

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: How to use shaders more efficiently in c++/sfml?
« Reply #6 on: September 12, 2016, 02:37:07 pm »
Thanks. I'm glad you like it! I use it myself all the time ;) It often grows when I use it and think of something else I'd like it to do so if you have suggestions, I'll certainly look into them :)

"Crash" is probably a good test of speed as it might just be one of the slowest things it does - randomising every cell in the screen. It was not supposed to be called every cycle (it was actually just a test method that I really liked) but if you need it, it's there!

If I stick with SFML and C++...
Why wouldn't you? :P

Remember to try out some other Selba Ward drawables too; they can help with some commonly required things. Console Screen is definitely the most featureful, of course. Did you end up managing to build it as a library?
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*