First of all, I've been using SFML for quite some time now both for my work and for educational purposes (my students really get a jumpstart into C++ graphics with it) and I'm really happy with most of its design decisions.
However, there's a few design decisions I don't like. One of them I wanted to discuss today regards native OpenGL rendering with SFML.
As far as I see, currently SFML supports native OpenGL rendering in a way when user theoretically can inject any kind of OpenGL code between native SFML calls and it should work as long as the user knows what they're doing. SFML even provides some basic API call to help doing so like sf::Texture::bind() or sf::Shader::bind(). However, in practice it turns out that in order to mix native OpenGL with SFML, user must have deeper OpenGL understanding than functionality he's actually going to use because of hidden states that SFML sets.
Here's an example of very basic OpenGL code injected into SFML:
sf::RenderWindow window(...);
while(window.isOpen())
{
while(window.pullEvent(...)){...}
window.setActive(1); //just to be sure
float vertices[] = {0, 0, 0, 100, 0, 0, 0, 100, 0};
int indices[] = {0, 1, 2};
glEnableClientState (GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(float) * 3, vertices);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, indices);
window.display();
}
The code is very straightforward and it if you run it, it works great. Right? Wrong. Thing is, it works well *most of the time* because SFML has internal buffer bindings for its own rendering, for example here:
//RenderTarget.h, line 356
void RenderTarget::resetGLStates()
{
//...
glCheck(glEnableClientState(GL_VERTEX_ARRAY));
glCheck(glEnableClientState(GL_COLOR_ARRAY));
glCheck(glEnableClientState(GL_TEXTURE_COORD_ARRAY));
//...
}
And when the user calls glDrawElements() or any similar function, colors are actually read from internal SFML buffers and of course that's undefined behaviour. It may even not crash most of the time, but when it does, crash occurs in nvogl.dll(windows) and that's pretty hard to track especially for those learning OpenGL.
Similar problems arise when using native OpenGL texturing. Since most OpenGL users are used to normalized texture coordinates, it's very confusing to track down glMatrixMode(GL_TEXTURE) that SFML uses.
Yes I understand that it's easy to say that the user must not make any assumptions on any states left by SFML. But due to vast number of non-obvious states that the user may forget to set to default values, debugging such errors may prove to be very frustrating, especially when the same code works perfectly fine in native code without SFML. I really think SFML should provide some functionality similar to resetGlStates(), but instead of resetting states for SFML usage, reset them to default OpenGL ones(matrices, client buffers, etc).