Drawing Static Sprites Using Vertex Buffers

Hey! In this tutorial, you’ll learn how you can use vertex buffers to draw static sprites. If you have a lot of static sprites to draw, using vertex buffers can be a lot faster than using objects or draw_sprite() functions. The grass in my grass asset is drawn using vertex buffers.

The grass is static even though it appears to be moving. That is done using shaders.

So, let me show you how you can draw a simple sprite using a vertex buffer.


Vertex Format

A vertex format specifies what kind of data will go into a vertex buffer.

For drawing a sprite, we mainly need three data types: 2D position (position of the sprite inside the room), Texcoord (position of the sprite on the texture page) and color.

So here’s how I’ll create the vertex format (all of the code hereafter is in the Create event):

vertex_format_begin();

vertex_format_add_position();
vertex_format_add_texcoord();
vertex_format_add_color();

var format = vertex_format_end();

vertex_format_begin() will start creating a vertex format, after which we can add the data types we want. So here I’ll add “position”, “texcoord” and “color”. Then vertex_format_end() ends the process of creating the vertex format, and returns its ID so that it can be stored in a variable.


Vertex Buffer

Now we can make the vertex buffer.

vbuff = vertex_create_buffer();

This will create a vertex buffer and store its ID in vbuff.

Drawing the Sprite

Note: Open Tools > Texture Groups and make sure “Automatically Crop” is disabled.

A vertex buffer takes points. By adding points, we can build triangles. For drawing a sprite, we have to create two triangles that will make a rectangle to draw the complete sprite:

1.png

 

Since one triangle has three points, in total we’ll need to add six. But before that, we must create some variables:

//sprite
tex = sprite_get_texture(spr_test, 0);

var uvs = texture_get_uvs(tex);

var uv_left = uvs[0];
var uv_top = uvs[1];
var uv_right = uvs[2];
var uv_bottom = uvs[3];

var left = x;
var top = y;
var right = x + sprite_get_width(spr_test);
var bottom = y + sprite_get_height(spr_test);

The function sprite_get_texture() takes a sprite and image index and returns its texture. That texture will be stored inside tex.

The function texture_get_uvs() returns the UV coordinates of a texture, inside an array. Basically, those UV coordinates are the top, left, right and bottom coordinates of the texture on the texture page. So, accordingly, those values will be stored inside variables uv_left, uv_top, uv_right and uv_bottom.

Next, the variables left, top, right and bottom will store the coordinates inside the room where the sprite is to be drawn.

Building the Triangles

Now, it’s time to build the triangles:

//begin
vertex_begin(vbuff, format);

//triangle 1
vertex_position(vbuff, left, top);
vertex_texcoord(vbuff, uv_left, uv_top);
vertex_color(vbuff, c_white, 1);

vertex_position(vbuff, right, top);
vertex_texcoord(vbuff, uv_right, uv_top);
vertex_color(vbuff, c_white, 1);

vertex_position(vbuff, left, bottom);
vertex_texcoord(vbuff, uv_left, uv_bottom);
vertex_color(vbuff, c_white, 1);

//triangle 2
vertex_position(vbuff, right, top);
vertex_texcoord(vbuff, uv_right, uv_top);
vertex_color(vbuff, c_white, 1);

vertex_position(vbuff, right, bottom);
vertex_texcoord(vbuff, uv_right, uv_bottom);
vertex_color(vbuff, c_white, 1);

vertex_position(vbuff, left, bottom);
vertex_texcoord(vbuff, uv_left, uv_bottom);
vertex_color(vbuff, c_white, 1);

vertex_begin() starts the vertex building. After this function, you can start adding the points.

The points must have data for each type created in the vertex format. Since our format had position, texcoord and color, you can see that each of the 6 points have those values.

This way, I am creating those two triangles. The first triangle has three points: (left, top), (right, top) and (left, bottom):

2.PNG

And the second triangles has these points: (right, top), (right, bottom) and (left, bottom):

3.PNG

The color is simply c_white with 1 alpha.

At the end, I’ll add this:

vertex_end(vbuff);
vertex_freeze(vbuff);

vertex_end() will end the vertex building, and vertex_freeze() will freeze the vertex buffer, making it read-only. This results in a faster buffer but you can no longer add more data to it.

Finally, I’ll add this to the Draw event:

vertex_submit(vbuff, pr_trianglelist, tex);

This submits the vertex buffer so that it can be drawn. The first argument is the vertex buffer itself, the second argument is the primitive type, and the third argument is the texture to be used.


Depth

You can add depth to the vertex points. Before creating the buffer, you have to use this function:

gpu_set_ztestenable(true);

This function will enable depth testing.

Then, in the vertex format building, instead of vertex_format_add_position(), you should use vertex_format_add_position_3d():

vertex_format_begin();

vertex_format_add_position_3d();
vertex_format_add_texcoord();
vertex_format_add_color();

var format = vertex_format_end();

Then when you’re building the vertex triangles, you need to use vertex_position_3d() and in the last argument, add the depth.

Example:

//triangle 1, point 1
vertex_position_3d(vbuff, left, top, 100); //100 depth
vertex_texcoord(vbuff, uv_left, uv_top);
vertex_color(vbuff, c_white, 1);

This should apply depth to the vertex buffer.


Alpha Testing

When drawing the sprites, there might be a problem where you can’t see a sprite behind one. In other words, the empty parts of a sprite might not appear empty. To fix that, use this before the vertex_submit() function in the Draw event:

gpu_set_alphatestenable(true);

Conclusion


That’s it! There’s a lot you can do with vertex buffers, and when used with shaders, you can make some amazing effects, like my grass asset:

grasset.gif

If you want to support me, you can do so by checking out my assets. (^_^)

See you later, and till then, happy dev’ing!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s