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

Author Topic: The new graphics API in SFML 2  (Read 80054 times)

0 Members and 1 Guest are viewing this topic.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #15 on: September 13, 2011, 09:31:36 am »
Quote
First, wrap the three new Transform, Mesh and Texture classes in, I don't know, DrawableMesh class. This class can have no texture if needed.
That would be the first class hierarchy. Without any child class. (I don't see what class should inherit from DrawableMesh but maybe I missed something.)
[...]
Here there is one downside : we have to keep four objects alive instead of three which is already huge. To simply thing, a fourth argument could be added to specify a copy/ownership policy like MovePolicy (C++11 only), CopyPolicy or ReferencePolicy. I don't know exactly how it should be done properly, though. Or maybe the mesh and the transformation could be copied and only the DrawableMesh object and the Texture object should be kept alive.

BlendMode, Transform and View should always be handled by value (copy), whereas Texture and Shader should be handled by reference. To make it clear, the first three will be passed as const references and the last two will always be passed as const pointer to functions that use them.

Therefore, following your idea, the DrawableMesh class would store a pointer to a texture and a copy of a transform and a mesh. But how would they be accessed after the object is constructed? Wouldn't it be too verbose, compared to just storing the 3 objects (texture/mesh/transform) separately? You would have to get/set them everytime you want to change them
Code: [Select]
sf::Transform transform = drawable.GetTransform();
transform.Rotate(45);
drawable.SetTransform(45);

In other words, what does this additional class bring?
Laurent Gomila - SFML developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
The new graphics API in SFML 2
« Reply #16 on: September 13, 2011, 12:24:16 pm »
I think that Hiura idea is to avoid having SetTexture and SetTransform on Window so that it doesn't interfere with Sprites transformations. The DrawableMesh seems only a way to aggregate mesh, texture and transform, so that everything use Window.Draw. We can achieve the same effect with a Draw taking 3 arguments, instead of an extra class:
Code: [Select]
// draw the map
window.Draw(map, &tileset, mapTransform);
// draw a sprite
window.Draw(mySprite);

But I don't like the idea, what if we want to use the same texture or the same transformation for several maps? We'd have to repeatedly apply the texture and transformation. This isn't the best solution.
Pluma - Plug-in Management Framework

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #17 on: September 13, 2011, 12:27:46 pm »
Quote
But I don't like the idea, what if we have several maps using the same texture? What if we want to do some draws with the same transform applied? We'd have to repeatedly apply the texture and transformation. This isn't the best solution.

I totally agree. Although I don't like global render-states, I admit that they are much more flexible when low-level functions are involved.
Laurent Gomila - SFML developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
The new graphics API in SFML 2
« Reply #18 on: September 13, 2011, 12:44:44 pm »
I don't see the problem on a Sprite class having it's own transform.
Code: [Select]
window.SetTexture(someTexture);    // set a texture for maps
window.SetTransform(someTrasnform) // some global transformation from now on

// draw a sprite:
// sprite transform is combined with the global one.
// the previous transform and texture are restored after this draw
window.Draw(mySprite);

I think it's not confusing, if we specifically apply a transform on a window we know that everything that we'll draw next will be deformed that way. If we have a sprite in position (300,120) we know that it will suffer the global transformation as well.

This will only happen if someone want to use low level things (that person should know what is doing then). Mixing low level with high level sprites can be convenient sometimes. But one using only high level features doesn't have to use SetTexture/SetTransform and everything works as it was before.
Pluma - Plug-in Management Framework

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #19 on: September 13, 2011, 12:58:30 pm »
Quote
I think it's not confusing, if we specifically apply a transform on a window we know that everything that we'll draw next will be deformed that way. If we have a sprite in position (300,120) we know that it will suffer the global transformation as well

I think this is very confusing: the other states (blend mode, texture) are overwritten, but the transform is combined with the global one.

I don't like having two APIs that can achieve the same results differently, so at least let's keep their interactions as clean and intuitive as possible. That's just my point of view ;)
Laurent Gomila - SFML developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
The new graphics API in SFML 2
« Reply #20 on: September 13, 2011, 09:16:04 pm »
I'll just write as my mind goes.

Quote from: "Laurent"
In other words, what does this additional class bring?
Mainly a better consistency between the two different high and low level APIs.

Quote from: "gsaurus"
I think that Hiura idea is to avoid having SetTexture and SetTransform on Window so that it doesn't interfere with Sprites transformations.
Yes, but also to have the same code structure on both sprites/texts/... and meshes.

Quote from: "gsaurus"
We can achieve the same effect with a Draw taking 3 arguments, instead of an extra class
From SFML point of view it would be the same. But from the user point of view it would be a little bit different : for example if you're storing your graphical object in a vector then you need to store a tuple of three object instead of only one.

As I write these lines I realize that most people wouldn't store graphics object directly but instead have classed like this one :
Code: [Select]
class XYZ {
  sf::Mesh myMesh;
  sf::Tranform myTrans;
:
:

So when it comes to storing data it don't change much between the wrapping DrawableMesh class and the three-arguments Draw method.

Quote from: "gsaurus"
But I don't like the idea, what if we want to use the same texture or the same transformation for several maps? We'd have to repeatedly apply the texture and transformation.
Are you thinking that performance will be an issue with this system ? I don't think so because it's very rare to keep the same texture / transformation to draw several objects. If I'm not wrong on that last fact the performance shouldn't be a issue in most cases.

Even if you have a lot of objects with the same texture then you need a very specific data structure to take part of this new system. And even with this data structure I think most user will call SetTexture even if it's not necessary just in case they have a flaw in on of their application module. (Ok, this is not a good argument because this would be a mistake to proceed like this and not fix the bug.)

My point is their wouldn't be so much different (performance-speaking or program-design-speaking) between calling window.SetTexture when drawing and drawableMesh.SetTexture when setting up the dm object.

Quote from: "Laurent"
Therefore, following your idea, the DrawableMesh class would store a pointer to a texture and a copy of a transform and a mesh. But how would they be accessed after the object is constructed? Wouldn't it be too verbose, compared to just storing the 3 objects (texture/mesh/transform) separately? You would have to get/set them everytime you want to change them
Yes, unfortunately. Because duplicating the API and add Scale, Rotate, ... to DrawableMesh would be a bad idea.

Quote
This isn't the best solution.
Definitely not, I agree.

So the Draw(mesh, texture, tranform) looks better than my idea. It also look consistent with Draw(sprite) if Sprite have their own Texture and Tranform. (Mixing window.Set[Texture|Transform]+window.Draw(mesh) and window.Draw(sprite) is confusing for me too.)

Maybe to add more flexibility to Draw(mesh, texture, tranform) version (let's call it gsaurus' idea for convenience if you don't mind) RenderTarget can have these overloads :
Code: [Select]
Draw(Mesh, Transform, Texture) // update current Texture and Transform
Draw(Mesh, Transform) // keep current Texture
Draw(Mesh, Texture) // keep Texture
Draw(Mesh) // keep both
Draw(Sprite/Text/...) // Use sprite's Transform and Texture


But the last one has still something confusing : does it update or keep the current Texture and Transform ? It would be easy if Sprite-like doesn't own their Transform and Texture. So is it possible ? It's possible only if all sprite-like have both Texture and Transform without specific requirement.

Can a Text have a specific texture ? (Would it be feasible for the implementation to display an image "in" the text's characters ?) Yes, I think so.

Because every sprite-like can have both Transform and Texture and doesn't have any specific requirement on these (or did I miss something there ?) I think sprite-like shouldn't have their own Transform and Texture.

To sum up my thoughts :
I agree that the DrawableMesh is not a good idea and that having these overload in RenderTarget should keep things consistent between the two high and low APIs :
Code: [Select]
Draw(Mesh, Transform, Texture) // update current Texture and Transform
Draw(Mesh, Transform) // keep current Texture
Draw(Mesh, Texture) // keep current Transform
Draw(Mesh) // keep both
Draw(Sprite/Text/..., Transform, Texture) // update current Texture and Transform  
Draw(Sprite/Text/..., Transform) // keep current Texture
Draw(Sprite/Text/..., Texture) // keep current Transform
Draw(Sprite/Text/...) // keep both

And if one doesn't want any texture he/she can call Draw(mesh or sprite-like, 0) or Draw(mesh or sprite-like, transform, 0) depending on the need to change the transformation.
SFML / OS X developer

gsaurus

  • Sr. Member
  • ****
  • Posts: 262
    • View Profile
    • Evolution Engine
The new graphics API in SFML 2
« Reply #21 on: September 13, 2011, 09:52:29 pm »
Quote from: "Hiura"
for example if you're storing your graphical object in a vector then you need to store a tuple of three object instead of only one.

Consider using a vector of Sprites instead (if a sprite already have those three elements). At low level it's up to the user to decide how to organize the resources.

Quote from: "Hiura"
it's very rare to keep the same texture / transformation to draw several objects. If I'm not wrong on that last fact the performance shouldn't be a issue in most cases.

Example: RPG game using a unique tileset for everything: background, characters (including animations), etc.

Quote from: "Hiura"
Code: [Select]
Draw(Mesh, Transform, Texture) // update current Texture and Transform
Draw(Mesh, Transform) // keep current Texture
Draw(Mesh, Texture) // keep Texture
Draw(Mesh) // keep both
Draw(Sprite/Text/...) // Use sprite's Transform and Texture

But the last one has still something confusing : does it update or keep the current Texture and Transform?

So this is exactly the same problem as if we're using SetTransform/SetTexture:
Code: [Select]
window.SetTexture(someTexture);
window.SetTransform(someTrasnform);
window.Draw(mySprite); // will it use it's own Transform or a combination with the global one?


I can't think of anything right now, I need some food  :P
Pluma - Plug-in Management Framework

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #22 on: September 13, 2011, 10:05:50 pm »
Quote
Code: [Select]
Draw(Mesh, Transform, Texture) // update current Texture and Transform
Draw(Mesh, Transform) // keep current Texture
Draw(Mesh, Texture) // keep current Transform
Draw(Mesh) // keep both
Draw(Sprite/Text/..., Transform, Texture) // update current Texture and Transform  
Draw(Sprite/Text/..., Transform) // keep current Texture
Draw(Sprite/Text/..., Texture) // keep current Transform
Draw(Sprite/Text/...) // keep both

Definitely not doable in my opinion, it will explode if you add BlendMode, Shader and View. And future other states (RenderMask for example).
And it will complicate the life of people who write bindings where function overloading is not supported :)
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
The new graphics API in SFML 2
« Reply #23 on: September 14, 2011, 01:20:20 am »
It sounds like the problem here is that there needs to be a global render state to accomidate the Mesh idea, but the Sprite idea needs its own render state that operates independently.


So how about introducing a new RenderState object?  When drawing a mesh, you would supply the desired RenderState (would have to be a mandatory parameter).  When drawing a Sprite, it would generate its own:

Code: [Select]

sf::RenderState lowlevelstate;
lowlevelstate.SetTexture( blah );
lowlevelstate.SetWhatever( whatever );

sf::Mesh mymesh = blah;
sf::Sprite mysprite = blah;

target.Draw( mymesh, lowlevelstate ); // uses low-level state
mysprite.Draw(target);  // uses sf::Sprite's internal state


sf::Sprite's Draw function would probably internally just manipulate it's own state and call target.Draw( spritemesh, spritestate ); or whatever.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #24 on: September 14, 2011, 07:54:13 am »
Quote
So how about introducing a new RenderState object? When drawing a mesh, you would supply the desired RenderState (would have to be a mandatory parameter). When drawing a Sprite, it would generate its own:

So a sprite would have to declare a getter/setter for every possible state: shader, view, transform, texture, blend mode.

I don't think that getting rid of global states is a good idea. It's more flexible:
- some states are better activated once, globally, than assigned to every entity (view, shader)
- you can combine a transform with the current one (parent/child relationship)
- an object can set the states that it needs, while enjoying other states that it doesn't care about

My plan was to use solution 3: a sprite has its own texture, therefore it overwrites the global one when it's rendered but still uses any shader/view/whatever which is active at that time.
Laurent Gomila - SFML developer

Lo-X

  • Hero Member
  • *****
  • Posts: 618
    • View Profile
    • My personal website, with CV, portfolio and projects
The new graphics API in SFML 2
« Reply #25 on: September 14, 2011, 08:32:20 am »
I don't understand all the points but as a begginer I prefer Hiura's solution than to do :

Code: [Select]
window.SetTransform(transform);
window.SetTexture(texture);
window.Draw(Mesh);

and suddenly

window.Draw(sprite);


Furthermore I don't understand why that's the window which have membres like SetTransform and SetTexture. In fact, I understand because OpenGL in the background works like that but for me these members should belong to a "drawable", something that can be drawn directly by the window.

I understand that what I describe is the old API and that it's difficult to find something between the old one and a low level API.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #26 on: September 14, 2011, 08:56:03 am »
Quote
I don't understand all the points but as a begginer I prefer Hiura's solution than to do

Which one? A DrawableMesh with texture/transform/mesh, or a Draw function which takes any combination of those?

Quote
Furthermore I don't understand why that's the window which have membres like SetTransform and SetTexture. In fact, I understand because OpenGL in the background works like that but for me these members should belong to a "drawable", something that can be drawn directly by the window.

Like I said, some states are better set globally than assigned per object, like shader and view.
And if all states were encapsulated in objects, I'm pretty sure that people would soon be tired of all those repeated Get/Set to modify them.
Laurent Gomila - SFML developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
The new graphics API in SFML 2
« Reply #27 on: September 14, 2011, 09:43:17 am »
Quote from: "Laurent"
Definitely not doable in my opinion, it will explode if you add BlendMode, Shader and View. And future other states (RenderMask for example).
Yes, you're write! (Again!  :P )

Quote from: "Hiura"
But the last one has still something confusing : does it update or keep the current Texture and Transform ? It would be easy if Sprite-like doesn't own their Transform and Texture. So is it possible ? It's possible only if all sprite-like have both Texture and Transform without specific requirement.

Can a Text have a specific texture ? (Would it be feasible for the implementation to display an image "in" the text's characters ?) Yes, I think so.

Because every sprite-like can have both Transform and Texture and doesn't have any specific requirement on these (or did I miss something there ?) I think sprite-like shouldn't have their own Transform and Texture.

What about that ? If sprite-like don't have their own render state then we can do something consistent and logical :
Code: [Select]
window.SetTransform(...);
window.Set....();

window.Draw(mesh);
window.Draw(sprite); // use same transform / texture
(Only two overloads.)

Now, what would be different in sprite-like and mesh ? The only fundamental difference I see is that sprite would have only TextCoord parameter.

Quote from: "Laurent"
My plan was to use solution 3: a sprite has its own texture
What about Text ? Ho, and will Shape still exist or it will replaced completely by Mesh (with some static function to have a high level API in order to create rectangle/lines/circle) ?

If they all have their own texture then mesh could also have its own one, right ? It would make things less confusing.
SFML / OS X developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The new graphics API in SFML 2
« Reply #28 on: September 14, 2011, 10:02:59 am »
Quote
If sprite-like don't have their own render state then we can do something consistent and logical

But higher-level objects need to have their own render states, otherwise they are pretty useless ;)
What is a sprite without a texture? Would you bind the text's texture from its font manually?

Quote
What about Text ?

I think that sf::Text won't change much.

Quote
Ho, and will Shape still exist or it will replaced completely by Mesh (with some static function to have a high level API in order to create rectangle/lines/circle) ?

That's the main point of the discussion, so I'm waiting for your suggestions :)

Quote
If they all have their own texture then mesh could also have its own one, right ? It would make things less confusing

Are you just talking about texture, or all other states too? If texture only, why would this state be a special case? And how would other states be handled?
Laurent Gomila - SFML developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
The new graphics API in SFML 2
« Reply #29 on: September 14, 2011, 10:30:36 am »
Quote
What is a sprite without a texture?
A colored rectangle. Ok a shape... So they would be quite the same. Shape (with optional texture) and Sprite I mean. Would we need both ?

Quote
Would you bind the text's texture from its font manually?
In fact, I was not speaking about the font texture but what you can draw "in" the characters. Sorry for the misunderstanding here.

Quote
Are you just talking about texture, or all other states too? If texture only, why would this state be a special case? And how would other states be handled?
Only about texture, because it is something that both sprite-like and mesh have in common. Moreover, when I think about something to draw I think of its shape (Mesh/Sprite/Text) _and_ its color/texture. Then comes the part of positioning it on the world (Transform), etc...
Other states would be directly Set on the render target.

(As for the implementation if two consecutively drawn objects have the same texture then we do not have to load it again (from OpenGL pov). So it won't change anything performance-speaking.)

Gosh! It's a complicated!  :P
SFML / OS X developer

 

anything