#include <thread>
#include <system_error>
#include <vector>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <X11/Xlib.h>
class Camera: public sf::Drawable {
private:
sf::View const & view;
sf::RenderTexture buffer;
std::thread thread;
void draw(sf::RenderTarget& target, sf::RenderStates states) const override {
// fetch texture
sf::Sprite sprite{buffer.getTexture()};
// apply to target
target.setView(view);
target.draw(sprite, states);
};
public:
Camera(sf::View const & view)
: view{view}
, buffer{}
, thread{} {
sf::Vector2u size{view.getSize()};
buffer.create(size.x, size.y);
}
void render(std::vector<sf::Drawable*> const & scene, sf::RenderStates states=sf::RenderStates{}) {
thread = std::thread{[&]() {
buffer.setActive(true);
buffer.clear(sf::Color::Black);
for (auto ptr: scene) {
buffer.draw(*ptr, states);
}
buffer.display();
}};
}
void wait() {
try {
thread.join();
} catch (std::system_error const &) {
// join might fail if thread already stopped
}
}
};
int main() {
XInitThreads();
sf::RenderWindow window{{640u, 480u}, "Distributed Rendering Test"};
window.setFramerateLimit(50u);
// create views
sf::View left, right;
left.setSize({320u, 480u});
left.setViewport({0.f, 0.f, 0.5f, 1.f});
left.setCenter({160.f, 240.f});
right.setSize({320u, 480u});
right.setViewport({0.5f, 0.f, 0.5f, 1.f});
right.setCenter({160.f, 240.f});
// create some shapes
sf::CircleShape circle{100.f};
circle.setPosition({5.f, 5.f});
circle.setFillColor(sf::Color::Yellow);
sf::RectangleShape box{{130.f, 280.f}};
box.setPosition({5.f, 35.f});
box.setFillColor(sf::Color::Green);
// apply shapes to scenes
std::vector<sf::Drawable*> scene1, scene2;
scene1.push_back(&circle);
scene2.push_back(&box);
// create cameras
Camera cam1{left};
Camera cam2{right};
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
// trigger distributed rendering
cam1.render(scene1);
cam2.render(scene2);
cam1.wait();
cam2.wait();
// apply to screen
window.clear();
window.draw(cam1);
window.draw(cam2);
window.display();
}
}