How to mask/clipping a sprite?

This is the plan. An atlas will have multiple layers where the individual images will be packed into the same position in each layer. This will make it possible to create lighting and other cool effects without much effort.

2 Likes

Just remembered that tilemaps are still an option, because you can guarantee the position of individual cells so you can put a mask texture in one cell and other images in other cells and then use UV trickery to select multiple textures to combine and clip the alpha of. Itā€™s really clunky but may work for you without needing a render target / multiple draw calls until multi texture support is added. Iā€™ve made an example on how to do this but not sure where it is right now.

If you always put your masks in specific spots then your shader can know which mask to select for whatever animation you want clipped.

Another option is to edit the image data manually to make a new texture which clips the sprite. This can be done with editing buffers or a NE. It would also be cumbersome but might work for your needs.

1 Like

Thanks. I give up. looks like there is no good use of shaders with Defold rightnow.

Iā€™m dropping my test project here. Maybe someone want to take a look.
It is based on Britzlā€™s Simple 2D Lights example.
There are two different approchs: one with using single quad with render targets and one with just using quads and materials. They cause x2 performance drop on actual mobile device and I donā€™t know how to improve it anymore. So Iā€™m not planning to use them.

sprite-mask-test.zip (222.4 KB)

1 Like

Something like this perhaps?

Or render a sprite to the stencil buffer, but I guess this has been suggested and discarded already.

4 Likes

@jhonny.goransson Could you please explain little more? It is impossible for me to understand that what is special here without looking the code. Are you using quad with separate render targets? Are you using shader to discard alpha or using alpha mask png? Did you test them with a lots of sprites or models? Is it working on old devices like iPad3 and how is the performance?

I did try stencil buffer and it didnā€™t end well for me: How to mask/clipping a sprite?

Alpha version scene setup:

  • One or more ā€˜maskingā€™ sprites that just draws black and white textures to the backbuffer
  • One or more ā€˜should-be-maskedā€™ sprites that has their alpha mode set to ā€˜multiplyā€™

Stencil version setup:

  • One or more ā€˜maskingā€™ sprites that has a pass-through shader that basically just transforms, writes to backbuffer doesnā€™t matter
  • One or more ā€˜should-be-maskedā€™ sprites that will be affected by the stencil buffer
  • Render ā€˜maskingā€™ sprites to stencil buffer with color and depth writes off
  • Render ā€˜should-be-maskedā€™ sprites with stencil testing on and stencil writes off

Not sure what your requirements are in terms of what you want to do with the masking, but either setup above is very lightweight (no extra framebuffers etc).

HTML5: https://jhonnyking.github.io/my-public-defold-examples/sprite-masking/
Project: https://github.com/jhonnyking/my-public-defold-examples/tree/master/sprite-masking

2 Likes

Thank you @jhonny.goransson for the example and detail description. But this alpha scene with Multiply actually doesnā€™t mask the sprite or am I doing something wrong? It just multiply with black and looks like it is masked. Did I miss something here?

10

What Iā€™m trying to achieve is this:

alpha_frame

Is there a way to use a custom shape for stencil? Any tutorial that you can suggest?

Yeah Itā€™s a multiply so you need a black and white texture for the mask to work - itā€™s a bit limited yeah. Can you share that project with me and Iā€™ll see if I can modify it to work with the alpha mask. Other ideas:

Iā€™m thinking that perhaps it might work to write the mask to the depth buffer instead and use depth testing to reject pixels instead of discarding them. You canā€™t write stencil buffer values from a pixel shader unfortunately, but you should be able to write values from a texture to the depth buffer and then enable depth testing. You wonā€™t be able to get a smooth fade like with alpha blending, but if thatā€™s not what you need then it might work :slight_smile:

Otherwise, if you want to use the stencil buffer you need a custom shape to render it, which means you need to construct a 2D/3D shape in something like blenderā€¦

2 Likes

Actually I made some test with quad and render targets. But it is not performing very well on mobile devices and using the same render target for all sprites cause masks to mix. You can find it here . Basically Iā€™m rendering mask and sprite to the quadā€™s textures and applying alpha on quad shader.

Ah, I need a smooth one :slight_smile:

Hmm, I have no idea how to do this. Iā€™ll try to learn more about that. But is this going to be preferred way of doing this?

The custom mesh shape method may perform better on the device where the full screen render target has issues for you.

You basically want to generate a flat plane, move one of the sides down, select the 4 points, and then bevel the 4 points twice probably.

So then tada

But the edges will be harder than smooth sprite masks.

You can multi texture with meshes already though so you could use a rectangle in the card shape and supply it with textures for mask and clipping texture directly.

plane_mesh_clipper.zip (35.7 KB)

You probably donā€™t want to use the mesh I quickly made though. Try to make one in blender and make sure the UVs are how you want them.

3 Likes

Thank you @Pkeod , Iā€™m going to check it out as soon as possible.

1 Like

How do you measure this? And on what device?

With on-screen profiler. iPad 3 is my main low level testing device. If it has lag on this iPad, it will be worse on Android.

Would either of these work well with multiple sprites with their own masks? Think a game board with tiles, each with their own masking, to simplify times when multiple individual tiles have to simultaneously move the graphic outside the tile boundaries, but clip it within the tile boundary.

I hope we would have this feature for sprite and GUI box node