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

Author Topic: Explanation of interactions between Image, Texture, and Sprite?  (Read 15066 times)

0 Members and 1 Guest are viewing this topic.

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Explanation of interactions between Image, Texture, and Sprite?
« on: November 18, 2012, 10:36:57 pm »
a problem with sprites showing up as a white box.  I found an explanation here http://en.sfml-dev.org/forums/index.php?topic=8961.0  which makes complete sense to me.

I believe I'm running into the same issue, although I'm not completely sure why.  It isn't clear to me exactly what the relationship in SFML is between Images, Textures, and Sprites, nor do I understand how their references are kept, and when they're released.

In particular, here's some code for a tetrimino factory function.  Ignore the render window parameter,
it's there strictly for testing purposes so I could try and get an idea of how and where the sprites were losing their texture references:

Tetrimino buildTetrimino(sf::Vector2f vecs[], std::string block_name, sf::RenderWindow *w) {
    sf::Texture bt;
    if(!bt.loadFromFile(block_name)) {
      std::cout << "failed to load " << block_name << std::endl;
      exit(1);
    }

    sf::Vector2f sz(bt.getSize());
    sf::Vector2f factors(30/sz.x,30/sz.y);  // blocks are 30x30 pixels

    sf::Sprite blocks[4];

    for(int i = 0; i < 4; ++i) {
      sf::Sprite sp(bt);
      sp.setScale(factors);
      sp.setPosition(vecs[i].x,vecs[i].y);
     
      blocks[i] = sp;
    }
    Tetrimino tet(blocks,sf::Vector2f(0,0),w);
    //tet.draw(*w);
    return tet;
  }
 


This is the function that's calling the factory function:

Tetrimino createI(sf::RenderWindow &w) {
    sf::Vector2f vecs[] = {
      sf::Vector2f(-1.5, 0.5),
      sf::Vector2f(-0.5,-0.5),
      sf::Vector2f( 0.5,-0.5),
      sf::Vector2f( 0.5, 0.5),
    };

    Tetrimino t = buildTetrimino(vecs,"./resources/block6.jpg",&w);
    t.draw(w);
    return t;
 


Note the t.draw.  The one in the factory function displays the block just fine.  The one in the createI() function displays a white block.


Here are the relevant constructors.

Tetrimino::Tetrimino(sf::Sprite inpBlocks[], sf::Vector2f center, sf::RenderWindow *w) {
  for(int i = 0; i < 4; i++) {
    this->blocks[i] = inpBlocks[i];
  }
  this->center = center;
  this->translateToTopLeft();
}

Tetrimino::Tetrimino(const Tetrimino &rhs) {
    for(int i = 0; i < 4; i++) {
      this->blocks[i] = rhs.blocks[i];
    }
}
 


I would have expected the copy constructors for the Sprite's to do the right thing, but apparently they're not?

Also, this code is unfinished, it's true that all of the blocks currently will render into the exact same position.  The vector you see in the code is defined in terms of a block size of 1 and the factory method will need to translate accordingly, but for now, I'm more worried about the white block being displayed :)
« Last Edit: November 18, 2012, 10:56:25 pm by ichineko »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #1 on: November 18, 2012, 10:44:46 pm »
Tetrimino buildTetrimino(...) {
    sf::Texture bt;
    // ...
    return tet;
  }
 
You create a texture within your function, thus as soon as the function is left the texture will get destroyed = white rectangle.
The texture has to be kept alive as long as it's in use.

Also for further post, please make use of the code=cpp tag to highlight your code examples and provide complete and minimal examples, rather than providing some pieces of your live code.
Additionally this post gives some guidance towards nice posts, which is directly connected to fast and precise answers. ;)

PS: There are quite a few bad practices in your code. Maybe you could take a look at some more example code in the forum. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #2 on: November 18, 2012, 11:30:59 pm »
You know exploiter, I appreciate your response, but these types of replies annoy me.

I used the search function or I wouldn't have been able to link you to the other post.
I gave you enough of an example to see exactly what was needed.  It was enough or you wouldn't have been able to point out the issue.  I made a subjective decision on that, and it was the right decision.  Don't ask for a complete code listing when I gave you enough.  Ask for a complete code listing when I don't.

But outside all of that, you

1.  Tell me my code is using bad practices for SFML, but choose not to link me to anything I can actually learn from, and

2.  Failed to answer the question I specifically asked for.  Which is, what is the interaction between images, textures, and sprites.

