Questions on custom texture slices and pivot points

I have an existing sprite sheet that doesn’t fall neatly into a grid. I do have a binary atlas file that contains all the info I need to slice it, including pivot points and flipbook animation indices. The textures are also very trimmed / whitespace-friendly / ultra packed. It would also take a lot of time to make individual pngs out of them, or even re-place them individually in a grid mold to use as a tilesource. And to be honest, I don’t want to do extra work or change to another sprite workflow just for Defold.

a) Is there a way for me to use such an existing spritesheet? The best way for me is to be able to make a “custom sprite” where I can change the uv, texture dimension, and offset manually at runtime.

b) An alternative is to at least find a way to set a pivot point for an image cell in the atlas but I don’t suppose that’s possible currently. Would it be possible to programmatically add a pivot variable to each atlas image cell, at the beginning of the runtime, and then detect which cell is being in use every frame and add that vector to the render child .go manually?

I’d very much prefer the former. I’d still have to export individual pngs from the original spritesheet for the latter. There’s already a model and a material component. It’d be nice if I can programmatically create a rect model and set their vertex uvs manually. Is it possible?

I don’t think shader is an option, unless I can write a geometry shader to change vertex position, as each cell would have different sizes… but even if I did I’d also need my entire atlas data on the gpu anyway and that may not be feasible. I just want a way to pass a custom vertex position and uv on the cpu manually.

Currently, no, we have no support for packed atlases (or spritesheets).
We have packed atlases on our short term roadmap. Eta is not known at this point.

I do have a binary atlas file that contains all the info I need to slice it

Cna I ask which format this is? (So that we can take it into consideration when planning the upcoming feature)

I thought so… well, I’m glad it’s on the roadmap.

As for the atlas it’s actually in a custom format so you don’t have to worry about it. I made a custom atlas editor gui because most spritesheets in the internet did not fall neatly in a grid, so I needed a way to slice and pivot them myself. By now my workflow is completely centered around it even for my original works.

I feel like having a resizeable plane with editable vertices/uvs is a solid feature to have. It will help with parallax too, provided the textures are set to repeat. It’d be even better if you keep the current sprite workflow and create a new one that works for existing non-grid/packed spritesheets. It’s not too difficult to slice such an existing one as even I made one myself… though I myself don’t need that feature. All I need is an atlas format for an existing spritesheet png that I can interface to.

1 Like

You can create a completely custom atlas in runtime by using resource.create_atlas API reference (resource)

I don’t 100% understand your use case but with that function you can create a packed atlas based on your custom format.

Actually yes, that’s about what I was asking for. I’m sorry, should have searched the docs more for that one. It seems like a promising base to work with. I do require some confirmations, though:

  1. My sprite cells also have an offset(pivot) point as well as an image rect. The create_atlas document suggests I can set vertex points as well as uv points for each geometry, would this account for all such use cases where I have to offset the sprite by a variable amount each frame? Apparently, it looks like it can account for rotations too if what I’m seeing is correct.

  2. About the animation… the docs only specify a frame-start and frame-end. I noticed that it was one-png/cell-per-frame for all animation use-cases in the first tutorial. Unfortunately my animations may have repeating elements and/or index jumps. It’s not neatly sequential. Could Defold somehow account for this?

  1. It should be possible. The offset isn’t needed in this case. You specify the image vertices in local space in the range [-0.5, 0.5]. We’re using the fact that the sprite is centered at the sprite position.
    As for the uvs, you specify the corresponding UV coordinates yourself, in texture space [0.0, 1.0].

  2. It is true that we currently don’t have a better way to specify animation ranges.
    You should be able to do it by adding images to your atlas, in such a way so that the animation frames are sequential.
    Is shouldn’t affect the texture, just the meta data you create.

Note that this is a bit untested but I think it should work.

1 Like

Does it have to be [-0.5, 0.5] space? I’m not sure I encountered a use case yet but it might be possible to have an image that is offset a bit further. Also, it’d be best if I can programmatically add individual animation cells to an animation. I saw that what I wanted was possible in the editor, so it’d be nice if we can do that in code as well… (maybe I’ll touch the metadata?)

I’ll get to playing around with this soon… right now busy refractoring some other things. I’ll let you know if I encounter something new.

The range [-0.5, 0.5] is in the image’s local space. Not to be confused with an UV coordinate. If the image size is 64 texels, then 0.5*64 = 32 and so on.

If the a vertex of an atlas image is p0 = [-0.5, 0.5], then we calculate the final sprite vertex as so:

// The world transform of the sprite, including the scale
// i.e. the size of the current animation frame
world = calcWorld(sprite, image_size) 
p0 = Vector3(-0.5, 0.5, 0); // The vertices are relative to the center of the sprite
world_pos0 = world * p0;

This a little pseudo code, but the real code is not much more complex: source code

The UV’s however, of these vertices, are in texture space. (note that we differentiate between image and texture. E.g. one atlas texture is likely to contain many images)

I’m not sure I encountered a use case yet but it might be possible to have an image that is offset a bit further

You’d have to elaborate here.

You can ofc put whatever in your vertices and UVs.

In our standard way of doing it the range [-0.5, 0.5] maps the entire sprite.
To make a sprite larger, you should use scaling of the gameobject/component.

2 Likes

I managed to try it out. In the resource doc above the numbers were whole so I assumed it was something related to translating/offsetting an object’s (or each vertex’) worldspace. Apparently it internally translates it into a ratio, as you said… and does something with it. I knew it wasn’t about uv space (the uv works just fine), but apparently it’s not something I’m used to. I’m afraid I’m not familiar with texels and I’m not sure what’s going on myself, but I don’t think it does what I want it to.

So… I brought a 128 x 128 png to test out. For now, I made an atlas asset in the editor, and inserted that single test image. 0 margin, padding and extrusion; it results in a 128x128 texture which is the exact same dimension as my png. The setup is as follows:

local atlas_info = resource.get_atlas("/images/test.a.texturesetc")
local tex = tostring(atlas_info.texture);
local aparams = {
	texture = tex,
	animations = { ... },
    geometries = { ... }
};
resource.set_atlas("/images/test.a.texturesetc", aparams)	

This itself works. I just used the same atlas parameters as the api docs at first, so the vertex table was as follows:

vertices  = {
	 0, 0,
 	 0, 128,
	 128, 128,
	 128, 0
},

So this about does what I expected it to, having the same effect as having the pivot point in the bottom left corner. And it’s the same for having 1 or 0.5 in place of 128.

fl

But then I have the following vertex points and the results are as follows. It’s the same with 0.5, 1, or 128 and it’s at this point I realized it was a ratio system as you said:

vertices  = {
	-64, -64,	
	-64, 64,
	64, 64,
	64, -64
},

mb

I’m afraid I don’t understand at this point. The go position is right at the arrow point. The scale is twice the size and no matter what I do I can’t get the sprite to center in the arrow point.

I played around but long story short it’s probably not what I think it is. Just one more example to illustrate my point:

vertices  = {
	0, 40,	
	0, 128,
	128, 128,
	128, 0
},

mm

Even if I somehow messed up the coordinates…
I can’t think of any rendering I know that does this with 4 vertices.

I’m sorry I’m really not familiar with texels in terms of ‘image space’… or anything that can do this. But honestly I don’t think image size should matter for what I want to do. I just want to offset the vertices by a certain amount, like this:

vertices  = {
	dx, dy,	
	dx, 128 + dy,
	128 + dx, 128 + dy,
	128 + dx, dy
},

Where dx, dy is the offset either in pixel space or at least something else that I can calculate from pivot point to worldspace.