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

Author Topic: SFML 3 - What is your vision?  (Read 236162 times)

0 Members and 1 Guest are viewing this topic.

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: SFML 3 - What is your vision?
« Reply #330 on: October 31, 2017, 10:12:00 am »
I understand that. I guess what I'm struggling with conceptually is I'm not sure what level of abstraction SFML intends to live at inside a large codebase.

So inside a large project, is it intended that I be calling SFML directly all over a codebase? Or is it intended to be abstracted away and only exist in the code in discrete, easy-to-swap-out abstractions, so it can be replaced with another library, for example SDL2, if I need to target a platform that SFML does not support (not even meaning say consoles. For example, if I intend to compile to Wasm/asm.js).

The former, means SFML is held back by the opaqueness of it's implementation. Parts of it can't be easily swapped out or plugged in, it's a whole package and you take it or leave it. Yes that aids in it's simplicity, but at a cost of flexibility.

If the latter, then fair enough. This is almost always the approach I wind up taking. It can sit behind an abstraction in the code, even the graphics rendering itself can be abstract just have different implementations of "initialise" and "render this game state" functions, and the rest of the system can be none-the-wiser.

I think the thing that exemplifies this confusion for me is sf::Sprite. It's never been entirely clear to me whether the intention with a larger game is that sf::Sprite is used as a part of the representation of entities in a game, or is the intention that sf::Sprites are created at-draw-time given some other representation of an entities state.

Or take image loading. With something much higher-level like MonoGame, you can plug your own asset formats into it's pipeline and it can load them. With SFML, you can't do that. If it's intended to be wrapped up in a facade anyway, that's fine since you'll be abstracting away the image loading into something more general purpose, you'll create your own pipeline for it. If it's not intended to be wrapped, you'd expect it to expose hooks instead.

This is something I've always struggled with when writing things that use SFML, I'm not entirely sure where's it's intended to live. SDL2 is low-level, it feels right to hide it away. SFML is higher-level by it's very nature, it's part of the reason it's easier to start out with, so needing to hide it away like that almost feels a bit like 'missing the point'.

This is all possibly just a result of SFML managing to straddle that sweet-spot of being usable for both smaller and larger projects (which is definitely a good thing), so it's not so much a flaw as it is a result of it providing tools usable for both and leaving the rest to you. But it does result in it dangling somewhat awkwardly between a high-level library and a low-level library in some regards, and that s something that's been bouncing around my head for awhile now about SFML, and I've never been quite sure how to word it xD

=================

On a less dramatic note, I'd love if Image/Audio loading returned an std::future or had a "loadFromFileAsync" variant that returned an std::future :) Embrace the non-blocking file-io of the future (future future)
« Last Edit: October 31, 2017, 10:52:45 am by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: SFML 3 - What is your vision?
« Reply #331 on: October 31, 2017, 12:09:51 pm »
I perfectly understand what you mean. But I think you're wrong:
Quote
SDL2 is low-level, it feels right to hide it away. SFML is higher-level by it's very nature
I'm curious to know what makes SFML higher-level. It is designed to provide the exact same set of features than SDL and other similar frameworks. Maybe SFML just looks higher-level, because it is designed nicely with an object-oriented approach? ;)

Quote
On a less dramatic note, I'd love if Image/Audio loading returned an std::future or had a "loadFromFileAsync" variant that returned an std::future :)
I think it's wrong to ask an asynchronous version of XYZ feature when you can simply do
auto result = std::async([](std::string filename){sf::Image image; image.loadFromFile(filename); return image;}, "blop.png");
Laurent Gomila - SFML developer

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: SFML 3 - What is your vision?
« Reply #332 on: October 31, 2017, 12:35:04 pm »
I honestly can't think of any reason why we wouldn't be able to support multiple render backends. Sure... it might look like e.g. OpenGL and D3D are by nature incompatible with each other, but considering SFML only makes use of such a small subset of OpenGL (which itself comprises mostly of legacy features), most if not all of the concepts in SFML can be easily represented in the D3D world as well. Most of these concepts come straight out of general computer graphics and so are present in any hardware accelerated graphics API.