Am I expected to keep the images around as well, or do the underlying textures share the images?  How and when are they released?  These are exactly the types of things I was hoping to learn because I've googled around and the documentation for SFML is hard for me to find.

If your critique was of the general quality of the C++ code, I would ask you to be quiet.  It's tetris.

I really want your input, but you didn't really give it.  It certainly wasn't enough to help the next person who finds this thread, or to keep me from running into other problems because I don't have the proper mental model for how these things interact with each other in SFML (and I mostly mean from a memory standpoint).
« Last Edit: November 18, 2012, 11:32:36 pm by ichineko »

eigenbom

  • Full Member
  • ***
  • Posts: 228
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #3 on: November 19, 2012, 12:08:53 am »
Don't get so offended, exploiter had no idea about your experience and what you had or had not done, and actually solved the exact question you asked about.

When he said a 'complete and minimal' example, he really meant for you to go and reproduce the problem in the smallest program you can (e.g., a 20 line program), and then post that, instead of fragments of a complex program, which may have all sorts of things going on.

In addition he offered some extra tips which you are free to take or not. Unfortunately your attitude tells me that you will struggle to learn things because you take offence when advice is given. It would have been far better to reply with something like "Thanks exploiter, that fixed my problem. However I'm still a bit confused about how Textures and Images are related, for example does a texture keep an internal reference to the image it was created from?" The answer to that is no btw, afaik.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #4 on: November 19, 2012, 12:21:04 am »
Hey I can also make nice listings ;D
  • All the answers in here are free and all the time spent to answer in here is taken their responses free time. If you expect a high-quality, book-perfect answer you're way off here. As a tip, appreciate every answer you get, because it's not very common, that people spend evenings just answering questions, which the asking person could find the answer to it on their own, if he just spent some more time researching the tutorials, the documentation, the source and the concepts of C++. ;)
  • I was typing on my phone and didn't want to write an complete essay on my touch keyboard. So I apologize that I didn't add tons of examples.
  • Although I didn't answer your questions directly, I did tell you the solution to the actual problem, so my answer wasn't just useless or anything. It just wasn't complete.
  • I'm aware that ranks and all don't really matter, but it's just very sad to see people join a new forum, totally unaware of their surroundings, what the rules are, how people talk to each other, etc. and the within in the first few posts just show their hate/annoyance towards members that have been around for quite a bit and help quite a few people. I personally try always to be most respectful to anyone when I join a new community. It preserves the atmosphere and you as newbie gain some respect in return.

I gave you enough of an example to see exactly what was needed.  It was enough or you wouldn't have been able to point out the issue.  I made a subjective decision on that, and it was the right decision.  Don't ask for a complete code listing when I gave you enough.  Ask for a complete code listing when I don't.
I never requested a full listing for your current code, I simply said "Also for further post", which obviously doesn't include this one. I gave you this advice since I saw that you're new to this forum and most of the new comers don't even think about providing complete examples and me having to answer in every other post "please provide a complete and minimal example that reproduces the error" gets quite annoying too. Prevention is better than reaction. ;)
Besides that, I can request whatever I want, like: "I want a chocolate cake from you."
But you're not forced to follow my requests. (It's called freedom of speech and freedom of decisions.) :D


1.  Tell me my code is using bad practices for SFML, but choose not to link me to anything I can actually learn from, and
  • Don't pass the window as pointer, pass it as reference. Also instead of passing by value (e.g. std::string), pass them as const reference.
  • Don't use arrays, specially if you have to pass it around. If you (for some reason) don't want to use std::vector then at least use std::array (TR1/C++11). The problem with a pure array is, that you never really know it's size and thus you'll have to use many hard coded numbers or other not so nice hacks.
  • Don't create a additional sprite object just to initialize it, if you're only purpose is to copy that object to another place later on. E.g. just use setTexture() to set the texture instead of sp(bt).
But then again this is all some mock-up code, so maybe you usually do follow all of these things.

2.  Failed to answer the question I specifically asked for.  Which is, what is the interaction between images, textures, and sprites.
sf::Image is a representation of an image and lives on the RAM.
sf::Texture is a representation of an image and lives on the memory of the GPU.
To get a sf::Texture things get internally loaded as a sf::Image and then copied to the GPU's memory. This operation is slow, thus one shouldn't have to copy stuff from the RAM to the GPU memory too much.
sf::Sprite holds a reference to a sf::Texture. If the reference is dead, i.e. the sf::Texture went out of scope or no texture has been set, then you'll get a rectangle filled with the color defined for the sprite.

To get picture on the screen, these rules need to be followed:
  • The image file must exist and be conform to the types SFML supports.
  • The texture has to in a scope where it exists as long as the image is needed.
  • The sprite has to reference the texture.

Am I expected to keep the images around as well, or do the underlying textures share the images?
sf::Image and sf::Texture are both representation of images (i.e. pure memory), thus you actually only need sf::Texture to display something on the screen.

How and when are they released?
The SFML objects use all RAII (google it), thus they get released as soon as they leave the scope.

and the documentation for SFML is hard for me to find.
You mean what you're looking for is hard to find in the doc right?
The doc is easy to find, here.

If your critique was of the general quality of the C++ code, I would ask you to be quiet.  It's tetris.
Don't post stuff nobody should ever see or comment upon. ;)

I really want your input, but you didn't really give it.  It certainly wasn't enough to help the next person who finds this thread, or to keep me from running into other problems because I don't have the proper mental model for how these things interact with each other in SFML (and I mostly mean from a memory standpoint).
Read, learn, experiment. :)

Do I now get paid for my 30+min essay just for you? ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #5 on: November 19, 2012, 01:37:45 am »
Quote
Hey I can also make nice listings

lets not be passive aggressive.  I mean that seriously.  I appreciate blunt honesty, I prefer it actually, but I don't like passive aggressive behavior.  It never does anyone any good, so can we agree to refrain from things like this please?


Quote
I was typing on my phone and didn't want to write an complete essay on my touch keyboard. So I apologize that I didn't add tons of examples.

Ok, that's fair, I shouldn't have assumed.  How anyone can type up anything on those keyboards is beyond me.


Quote
I'm aware that ranks and all don't really matter, but it's just very sad to see people join a new forum, totally unaware of their surroundings, what the rules are, how people talk to each other, etc. and the within in the first few posts just show their hate/annoyance towards members that have been around for quite a bit and help quite a few people. I personally try always to be most respectful to anyone when I join a new community. It preserves the atmosphere and you as newbie gain some respect in return.

It was pushback in the hopes that you would respond with a better answer.  You did, and I want you to know I appreciate it.  Maybe you'll take that negatively, but it isn't meant to be taken so.  In my experience, people sometimes need pushback in order to understand that they weren't as helpful as they thought.


Quote
- Don't pass the window as pointer, pass it as reference. Also instead of passing by value (e.g. std::string), pass them as const reference.
- Don't use arrays, specially if you have to pass it around. If you (for some reason) don't want to use std::vector then at least use std::array (TR1/C++11). The problem with a pure array is, that you never really know it's size and thus you'll have to use many hard coded numbers or other not so nice hacks.

-Don't create a additional sprite object just to initialize it, if you're only purpose is to copy that object to another place later on. E.g. just use setTexture() to set the texture instead of sp(bt).


That last point is exactly the types of things I'm wanting to get out of this thread.  The other points are stylistic issues which I'm not interested in.

The array point in particular is ideology.  Vectors have their place, but I prefer the initializer syntax, and tetriminos have been defined as 4 blocks for well on 25 years now. 



Quote
You mean what you're looking for is hard to find in the doc right?
The doc is easy to find, here.

You know, I was going to complain about that link, I *have* been reading those documents.  But then I realized the sprite page did describe the issue I was running into.  I read it the first time I read over the page, but on subsequent visits I didn't hit the 'more' link and so missed it (and had forgotten the warning about keeping the texture alive, although I did remember that they were kept separate which caused unnecessary fears on my part).

So I apologize for that, I should have been able to find that myself.  But having said that, you should link directly to the page, it's more useful and it means when others use that search button and find this thread, they can be directed straight to what they're looking for too.


Quote
The SFML objects use all RAII (google it), thus they get released as soon as they leave the scope.

That's not quite what I was asking for.  A reference counted "Smart Object" would use RAII as well, but that doesn't mean the memory would get released.  I have to assume something similar is being used underneath or drawing a texture would blow up after the fact.

Those types of details are what I was looking for.



Quote
Don't post stuff nobody should ever see or comment upon.

I get that, but I'm also not interested in it.  fyi, I've been using C++ since before a standard *existed*.  I've seen all kinds of code, and I've worked with all kinds of people.  Personally, I believe in scaling the solution to the problem, this means using an array for something as small and well defined as tetris is not a big deal.  If someone wants to get offended about it, that's their business, but it's a waste of my time.  And I'm not saying you acted that way, I'm just explaining why I take took the approach I did.

