-
I'm drawing lots of rotated sprites.
And i have to draw some of this sprites partly - that ones, that are partly out of given region.
Briefly, I want do draw only that pixels of sprites that are in specified region.
Effect have to be like using sf::View but on single drawable object
PS I do it in my own Drawable component so i can't use sf::View::setViewport().
Any ideas?
-
You will probably have to use an OpenGL stencil for this sort of operation, I'm not sure that SFML supports partially drawing sprites or textures. Alternatively you could probably use a shader but that might be a little more work.
-
Shaders isn't my best side :)
-
Why can't you use sf::View? It's your best option to implement clipping without doing OpenGL stuff.
-
So i have another question: does view transformations applies on end of frame or for each draw()?
I'm asking it because i have idea:
virtual void draw(RenderTarget& target, RenderStates rs)
{
rs.transform *= getTransform();
View oldV = target.getView();
View newV;
// setting parameters of new view
target.setView(newV);
// draw my stuff
target.setView(oldV);
Does my stuff draw with newV wiew or oldV view?
Can I apply view on only a few of objects?
-
Once you set the view, all objects that get drawn after, will be drawn with the set view.
Keep in mind though that the draw function from sf::Drawable is const (http://sfml-dev.org/documentation/2.1/classsf_1_1Drawable.php#a90d2c88bba9b035a0844eccb380ef631), so you can't change objects states in there.
-
It doesn't work or I do something wrong.
The whole problem is because I'm rendering a physics simulation that have its own coordinates.
And I want to render specified rect of physics simulation to specified rect on window (not on whole window)
// some useful inlines that are missing in SFML
inline Vector2f size(const FloatRect& rect)
{
return Vector2f(rect.width, rect.height);
}
inline Vector2f pos(const FloatRect& rect)
{
return Vector2f(rect.left, rect.top);
}
inline Vector2f localCenter(const FloatRect& rect)
{
return size(rect) * 0.5f;
}
inline Vector2f globalCenter(const FloatRect& rect)
{
return pos(rect) + localCenter(rect);
}
void WorldRender::draw(RenderTarget &target, RenderStates states) const
{
//states.transform *= getTransform(); // i don't need Transformable transform because i use the same transform in view
// vp is source region of simulation
// view set
View oldV = target.getView();
View newV;
newV.setRotation(getRotation());
newV.setSize(size(vp));
newV.setCenter(globalCenter(vp));
newV.setViewport(FloatRect(getPosition(), Vector2f(size(vp).x * getScale().x, size(vp).y * getScale().y)));
target.setView(newV);
// only for example
CircleShape cs(50);
cs.setPosition(0, 0);
cs.setFillColor(Color::Black);
target.draw(cs, states);
//...
target.setView(oldV); // restore old view
}
And in this case NOTHING renders. Even simple circle (cs in my code).
But out of this function everything works properly.
-
The viewport is defined in normalized coordinates. Please read the documentation carefully.
-
Thanks, it works.
Here's my code. Maybe it will help someone.
View newV;
newV.setSize(size(vp));
newV.setCenter(globalCenter(vp));
newV.setRotation(getRotation());
Vector2f vpPos(getPosition().x / target.getSize().x, getPosition().y / target.getSize().y);
Vector2f vpSz((size(vp).x * getScale().x) / target.getSize().x, (size(vp).y * getScale().y) / target.getSize().y);
newV.setViewport(FloatRect(vpPos, vpSz));
target.setView(newV);
-
I don't know how expensive these function calls are, but as a general rule, I would store results in variables instead of calling the same function multiple times. It's also more readable. That concerns getPosition(), getScale() and getSize().
Alternatively, you can use thor::cwiseProduct() or thor::cwiseQuotient() to multiply/divide vectors component-wise, see here (http://www.bromeon.ch/libraries/thor/v2.0/doc/group___vectors.html).