How to mask/clipping a sprite?

There is some formula to get the UVs right clearly but I don’t know it. Some expert would have to say it. It would be extremely useful to know because this has many applications for gamedev with proper scaling.

Luckily we can crowd source these things so none of us are alone in this!

2 Likes

Shaders are always my hurts.

1 Like

To fix this particular shader, you only need to replace each int literal with a floating literal, i.e. 10 -> 10.0, and so on.

1 Like

Thank you, I know and I will. But actually that is not my point.

For whatever reason, Defold on windows seems to be extra forgiving when it comes to shaders. I don’t think you will have the same issues developing from Mac.

I had similar problems making my lighting demo from windows, and got around it by testing with HTML builds, which are more strict.

1 Like

I guess I couldn’t explain myself correctly. What I’m trying to achieve/meant is the same with GUI Clipping but for sprites.
I’m looking for a shader based solution for build-in sprite.

Something like this:


or

https://docs.unity3d.com/Manual/class-SpriteMask.html

  • Without using quads
  • Per sprite from an atlas(with multiple sprites in it)
  • Works with diffent OpenGL vesions, especially for mobile
  • Fast (minimum draw calls, batched (if possible))

shader

With GOs, I think the minimum is still something like 3 draw calls per clipped layers. One for the things you are clipping, one for drawing their masks, one for drawing the render target. Then you would need 2 predicates per layer too. You currently cannot do this without using a render target with GOs as far as I know. Multi texture support is still not in. I could make a simplified sample project closer to what you want sometime in the future.

Multi texturing isn’t in yet Defold roadmap H1-2019 - Q1 summary

I don’t know how it will work but hopefully it will make doing stuff like this easier. It needs to be able to really intelligent about UV space for textures in atlases to be useful for this if it’s just ability to apply multiple textures straight to a sprite it will barely be useful. Ideally we want to be able to apply multiple kinds of textures from atlases so we can do other cool things like complex lighting on sprites eventually too.

1 Like

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?