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

Author Topic: [SOLVED] VertexArray & Vertex's tilemap nightmare  (Read 19035 times)

0 Members and 1 Guest are viewing this topic.

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
[SOLVED] VertexArray & Vertex's tilemap nightmare
« on: January 19, 2013, 03:11:49 am »
Hello, hello! :D

I had a great progress on my framework, now, I have animated sprites :'D. BUT, I'm experiencing a lot of lag :-/ :(



A LOT! xd. I thought that was the tilemap drawing's fault, even if I'm drawing black squares on the screen (have to implement something to draw a color if no tmx file is passed), 10x10 pixels size in 80x60 tiles. Anyway, I want to use VertexArrays and Vertexs.

BOY! I don't have any idea at all about using VertexArrays to draw tilemaps, I was reading C++ and C# code but is like reading this:
Code: [Select]
使用系统;
使用SFML.Graphics;
使用SFML.Window;
使用测试;

命名空间SFML.Utils
{
    公共的委托无效TileProvider(X,Y,诠释层,出彩的颜色,出IntRect REC);
    MapRenderer:可绘制对象类
    {
        私人只读持股量TileSize;
        公共只读整型层;

        私人诠释的高度;
        私人诠释宽度;

        私人Vector2i偏移;
        私人顶点顶点;

        提供私人TileProvider;
        私人纹理质感;

        ,公共MapRenderer(纹理质地,TileProvider供应商,持股量tileSize=16,智力层=1)
        {
            (供应商== NULL | |层<= 0)抛出新的ArgumentException();
            this.provider供应商;

            TileSize tileSize;
            层=层;

            顶点=新的顶点[0];
            this.texture质感;

        }

        公共无效刷新()
        {
            RefreshLocal(0,0,宽度,高度);
        }

        私人无效RefreshLocal(左,诠释顶部,诠释的权利,诠释底部)
        {
            (VAR Y =顶部<底部,Y++)
                (VAR所述=左,X权; X ++)
                {
                    刷新(X + offset.X,Y+ offset.Y);
                }
        }

xD
anyway, get the idea, I don't understand ANYTHING! even that I can read C++ code. My question is:

How should I use VertexArray and Vertexs in order to draw tiles? because something that is confusing for me is the choosing a color for the Vertex. What's the idea of using that? Why you don't use a reference to a texture instead? Should I inherit from Drawable class and use the VertexArray and Vertex as an attributes?

I also like the idea of drawing only the vertex that the user sees (what he sees through sfml.View) but I don't know how to proceed, so, maybe a lay explication/mentoring might be helpful (once you understand how to use Vertex) for this.

cheers!
« Last Edit: February 01, 2013, 12:56:21 am by shackra »

GNU User
Python programmer
Blog

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #1 on: January 23, 2013, 03:01:57 am »
Hello!

I see you wrote that four days ago, so sorry to be late on this. Don't hesitate to ask your questions via my private email address (in case I don't answer soon and you should get faster answers too :p). I'll make an effort to check the forum more often.

I'm aware there are performance issues (#65) when doing intensive computation with vectors (since they're still handled at Python level) but I don't think this is your case. Note: this issue should be fixed soon since fused type Cython feature is now fixed in last stable release.

About Vertex and VertexArray:
First I would suggest to read the documentation, Vertex and VertexArray, but I admit this is not enough to apprehend what is really going on and thus, write efficient code.

SFML is based on OpenGL. Basically, OpenGL only knows vertices location. Then you tell OpenGL to draw these vertices and how to link them to make shapes. E.g: You'll need four vertices to make a rectangle. Note that SFML use Vertex and VertexArray internally to draw your shapes, your sprites, etc.

As sf.VertexArray inherits from sf.Drawable, once you have defined your vertices and stored them in a VertexArray, you'll be able to draw as a traditional drawable (sprite, shape, text):
window.draw(vertex_array)

To try it out:
import sfml as sf
window = sf.RenderWindow(sf.VideoMode(640, 480), "pysfml")
lines = sf.VertexArray(sf.PrimitiveType.LINES_STRIP, 2)
lines[0].position = (10, 10)
lines[1].position = (100, 10)

lines.append(sf.Vertex((100, 100)))

lines.resize(4)
lines[3].position = (10, 100)

window.clear()
window.draw(lines)
window.display()
raw_input()
 

I'm glad you have animations working :) and hope you'll get your performance issues solved quickly!
Interested in using SFML with Python ? Try out its Python binding!

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
Re: VertexArray & Vertex's tilemap nightmare
« Reply #2 on: January 24, 2013, 02:12:13 am »
cool, a square!

I'm glad you have animations working :) and hope you'll get your performance issues solved quickly!

Yes, I did by filling the screen with white when no TMX file is passed to my AbstractScene class, just watch:



However, I'm trying to wrap my mind on this code that archives what I want https://github.com/SFML/SFML/wiki/Source:-TileMap-Render :(

EDIT:

I'm trying to undestand Tile-mapping with Vertexs... I wrote an example that goes like this:

#!/usr/bin/env python2
# coding: utf-8

import sfml

class Mapa(sfml.Drawable):
    def __init__(self, texture):
        sfml.Drawable.__init__(self)
        self.vertexarray = sfml.VertexArray(sfml.PrimitiveType.QUADS)
        self.texture = texture
       
    def draw(self, target, states):
        states.texture = self.texture
        target.draw(self.vertexarray, states)
       
def main():
    wn = sfml.RenderWindow(sfml.VideoMode(800, 600), "Prueba de Vertexs")
    wn.vertical_synchronization = True
    wn.framerate_limit = 60
   
    textura = sfml.Texture.from_file("textura.png")
    mapa = Mapa(textura)
    # Creamos una serie de vertexs conforme al mapa
    v1 = sfml.Vertex(sfml.Vector2(100, 1), sfml.Color.BLUE, sfml.Vector2(0, 0))
    v2 = sfml.Vertex(sfml.Vector2(300, 32), sfml.Color.RED, sfml.Vector2(0, 32))
    v3 = sfml.Vertex(sfml.Vector2(45, 64), sfml.Color.BLACK, sfml.Vector2(0, 64))
    v4 = sfml.Vertex(sfml.Vector2(32, 96), sfml.Color.YELLOW, sfml.Vector2(32, 0))
    # Existen más baldosas pero lo dejare hasta ahí
    for vertex in [v1, v2, v3, v4]:
        mapa.vertexarray.append(vertex)
       
    while wn.opened:
        for event in wn.events:
            if isinstance(event, sfml.CloseEvent):
                wn.close()
               
        wn.clear(sfml.Color.WHITE)
        wn.draw(mapa)
        wn.display()
       
if __name__ == "__main__":
    main()
 

and I got this:



Not what I was expecting xd. I'm using this image as texture:


any help? :)
« Last Edit: January 24, 2013, 05:35:43 am by shackra »

