Hi
I'm currently out of inspiration for the new graphics API. So I thought it would be a good idea to share what I've done so far, and use your feedback to complete this task
I decided to start with the lowest level. I needed something flexible enough so that people stop complaining about performances or limitations, but still easy to use; and as a bonus, something that will allow me to drop deprecated functions so that SFML can be ported to pure OpenGL (ES) 2 architectures.
The result is something very close to how OpenGL works, and it contains the 5 ingredients required by modern rendering architectures:
Texturessf::Texture is left unchanged.
Shaderssf::Shader is left unchanged, but it will later be upgraded to support vertex shaders.
TransformsThey will be handled by a new class, sf::Transform. Internally a transform is a 3x3 matrix, but its public API provides the usual functions: Translate, Rotate, Scale, Combine (with other matrix), TransformPoint, GetInverse, and some operator overloads.
So, transformations are now completely separated from drawables, and are much more flexible.
GeometryGeometry is no longer hidden behind high-level classes, it is now directly exposed.
Vertices are defined with a new class, sf::Point. It's very simple, it contains 3 public members (Position, Color, TexCoords) as well as a bunch of constructors to easily construct points with 1, 2 or 3 of these attributes.
On top of that there's a sf::Mesh class (
its name can change if you have better ideas), which is a thin layer on top of OpenGL vertex arrays. It is also quite simple: it combines a dynamic array of sf::Point (Resize, operator[], Append, ...) with a primitive type which defines how the points must be interpreted as geometrical primitives when they are rendered (for example it can be Points, Lines, Triangles, Quads, ...).
RendererAll these things are put together in the sf::RenderTarget class (the same as now, the base of RenderWindow and RenderTexture), with the following functions:
- SetView(sf::View)
- SetTransform(sf::Transform)
- SetTexture(const sf::Texture*)
- SetShader(const sf::Shader*)
- SetBlendMode(sf::BlendMode)
- Draw(sf::Mesh)
Here is a typical example, a tiled map:
const int size = 32;
// load the texture containing all the tiles
sf::Texture tileset;
tileset.LoadFromFile("tileset.png");
// create the map
sf::Mesh map(sf::Quads, width * height * 4);
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
int current = (x + y * width) * 4;
// define the position of the 4 points of the current tile
map[current + 0].Position = sf::Vector2f((x + 0) * size, (y + 0) * size);
map[current + 1].Position = sf::Vector2f((x + 0) * size, (y + 1) * size);
map[current + 2].Position = sf::Vector2f((x + 1) * size, (y + 1) * size);
map[current + 3].Position = sf::Vector2f((x + 1) * size, (y + 0) * size);
// define the texture coordinates of the 4 points of the current tile
int tx = /* X index of the tile in the tileset */;
int ty = /* Y index of the tile in the tileset */;
map[current + 0].TexCoords = sf::Vector2i((tx + 0) * size, (ty + 0) * size);
map[current + 1].TexCoords = sf::Vector2i((tx + 0) * size, (ty + 1) * size);
map[current + 2].TexCoords = sf::Vector2i((tx + 1) * size, (ty + 1) * size);
map[current + 3].TexCoords = sf::Vector2i((tx + 1) * size, (ty + 0) * size);
}
// let's scale and translate the whole map
sf::Transform mapTransform;
mapTransform.Scale(2, 2);
mapTransform.Translate(500, 400);
...
// draw the map
window.SetTexture(&tileset);
window.SetTransform(mapTransform);
window.Draw(map);
Building the map is a little more verbose than with sprites, but the whole map is now a single 2D entity and it can be drawn with a single call (which is
very fast -- no need for tricks such as manual clipping or pre-rendering to a texture).
That's it for the new low-level API. Hopefully, users who required more flexibility and/or performances will be happy with it.
But it's not enough: it's very low-level, a lot of SFML users enjoy the simplicity of the high-level classes and I don't want to force them to use these classes.
I can easily implement the old sf::Text, sf::Sprite and sf::Shape classes on top of this new API. But it would probably not be a good idea. These classes were required in the old API because they were the only way to draw things on screen. But now that we have a low-level layer that can do almost everything, these classes would exist only for convenience. Therefore, maybe we can think of something different. And we must also decide how these classes would mix with the low-level layer: do they define and use their own transform, or the one that is set with SetTransform? Should they inherit a base class, that would allow to write "window.Draw(sprite)"? Or rather define a Draw function in all of them so that we would write "sprite.Draw(window)"?
I actually have a lot more pending questions and problems, but let's see what
you think about this
Don't hesitate to comment the low-level API, suggest features or modifications, propose ideas for the high-level classes, etc. But please don't focus on details (except class names), here we are talking about general concepts.
PS: sorry for those who, after reading the title, thought that the new API was already written and pushed :lol: