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

Author Topic: VertexArray  (Read 9652 times)

0 Members and 1 Guest are viewing this topic.

gyscos

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
VertexArray
« on: November 16, 2012, 10:32:29 am »
Hey there :)

From what I gathered in the various posts I read here, there is some black magic available to draw tile maps, and that is the VertexArray.

I understand this is a kind of Graal for many 2D games, so I'll try to understand it a little better.

Some people said I could divide the world in big chunks, with a vertexArray for each chunk, and use these chunks for culling.
So how exactly does it work ? Here are my thoughts.

- Each chunk represents a static part of the map. So it's set once at first, and never ever edited again.
- The visible chunks are picked and drawn. Since the visible part of the map can move (or we wouldn't need culling in the first place), it means we have to translate the chunks to their correct position. But the documentation says VertexArrays are not transformable.

Does this mean we can't translate the whole array ?
If we can't, then will we need to translate each vertex individually ? But then we lose the "set once, don't touch again" property of these chunks...

Now, I'll propose another solution. Since I didn't see it mentioned in the threads I read, I'll assume that's because I missed something, and I'll be glad if you can show it to me.

We'll start from a VertexArray-less situation, with the usual per-tile culling, and where we draw each tile individually.
Now, let's just replace the single-sprite drawing call with one that adds a quad to the vertex array, with the position it would have been drawn to.
In the end, the vertex array just acts as a gatherer for all the draw calls, and bath them all in the end.

Was I too unclear ?
If not, would it even work ?
If it would, would it be much slower than the other method ? In the end, we only have one draw() call, and tile-precise culling.
« Last Edit: November 16, 2012, 10:34:10 am by gyscos »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #1 on: November 16, 2012, 10:39:29 am »
Quote
Each chunk represents a static part of the map. So it's set once at first, and never ever edited again.
Correct

Quote
The visible chunks are picked and drawn. Since the visible part of the map can move (or we wouldn't need culling in the first place), it means we have to translate the chunks to their correct position
You can (and should) create the chunk's vertices directly at their final position. For runtime you can them use sf::View to scroll the map.

Quote
VertexArrays are not transformable
Not directly, but you can pass a sf::Transform when you draw a vertex array.
sf::Transform transform;
transform.translate(x, y);
window.draw(vertexArray, transform);

Quote
If not, would it even work ?
That's more or less what SFML does internally as an optimization. As long as you draw small entities with the same texture, SFML pre-transforms them and batches them inside a bigger vertex array.

But anyway, if you define vertices directly at their final position there should be no problem.
Laurent Gomila - SFML developer

gyscos

  • Jr. Member
  • **
  • Posts: 69
    • View Profile
Re: VertexArray
« Reply #2 on: November 16, 2012, 11:01:19 am »
Thanks ! :)

Oow, I forgot about sf::View's ability to "translate" the map. With this, indeed, I no longer have to move the vertices on each frame. And giving a sf::Transform in the draw() call can achieve the same result.

As a side question, among these two solutions (Translate the View or translate the VertexArrays at draw call), which is the best practice ? I'd say moving the view, as it's semantically more correct (and eases the placement of other layers).

Can two quads in the VertexArray overlap ? If so, is the last one on top ? Or is this undefined ?

If a quad's vertices aren't axis-aligned, but still define a correct rectangle, will this rotate the texture correctly ? Can this be used to draw rotated (or any other linear transformed) sprites ?
EDIT : ok, just saw that quads were actually two triangles, which may affect some trapezoidal transformations. Linear transformation should be fine, though... shouldn't they ?

Also, since SFML already does the optimization for us, is there really a point in using VertexArrays ? As long as we're careful to use the same texture for consecutive draw() calls, there souldn't be too much of a difference... right ? It does make culling much easier...
« Last Edit: November 16, 2012, 11:16:19 am by gyscos »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #3 on: November 16, 2012, 11:28:56 am »
Quote
which is the best practice ? I'd say moving the view, as it's semantically more correct (and eases the placement of other layers).
Yep.
These are two very different things: moving entities in the 2D world, and changing what part of the world is visible in the window. sf::View is designed to handle the latter.

Quote
Can two quads in the VertexArray overlap ? If so, is the last one on top ? Or is this undefined ?
They can overloap, and the last one should be on top. I don't know if it's strictly defined in the OpenGL spec though.

Quote
If a quad's vertices aren't axis-aligned, but still define a correct rectangle, will this rotate the texture correctly ? Can this be used to draw rotated (or any other linear transformed) sprites ?
EDIT : ok, just saw that quads were actually two triangles, which may affect some trapezoidal transformations. Linear transformation should be fine, though... shouldn't they ?
You're right. As long as your quad looks like a rectangle it will be ok, but if you try to simulate a perspective effect the texture mapping will most likely be wrong.
Don't forget that high-level entities (sprite, text, shape) all use vertex arrays internally, so everything that you can do with them is also possible with vertex arrays.

Quote
Also, since SFML already does the optimization for us, is there really a point in using VertexArrays ? As long as we're careful to use the same texture for consecutive draw() calls, there souldn't be too much of a difference... right ? It does make culling much easier...
It's more expensive if done by SFML, because:
- it has to transform every point everytime they are drawn
- it has to dynamically manage (allocate/deallocate/copy) the internal vertex array

In fact for maximum performances, everything should use vertex arrays directly. High-level classes are there mainly for convenience and historical reasons.
Laurent Gomila - SFML developer

Nekroze

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: VertexArray
« Reply #4 on: November 16, 2012, 11:03:52 pm »
Quote
You can (and should) create the chunk's vertices directly at their final position. For runtime you can them use sf::View to scroll the map.

By this i assume you would say that if i was using a vertex array, my current system of storing each chunks screen position and the character moves by moving all chunks to the opposite direction to what the player wants to move, would be incorrect?

See i did this so that i didn't have to move a view across a pseudo-infinite map because i figured that eventually the coordinates would be larger then the floats and int's that store the positions of things. So this way the only coordinates that ever need to be used are all pixel positions in the screen plus and minus about 500-1000 max.

First question then, am i right that placing down the vertex arrays in absolute positions and using the sfView to move the character around will, eventually, hit undefined behavior with coordinates beyond a float's range for example.

Secondly should i attempt to use my current method then but with vertex arrays even though you say they should be placed in their final positions.

Last up, what would be the performed way of doing perspective on tiles then?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #5 on: November 17, 2012, 08:47:36 am »
Quote
By this i assume you would say that if i was using a vertex array, my current system of storing each chunks screen position and the character moves by moving all chunks to the opposite direction to what the player wants to move, would be incorrect?
This is not incorrect, but not the way it's supposed to be done.

Quote
See i did this so that i didn't have to move a view across a pseudo-infinite map because i figured that eventually the coordinates would be larger then the floats and int's that store the positions of things
Are you sure that you can reach the max value a float can store (10^37)?
But ok, this might be a problem at approximately 10^7 (?), where 32-bit floats start to lose precision.

Quote
Secondly should i attempt to use my current method then but with vertex arrays even though you say they should be placed in their final positions.
... if possible. If not, then you must find another solution, and I'd say that yours is not bad ;)

Quote
Last up, what would be the performed way of doing perspective on tiles then?
Perspective?
Laurent Gomila - SFML developer

Nekroze

  • Newbie
  • *
  • Posts: 30
    • View Profile
Re: VertexArray
« Reply #6 on: November 17, 2012, 08:59:55 am »
Cool that answered a lot of my questions.

As far as reaching the max of a float while it isn't likely to happen it would be possible in my game and i would rather not put limits that i don't have to. with a 32 bit float and 64x64 tile chunks with each tile 32x32 that would impose a limit of 4882x4882 chunks where the current system i have will allow as many chunks as the max an int can store on the host system, needless to say a lot more then 4882x4882.

By perspective i mean some way to make it so you are not looking straight down on perfectly square tiles, something so that tiles in the distance are smaller or something to give the illusion that the top of the screen is farther away.
« Last Edit: November 17, 2012, 09:12:52 am by Nekroze »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #7 on: November 17, 2012, 10:38:31 am »
Quote
By perspective i mean some way to make it so you are not looking straight down on perfectly square tiles, something so that tiles in the distance are smaller or something to give the illusion that the top of the screen is farther away.
I don't know if there's a robust way of doing that with SFML. If you make your tiles trapezoidal, texture mapping will be incorrect because there's no perspective correction.
Laurent Gomila - SFML developer

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: VertexArray
« Reply #8 on: November 20, 2012, 06:13:54 pm »
Wait a minute... I really don't understand those sf::VertexArrays. I searched the documentation, the forum and the wiki but none of that seemed to help me all that much...
So VertexArrays can only use primitives such as points, lines, triangles and rectangles. But how do you insert a texture into it. You don't have to copy each individual pixel, right? Because that seems to be a lot less efficient than drawing tile per tile. So the question is: how does one copy a texture into a VertexArray?
Also, what are these chunks? What do you mean with static parts of the map? If I had an indoor map with a size of 50x50 tiles, but there are lots of doors and switches to interact with which changes the texture of it, it doesn't seem all too helpful anymore...

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: VertexArray
« Reply #9 on: November 20, 2012, 06:18:48 pm »
But how do you insert a texture into it. You don't have to copy each individual pixel, right? Because that seems to be a lot less efficient than drawing tile per tile. So the question is: how does one copy a texture into a VertexArray?
You don't 'copy' it into, you pass it as second parameter in the draw call, i.e. draw(vertexarray, texture). It will then call the constructor of the RenderState class and then get passed to the draw function.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: VertexArray
« Reply #10 on: November 20, 2012, 11:05:35 pm »
Sorry for the noob questions, but I still can't figure it out. The code
// setting up rectangle in (0,0) and size (100,100)
sf::VertexArray vertex(sf::Quads, 4);
vertex[0].position = sf::Vector2<float>(0,0);
vertex[1].position = sf::Vector2<float>(100,0);
vertex[2].position = sf::Vector2<float>(100,100);
vertex[3].position = sf::Vector2<float>(0,100);

// load texture
sf::Texture texture;
texture.loadFromFile("texture.png");

// render
window.clear();
window.draw(vertex, &texture);
window.display();
 
shows nothing at all. When creating an empty sf::RenderStates (thus with NULL texture) a white square appears which is to be expected. When replacing sf::VertexArray with an sf::Sprite it doesn't seem to do anything either. This was just a test to what the extra argument exactly does.

So I'll rephrase: what is the role of sf::RenderStates and what influence will it have when adding it to the sf::RenderWindow::draw() function?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #11 on: November 20, 2012, 11:16:24 pm »
What's missing in your code are the texture coordinates of the vertices. You don't define how to map the texture on your rectangle.
Laurent Gomila - SFML developer

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: VertexArray
« Reply #12 on: November 21, 2012, 01:06:38 am »
Finally! Now I'm getting it :) So I should have set
vertex[0].texCoords
too. That took a while... Thank you very much!

Now that I know how these work, my question of the chunks still remains. If you want to change for example an image of a closed door with an opened one, changing the variables doesn't seem like a big task. Why should it be stationary? Or is this the reason why one should use sf::VertexArrays?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: VertexArray
« Reply #13 on: November 21, 2012, 08:16:58 am »
Quote
If you want to change for example an image of a closed door with an opened one, changing the variables doesn't seem like a big task. Why should it be stationary?
You're right, it's not a big task. And you can do it. What would be wrong is to change all the vertices every frame -- but it would probably still be ok (think about a particle engine, for example).
Laurent Gomila - SFML developer

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: VertexArray
« Reply #14 on: November 21, 2012, 11:47:11 am »
Ok, thanks for the answers :) helped me out a lot!
So to wrap it up: sf::VertexArrays are used as containers so you don't have to call sf::RenderWindow::draw() too much.

 

anything