Bonjour !
Je me permet de relancer ce topic car je n'ai toujours pas réglé mon problème de performance pour l'application de shader globaux.
Avant tout, j'ai fais un gros travail d'optimisation dans le code. En effet, toute mes "bullets" font maintenant parties d'un seul sf::VertexArray que je met à jour à chaque frame. Aussi, tout mes systèmes de particules sont également rassemblé dans un seul sf::VertexArray.
En gros, je dois gagner environ 300/350 draw par frame (HUGE
).
Cependant, j'ai toujours un problème de chute de fps pour l'application de shader globaux. J'ai donc décidé de faire un exemple de code qui illustre ce problème.
Les shaders ne seront pas en std::string car il y a pas mal de code, ils sont donc en pièce jointe a mettre dans le même répertoire de le binaire.
#include <SFML/Graphics.hpp>
#include <sstream>
std::string intToString(const int &i)
{
std::stringstream ss;
ss << i;
return ss.str();
}
void loadShader(sf::Shader &pass1, sf::Shader &pass2)
{
pass1.loadFromFile("vertex.vert", "fragment.frag");
pass2.loadFromFile("vertex.vert", "fragment.frag");
pass1.setParameter("texture", pass1.CurrentTexture);
pass1.setParameter("pixelSize", 1.0f / (float)1920.0f,
1.0f / (float)1080.0f);
pass1.setParameter("pass", 0.0);
pass1.setParameter("range", 2.0);
pass1.setParameter("intensity", 1.0);
pass2.setParameter("texture", pass2.CurrentTexture);
pass2.setParameter("pixelSize", 1.0f / (float)1920.0f,
1.0f / (float)1080.0f);
pass2.setParameter("pass", 1.0);
pass2.setParameter("range", 2.0);
pass2.setParameter("intensity", 1.0);
}
sf::RenderTexture *applyShader(sf::RenderTexture &buffer1, sf::RenderTexture &buffer2,
sf::CircleShape &shape, sf::Text &fps,
sf::Shader &pass1, sf::Shader &pass2)
{
buffer1.clear();
buffer2.clear();
// Draw objects in first buffer
buffer1.draw(shape);
buffer1.draw(fps);
buffer1.display();
pass1.setParameter("textureBase", buffer1.getTexture());
pass2.setParameter("textureBase", buffer1.getTexture());
// Apply shader
buffer2.draw(sf::Sprite(buffer1.getTexture()), &pass1);
buffer2.display();
buffer1.draw(sf::Sprite(buffer2.getTexture()), &pass2);
buffer2.display();
return &buffer1;
}
int main(void)
{
sf::RenderWindow window(sf::VideoMode(1920, 1080), "Shader application, performance", sf::Style::Fullscreen);
// Buffers
sf::RenderTexture buffer1;
buffer1.create(1920, 1080);
sf::RenderTexture buffer2;
buffer2.create(1920, 1080);
// CircleShape
sf::CircleShape shape;
shape.setRadius(200);
shape.setPosition(1920.0f / 2.0f, 1080.0f / 2.0f);
shape.setOrigin(shape.getRadius(), shape.getRadius());
shape.setFillColor(sf::Color::Green);
// FPS
sf::Clock clock;
clock.restart();
int frame = 0;
sf::Font font;
font.loadFromFile("arial.ttf");
sf::Text fps("", font);
// Shaders
sf::Shader pass1;
sf::Shader pass2;
loadShader(pass1, pass2);
while (window.isOpen())
{
// Process events
sf::Event event;
while (window.pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
window.close();
}
// Clear
window.clear();
// FPS
if (clock.getElapsedTime().asSeconds() > 1.0f)
{
fps.setString("fps : " + intToString(frame));
clock.restart();
frame = 0;
}
// Shader version, comment this to desactivate shader
sf::RenderTexture *final = applyShader(buffer1, buffer2, shape, fps, pass1, pass2);
window.draw(sf::Sprite(final->getTexture()));
// No shader version, uncomment this to desactivate shader
//window.draw(fps);
//window.draw(shape);
window.display();
frame++;
}
return 0;
}
Sans shader, je tourne preque à 1000 fps (je viens de mettre à jour mes drivers graphiques).
Avec, je tombe à 60 fps.
J'ai déjà essayé d'utiliser des texture puissance de 2, le problème c'est que 1024*1024 c'est petit (donc pour scale à la taille de l'écran c'est moche), 2048*2048 c'est trop gourmand.
J'espère avoir été clair
.
Merci d'avoir pris le temps de lire mon post.
Cordialement