SOLVED vertex_submit & sprite_get_texture

Cash Munkey

Member
Hey forum, I'm looking for a little help understanding how the vertex_submit() function receives a texture.

Consider a fairly simple vertex with position, color, and texture. This would be declared in obj_triangle.create step.
Code:
vertex_format_begin();
vertex_format_add_position();
vertex_format_add_colour();
vertex_format_add_texcoord();
vtx_format = vertex_format_end();
vtx_buff = vertex_create_buffer();
And for the sake of simplicity, all I want to do is draw a single, right triangle with sides of length 32 (pixels). This happens in obj_triangle.draw.
(Also, assume that spr_block_32 is a 32x32 pixel sprite that exists in the project.)
Code:
vertex_begin(vtx_buff, vtx_format);

vertex_position(vtx_buff, 100, 100);
vertex_colour(vtx_buff, c_white, 1);
vertex_texcoord(vtx_buff, 0, 0);

vertex_position(vtx_buff, 131, 100);
vertex_colour(vtx_buff, c_white, 1);
vertex_texcoord(vtx_buff, 1, 0);

vertex_position(vtx_buff, 100, 131);
vertex_colour(vtx_buff, c_white, 1);
vertex_texcoord(vtx_buff, 0, 1);

vertex_end(vtx_buff);

vertex_submit(vtx_buff, pr_trianglelist, sprite_get_texture(spr_block_32, 0));
My question is with the last line of the second code block. I am using sprite_get_texture() following the Example provided in the documentation for vertex_submit(). BUT also, the documentation for sprite_get_texture() indicates that it returns a special pointer for the (whole) sprite texture page. The behavior I'm seeing is that the example above will only draw the primitive correctly if spr_block_32 is the ONLY sprite on the texture page (otherwise the drawn image just looks like noise/static).

Is there a function I'm missing to get the cell of sprite on a texture page? Or am I misunderstanding how vertex buffers use textures?
 

Bart

WiseBart
You're missing the information from sprite_get_uvs, as rytan451 says.

Sprites, fonts and tile sets are laid out on texture pages in a certain way. You can see how the texture pages look by making a Preview under Game Options > Windows or by using this script to visualize the layout at runtime.

The uv coordinates that you define in the vertex buffer, (0, 0), (1, 0) and (0, 1), refer to the entire page/image/texture. (0, 0) is top left, (1, 0) is top right and (0, 1) is bottom left.
But a single sprite (or font, or tileset) usually only takes up a part of that space. Unless you enable Separate Texture Page for a sprite, since that will put it on an entirely new image/"page" and will make the corners of the sprite correspond to the corners of the texture page.

What you see as "noise/static" is the triangle being drawn using the entire texture page. It may look odd, depending on what else is on that texture page.

The easiest way to solve this, if you're not using a custom shader and don't want to use a separate texture page per sprite, is probably to modify the uvs that you put into the vertex buffer. So, for every sprite on the page, make the [0, 1] u and v range correspond to its actual coordinates on the texture page. sprite_get_uvs gives you the info for that in the first 4 array elements.

You could also keep the uv coordinates in the vertex buffer in the [0, 1] range but then you'll need to pass the uv information for all sprites on the page via a uniform to a custom shader and calculate the offset in there.

Both work, though the first is by far the easiest since you don't need to write a custom shader for that.
 

Cash Munkey

Member
Thank you both, I'd been stuck on that for a good 2 or 3 days.

You could also keep the uv coordinates in the vertex buffer in the [0, 1] range but then you'll need to pass the uv information for all sprites on the page via a uniform to a custom shader and calculate the offset in there.
This is my first time working with sprites and graphics in GameMaker (or at all) so I was really hoping a custom shader was not the only option :).
 
Top