On the other hand, if SFML were to seriously one day support "modern" OpenGL, then the differences between OpenGL and D3D or even Vulkan for that matter become so small they aren't even worth mentioning. Just look at DX12 and Vulkan and to some weird extent OpenGL 4.6. The main reason why developer teams choose one over the other (DX vs Vulkan) is because they have a lot of prior experience with the API. The argument "one API supports something that the other doesn't" has become a thing of the past, which is a good thing. What matters more is what level of hardware the developer wants to support and this shouldn't boil down to the question of which graphics API to use.

We aren't doing the future of SFML a favour by artificially pretending that the differences between graphics APIs are too huge to abstract behind a single interface. If that is still a concern then the only sane thing to do is modernize the implementation to the point where there would no longer be any differences anyway. If the big player engines can do it on a large scale then we already know it is theoretically possible.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: SFML 3 - What is your vision?
« Reply #333 on: October 31, 2017, 12:40:19 pm »
Maybe SFML just looks higher-level, because it is designed nicely with an object-oriented approach? ;)

Like I said, sf::Sprite is something of the representation of why SFML confuses me with what level to put it at. sf::Sprite has functions to move it, scale it, rotate it, get global and local boundaries that can be used in simple collision detection. These make it conceptually more than a dumb object passed around to give information to SFML for rendering, it makes it a higher-level of object and even if that's not the intention it encourages people to use it as such.

I know the docs describe these as 'convenience functions', but I'd argue they expand the domain of the object considerably and make it something beyond what a low-level library would, or even maybe should, provide. So perhaps my critique is with the very existence of sf::Sprite as a render-level primitive.

I guess it just feels like using sf::Sprite to simply be a POD to pass a blit of an image, even a scaled and rotated blit, into SFML is a kind of conceptual overkill due to the presence of these functions, which makes me doubt that it's what I should be doing. All doubts flow from that point, I guess.

There are a few other things, like sf::Image having functions to load images from the filesystem that I'd like to see moved outside of sf::Image and into some kind of global function instead. Perhaps even moved out of sfml/Graphics entirely and into new packages that 'higher level functionality' like that can live (though C++'s library system as out-right clunky as it is, that's maybe a step too far).

Separates the loading of an image from the file system straight out of the definition of what an image is, having image loading even as a static function conflates it with the very idea of an Image, and having it as a local function makes sf::Image needlessly stateful. To my mind, Image shouldn't even have a default constructor at all, and should require some kind of data be passed to it for it to even exist.

I'm pretty sure that's been discussed already though.

But this is what I mean by SFML being higher-level, it's got conceptually 'higher' ideas like loading an image from the file system living side-by-side with conceptually 'lower' ideas, like creating an image from a byte array, and that muddies the waters somewhat. Or Sprites, with boundaries and moving, mixed up with Blitting, which is just "here is a texture, here's the section to draw, here's a transformation, have at!".

I guess you could say my vision for SFML 3 is for it to finish the job started all the way back when Image and Texture were separated into two classes: Remove all these mixed concerns from the code, to make it simpler, purer and more streamlined.

On the whole multi-renderer thing, I've found the main thing that makes cross-renderer abstractions tricky is Shaders. DX12 and OpenGL have different shader languages, so how exactly you can abstract that away (not abstracting the existence of the multiple shader languages obviously, but the creation and passing around of those shaders) is a design question that I've not found any really nice answers, just 'somewhat acceptable work-arounds'.

Quote
I think it's wrong to ask an asynchronous version of XYZ feature when you can simply do
auto result = std::async([](std::string filename){sf::Image image; image.loadFromFile(filename); return image;}, "blop.png");

True, file I/O is just the thing other languages have conditioned me to think of as async-by-default, otherwise you're holding up a system thread even if you create a new thread just for loading it. But the more I think about it the idea does not carry over to C++'s async/threading model as well (yet), since most of those languages have the idea of some sort of task pools baked into the language or standard library (even the newer 'low-level' languages like Rust and Go).

Although, if the std filesystem API were ever to go with an async-first design, I'd then argue SFML should follow-suit for file I/O (or if SFML got it's much-suggested Filesystem API, that could declare 'f-u' and go async-based from the ground-up. But C++'s futures API isn't quite there yet, maybe when it inevitably becomes monadic).
« Last Edit: October 31, 2017, 08:42:03 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

 

anything