I'm here to get answers for things I need to learn, not rehash inane internet arguments about things that have no real bearing on the 'success' of my tetris clone.

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #6 on: November 19, 2012, 01:53:18 am »
And actually, I have a few more questions.

Does all of this mean I'm responsible for the lifetime of the texture?  I can't assume that it's going to be cleaned up after there are no more references to it?  I don't mean the representation on the video card, I mean the object itself.

So, even though the constructor for sprite takes a *reference*, it's assumed that reference is to heap memory, or the sprite is not going to last past the current scope?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #7 on: November 19, 2012, 02:01:35 am »
Well good luck with your attitude then, I don't like it, but who am I and why would you care? ;D

Does all of this mean I'm responsible for the lifetime of the texture?  I can't assume that it's going to be cleaned up after there are no more references to it?  I don't mean the representation on the video card, I mean the object itself.
What? ???
sf::Texture is not a smart pointer or anything. It's a normal object and one always have to take care of the lifetime of the object one is using...

For example:
// tex doesn't exist
void foo()
{
    sf::Texture tex;
    // tex exists
} // tex gets released/deleted
// tex doesn't exist


So, even though the constructor for sprite takes a *reference*, it's assumed that reference is to heap memory, or the sprite is not going to last past the current scope?
No it can be on the stack, but it (the texture) has to exist when you call window.draw(sprite).

For example this would work
void foo(sf::RenderWindow& rw)
{
    sf::Texture tex;
    tex.loadFromFile("img.png");
    sf::Sprite spr(tex, true);
    rw.clear();
    rw.draw(spr);
    rw.display();
} // tex & spr get released/deleted
« Last Edit: November 19, 2012, 02:04:27 am by eXpl0it3r »
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

masskiller

  • Sr. Member
  • ****
  • Posts: 284
  • Pointers to Functions rock!
    • MSN Messenger - kyogre_jb@hotmail.com
    • View Profile
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #8 on: November 19, 2012, 02:39:16 am »
I wasn't going to butt into this thread (since it was already answered anyway), but ichineko's attitude pretty much blew it all up.

As a courtesy rule if you are asking for help in something you don't know you do it politely not demanding it. eXpl0it3r might be too much of a nice guy, but most people wouldn't even think of helping you if you come all high and mighty when you're trying to ask about something you are ignorant about. Just like we all started.

I won't make this any longer since I don't want to cause a flame war in a help thread, but if you want help at least abide to what I wrote above. Nobody here is forced to help you just because you think you are special or whatever it may be.

I'll leave it here, even if you answer I won't so just take what I wrote as a self note for possible future threads. That way people will want to help you instead of arguing with you.
Programmer, Artist, Composer and Storyline/Script Writer of "Origin of Magic". If all goes well this could turn into a commercial project!

Finally back into the programming world!

cire

  • Full Member
  • ***
  • Posts: 138
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #9 on: November 19, 2012, 06:40:09 am »
fyi, I've been using C++ since before a standard *existed*.

So, even though the constructor for sprite takes a *reference*, it's assumed that reference is to heap memory, or the sprite is not going to last past the current scope?

The question after the claim just boggles my mind.

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #10 on: November 19, 2012, 08:28:31 am »
Quote
Well good luck with your attitude then, I don't like it, but who am I and why would you care?

That's the internet equivalent of asking me if I know who you are, and I should think you'd be embarrassed, but I'm guessing you're not.

I may or may not continue with SFML, but I'll be diving into the source from here on out.  I don't deal well with fragile egos, and doubly so with passive aggressive behavior.  Lets call it a personality quirk.

FWIW, I don't like the idea that these texture objects destroy the data on the vid card when they go out of scope, I think it's counter intuitive and makes it non-obvious when something is getting removed.;  The API made the construction and loading of these objects awkward due to the expense of the operations, I think they should have made the destruction just as awkward.  Files don't get created when you create a file object, and they aren't deleted when the file object goes out of scope, in case you're looking for precedence for that sort of behavior.

It certainly caused confusion on my part, and it took reading the source before I realized what was going on.  Arguably that's a good thing, but you would think this board would be able to convey that information.  Unfortunately ... egos and all that.


Quote
The question after the claim just boggles my mind.

I was referring to the texture.  It's conceivable for a sprite to lay claim to the actual OpenGL texture handle so the underlying resources don't get thrown away, regardless of the texture object's lifetime.