GNU User
Python programmer
Blog

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #3 on: January 24, 2013, 04:47:55 pm »
Unfortunately OpenGL doesn't support concave shape :D And by consequence, SFML neither :( But you can build them from multiple convex shapes if you really need (be warned, it's pain in the ass). But tiles are convex shapes so for your tile engine using Vertex and VertexArray, you're fine.

In your snipped code, you tried to construct a concave shape which renders badly, so you should try with a rectangle to start. This shape is built from vertices which all have a color, so your shape is filled with a gradient color (interpolation).  Then, you applied a texture on top of that which merges the texture and the gradient color and give you at the end a weird shape :). The third argument in Vertex constructor tex_coords tells OpenGL what part of your texture is used to fill the shape.

To experiment:

1) Start with a rectangle without texture
2) Then, try with white color points and a texture
3) Make your shape convex (other than a rectangle)
3) Modify tex_coords to fill your shape with different part of your texture

#!/usr/bin/env python2
# coding: utf-8

import sfml

class Mapa(sfml.Drawable):
    def __init__(self, texture):
        sfml.Drawable.__init__(self)
        self.vertexarray = sfml.VertexArray(sfml.PrimitiveType.QUADS)
        self.texture = texture
       
    def draw(self, target, states):
        states.texture = self.texture
        target.draw(self.vertexarray, states)
       
def main():
    wn = sfml.RenderWindow(sfml.VideoMode(800, 800), "Prueba de Vertexs")
    wn.vertical_synchronization = True
    wn.framerate_limit = 60
   
    textura = sfml.Texture.from_file("textura.png")
    mapa = Mapa(textura)

    # Creamos una serie de vertexs conforme al mapa
    v1 = sfml.Vertex(sfml.Vector2(10, 10), sfml.Color.WHITE, sfml.Vector2(0, 0))
    v2 = sfml.Vertex(sfml.Vector2(600, 50), sfml.Color.WHITE, sfml.Vector2(86, 0))
    v3 = sfml.Vertex(sfml.Vector2(450, 450), sfml.Color.WHITE, sfml.Vector2(86, 86))
    v4 = sfml.Vertex(sfml.Vector2(10, 300), sfml.Color.WHITE, sfml.Vector2(0, 86))
    v5 = sfml.Vertex(sfml.Vector2(10, 10), sfml.Color.WHITE, sfml.Vector2(0, 0))

    # Existen más baldosas pero lo dejare hasta ahí
    for vertex in [v1, v2, v3, v4, v5]:
        mapa.vertexarray.append(vertex)
       
    while wn.is_open:
        for event in wn.events:
            if isinstance(event, sfml.CloseEvent):
                wn.close()
               
        wn.clear(sfml.Color.WHITE)
        wn.draw(mapa)
        wn.display()
       
if __name__ == "__main__":
    main()
Interested in using SFML with Python ? Try out its Python binding!

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
Re: VertexArray & Vertex's tilemap nightmare
« Reply #4 on: January 24, 2013, 05:59:10 pm »


cool! :)

I feel like I'm not have the right idea about Vertex's position and text-coords (and sfml.PrimitiveType.QUADS). For instance, which position (on screen) and what's wrapping (from my texture) does
v1 = sfml.Vertex(sfml.Vector2(10, 10), sfml.Color.WHITE, sfml.Vector2(0, 0))
,
v2 = sfml.Vertex(sfml.Vector2(600, 50), sfml.Color.WHITE, sfml.Vector2(86, 0))
and
v3 = sfml.Vertex(sfml.Vector2(450, 450), sfml.Color.WHITE, sfml.Vector2(86, 86))
why 5 vertex and no 4 or 3? (that depends on the sfml.PrimitiveType.*?)

If you can add screenshots/pictures to your explanation, I'll appreciate that!

cheers!

GNU User
Python programmer
Blog

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #5 on: January 24, 2013, 09:19:01 pm »
This topic is rather related to how OpenGL work to render 2d vertices and its documentation might help you understand. Because SFML just provides wrappers to make things more convenient.

You're right, the fifth vertex is not necessary (and shouldn't even exist).

It's quite easy to understand, just keep things simple: you define 2d vertices (location + color), then tell OpenGL how to draw them (sf.PrimitiveType.QUAD is what you need here).

OpenGL will fill your shape with the colors you gave to your vertices. If you used four red vertices, your shape will be red. If you used multiple colors, you'll get a gradient color.

Additionally you can fill your shape with a texture as your screenshot shows it.

But now you can combine both and you'll get this result.


Now, use tex_coords to use the top left corner of your texture by replacing  86 with 46.
    v1 = sfml.Vertex(sfml.Vector2(10, 10), sfml.Color.RED, sfml.Vector2(0, 0))
    v2 = sfml.Vertex(sfml.Vector2(600, 50), sfml.Color.RED, sfml.Vector2(86, 0))
    v3 = sfml.Vertex(sfml.Vector2(450, 450), sfml.Color.RED, sfml.Vector2(86, 86))
    v4 = sfml.Vertex(sfml.Vector2(10, 300), sfml.Color.RED, sfml.Vector2(0, 86))
And you'll get this:

Interested in using SFML with Python ? Try out its Python binding!

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
Re: VertexArray & Vertex's tilemap nightmare
« Reply #6 on: January 24, 2013, 10:07:04 pm »
ok, ok, I'm getting the idea now.

Looks like you can only make one shape per vertexarray, no? how it comes for tilemapping? I'm missing something?

GNU User
Python programmer
Blog

G.

  • Hero Member
  • *****
  • Posts: 1592
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #7 on: January 24, 2013, 10:11:03 pm »
You can (and will) have more than 4 vertices in your vertex array. ;)

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
Re: VertexArray & Vertex's tilemap nightmare
« Reply #8 on: January 28, 2013, 02:26:53 am »


    # Creamos una serie de vertexs conforme al mapa
    v1 = sfml.Vertex(sfml.Vector2(0, 0), sfml.Color.WHITE, sfml.Vector2(0, 0))
    v2 = sfml.Vertex(sfml.Vector2(32*2, 0), sfml.Color.WHITE, sfml.Vector2(32, 0))
    v3 = sfml.Vertex(sfml.Vector2(32*2, 32*2), sfml.Color.WHITE, sfml.Vector2(32, 32))
    v4 = sfml.Vertex(sfml.Vector2(0, 32*2), sfml.Color.WHITE, sfml.Vector2(0, 32))
    v5 = sfml.Vertex(sfml.Vector2(32*2, 0), sfml.Color.WHITE, sfml.Vector2(64, 64))
    v6 = sfml.Vertex(sfml.Vector2(64*2, 0), sfml.Color.WHITE, sfml.Vector2(95, 64))
    v7 = sfml.Vertex(sfml.Vector2(64*2, 32*2), sfml.Color.WHITE, sfml.Vector2(95, 95))
    v8 = sfml.Vertex(sfml.Vector2(32*2, 32*2), sfml.Color.WHITE, sfml.Vector2(64, 95))
 

Ok, I think that I'm getting the idea now... what about moving vertex to just show the ones that the user can see? D:

GNU User
Python programmer
Blog

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #9 on: January 28, 2013, 07:47:57 pm »
I tried to understand the C++ code (about tile rendering using Vertex and VertexArray) but couldn't figure out why it would faster thus, sorry, I cannot help you about that.

By the way, seems you're mastering drawing shapes/tiles at hand, once you understand everything I won't mind a feedback :p
Interested in using SFML with Python ? Try out its Python binding!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10821
    • View Profile
    • development blog
    • Email
Re: VertexArray & Vertex's tilemap nightmare
« Reply #10 on: January 28, 2013, 07:55:46 pm »
I tried to understand the C++ code (about tile rendering using Vertex and VertexArray) but couldn't figure out why it would faster
The main reason is, that you only have one draw call for all the vertices, instead of N draw calls for N sprites (with 4 vertices). GPUs are built to process millions of vertices at once, thus there shouldn't be a problem passing on an huge array. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #11 on: January 28, 2013, 10:10:18 pm »
Woaw, that's very interesting! I'm quite new to OpenGL, how do you set many textures to be all drawn in one call ? (I assumed you have one texture per tile.)
Interested in using SFML with Python ? Try out its Python binding!

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10821
    • View Profile
    • development blog
    • Email
Re: VertexArray & Vertex's tilemap nightmare
« Reply #12 on: January 28, 2013, 10:23:50 pm »
(I assumed you have one texture per tile.)
Nope, you use one texture with all tiles on (if it's not too big) and then you simply set the texture coordinates you want your vertices to map to. ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Sonkun

  • Moderator
  • Full Member
  • *****
  • Posts: 241
    • View Profile
Re: VertexArray & Vertex's tilemap nightmare
« Reply #13 on: January 28, 2013, 10:48:36 pm »
Things get clearer now :p Thanks for the tip! :)
Interested in using SFML with Python ? Try out its Python binding!

shackra

  • Jr. Member
  • **
  • Posts: 54
    • View Profile
    • http://swt.encyclomundi.org
Re: VertexArray & Vertex's tilemap nightmare
« Reply #14 on: January 29, 2013, 06:50:28 am »
I tried to understand the C++ code (about tile rendering using Vertex and VertexArray) but couldn't figure out why it would faster
The main reason is, that you only have one draw call for all the vertices, instead of N draw calls for N sprites (with 4 vertices). GPUs are built to process millions of vertices at once, thus there shouldn't be a problem passing on an huge array. ;)

However, I'm worried about perfomance with huge maps (8000x2000~ tiles), but what I don't get at all is the process of "moving" the right vertexs to the left top corner of the screen in order to start drawing the tiles.
Trying to figure out which Vertex are inside the View rect isn't good Idea either because some points of the 4 that compose the vertex will not been draw, thus, showing just three, two or one of them (as when you delete one vertice of a plane in Blender 3D, the plane lose its face!)

Maybe I should ask for more commentaries in that source code...

By the way, seems you're mastering drawing shapes/tiles at hand, once you understand everything I won't mind a feedback :p

No problem ;)

GNU User
Python programmer
Blog

 

anything