today i tried to get the fragment shader to draw multiple lasershots at different positions at the same time.
this is how it looks like:
i just love it!
However i noticed a heavy fps-drop when shooting some more of those little lasers.
so i refactored the program using sprites and textures (as suggested by Laurent).
I created a small laser-texture and tried to get is as close as possible to the shader-variant i already got.
It looks like this:
The performance-difference is quite drastic:
shader-version: 61 fps at 0 shots
shader-version: 37 fps at 100 shots
texture-version: 61 fps at 0 shots
texture-version: 61 fps at 1860 shots
Basically after 100 Shots i lost almost half of the performance :-(
i implemented the shader-based solution basically this way:
main.cpp
int main(){
sf::RenderWindow window(sf::VideoMode(800, 600), "Radial Gradient", sf::Style::Default);
//the rect thats used for drawing the shader
sf::VertexArray renderRect{sf::PrimitiveType::Quads, 4 };
renderRect.append(sf::Vertex{sf::Vector2f{0.f,0.f}});
renderRect.append(sf::Vertex{sf::Vector2f{0.f,600.f}});
renderRect.append(sf::Vertex{sf::Vector2f{800.f,600.f}});
renderRect.append(sf::Vertex{sf::Vector2f{800.f,0.f}});
sf::Sprite playerSpaceship;
std::vector<Projectile> projectiles;
//...
//...some setup-code
//...
if(keyPressed()) projectiles.push_back(Projectile{sf::Vector2f{playerSpaceship.getPosition()},renderRect, shader});
for(auto& i: projectiles) {
i.update(sf::seconds(fixedFrameTime));
}
window.clear(sf::Color{0,40,60,255});
for(auto& i: projectiles) {
window.draw(i);
}
window.draw(sprite);
window.display();
}
return EXIT_SUCCESS;
}
Projectile.hpp
class Projectile : public sf::Drawable{
public:
Projectile(sf::Vector2f position, sf::VertexArray& rect, sf::Shader& shader);
void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
void update(const sf::Time& dt);
private:
sf::VertexArray& mRectShape;
sf::Shader& mShader;
sf::Vector2f mPosition;
};
Projectile.cpp
Projectile::Projectile(sf::Vector2f position, sf::VertexArray& rect, sf::Shader& shader)
: mPosition(position), mRectShape(rect),mShader(shader) {}
void Projectile::draw(sf::RenderTarget& target, sf::RenderStates states) const {
states.shader = &mShader;
mShader.setParameter("laserPos", mPosition);
mShader.setParameter("resolution", sf::Vector2f{800.f,600.f});
target.draw(mRectShape, states);
}
void Projectile::update(const sf::Time &dt) {
mPosition.y -= 50.f * dt.asSeconds();
}
the bottleneck seems to be drawing the sf::VertexArray for each projectile. Exchanging the sf::VertexArray with a sf::RectangleShape has the same effect on performance. Drawing the sf::VertexArray or sf::RectangleShape without any Shader-Calculations (like: target.draw(rectShape) omitting "states" as an Argument) has the same performance-consuming effect, so im pretty sure the performance drop is due to the overall design using one sf::RectangleShape /sf::VertexShape for drawing alle the projectiles :-/