But they apparently chose to make it mimic the object's lifetime, which means I have to maintain the texture's lifetime as long as the sprite's lifetime, or we get bugs.

I don't like that design.  I understand it to some extent, but it isn't how I would have done it, at least not conceptually.  I'm sure there are valid reasons for them to do it (performance), but it's awkward and it's akin to a dangling pointer.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #11 on: November 19, 2012, 08:56:22 am »
Stop it please, and focus on the problem. If you have something personal to say, say it with PMs.

I'll delete any new message that contains anything other than questions and answers concerning the initial problem.

Thanks for spoiling my forum >:(
« Last Edit: November 19, 2012, 08:58:15 am by Laurent »
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #12 on: November 19, 2012, 09:04:29 am »
Quote
FWIW, I don't like the idea that these texture objects destroy the data on the vid card when they go out of scope, I think it's counter intuitive and makes it non-obvious when something is getting removed
SFML is a simple library, not a complex engine. There's no hidden/automatic ownership, if a sf::Texture instance is destroyed then the corresponding texture data is destroyed. That's the most obvious behaviour that can be implemented.

Your file example is totally different. The hard disk is a permanent storage, once written to the disk the file can be accessed by other applications, the std::ofstream instance doesn't own it, it's just an interface to write to it. But a texture is not supposed to live after your application is finished, and nobody has public access to textures in video memory; so how would it be accessed if no sf::Texture instance refers to it anymore?

Maybe you're coming from languages with garbage collection? Because in C++, it's very unusual to let a resource live after its owner object(s) is (are) destroyed.
Laurent Gomila - SFML developer

ichineko

  • Newbie
  • *
  • Posts: 44
    • View Profile
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #13 on: November 19, 2012, 02:49:25 pm »
It's also unusual to destroy a resource while it's in use by another object.

In my head the texture object is just a handle, hence the initial expectation that it would not completely disappear when the object gets cleaned up, especially since you chose to separate textures from sprites.

I'm not arguing that your approach shouldn't be done, just that it's surprising, to me at least.  You don't delete a file, you close the handle.  You don't delete the DB, you close the connection.  All of these are external resources whose lifetimes are controlled by an external entity.  Much like an OGL texture.  It makes perfect sense to me.

To me, the upshot is that you end up having to manually manage the lifetime of that texture, just like you would a raw pointer.  But your approach is also mostly thread safe, pros and cons, I just found it surprising.

But I do think a blurb in your documentation making this behavior a little more explicit wouldn't hurt.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Explanation of interactions between Image, Texture, and Sprite?
« Reply #14 on: November 19, 2012, 03:19:50 pm »
Quote
It's also unusual to destroy a resource while it's in use by another object.
Yep, so don't do it ;)
The point is that you are responsible of the texture, it's you who knows when the texture is in use or not, and who decides when to destroy it.
In fact, Sprite::setTexture is just a convenience function, I could remove it and you would have to call window.draw(sprite, texture);, which would make it obvious that the texture is used at this point and that is has to be alive.

Quote
In my head the texture object is just a handle, hence the initial expectation that it would not completely disappear when the object gets cleaned up, especially since you chose to separate textures from sprites.
Even if it was a handle, if the only thing that refers to it (the sf::Texture instance) is destroyed, it must be destroyed too. Otherwise it would be lost in the nature and could be considered a leak.
And... it's not a handle, otherwise it would be named sf::TextureHandle. sf::Texture really is what it means: a texture. If you destroy it, you destroy the texture. I think that things are overcomplicated in your head; or at least biased by your personal background ;)

Quote
You don't delete a file, you close the handle.  You don't delete the DB, you close the connection.  All of these are external resources whose lifetimes are controlled by an external entity.  Much like an OGL texture.  It makes perfect sense to me.
In my opinion these comparisons are irrelevant. Files and databases are persistent external objects that applications use; textures are resources that you create, manage and destroy during the lifetime of the application. Nobody else will use them from another program, and nothing must remain when your program ends.

If you have a std::vector, you expect it to release its memory when it is destroyed, because the vector is the array, not a handle to it. Now what makes sf::Texture, an array of pixels, different? Is it special because it interacts with another class? Who is supposed to control its lifetime, if not you?

Of couse I could use shared ownership between user and sf::Sprite, but that would involve to manipulate sf::Texture instances through pointers and to allocate them on the heap. That would be a pretty bad design for C++; it would be ok for garbage collected languages.
« Last Edit: November 19, 2012, 03:29:27 pm by Laurent »
Laurent Gomila - SFML developer