Topic was automatically imported from the old Question2Answer platform.
Asked By
sleepprogger
Old Version
Published before Godot 3 was released.
I am trying to mask a sprite with a dynamic mask updated from code.
This should be possible, or am i wrong ?
I know i can do the masking part via shader, but how do i manipulate (draw/remove circles, rectangles and polygons) the mask from code ?
Is there a way to create a texture from the current content of a CanvasItem ?
Alternatively if someone knows of a better way to reach my goal please share.
Thanks a bunch.
Do you want to make a Sprite or a Texture Button with a dynamic mask? because if I’m not mistaken a Sprite got no mask, only a picture which it displays
rustyStriker | 2016-10-23 14:54
I want to mask a sprite. This works via Shader/Light2D. But my problem is to generate dynamic masks at runtime.
Thanks, i found that post (after submitting this question tho).
Manipulating the mask with brush_transfer should work for some things but is really suboptimal.
All that is needed is some way to render a CanvasItem to a texture or some other way to use the draw_* methods to create images/textures.
One could manipulate the image data pixel by pixel ofc. but i guess that would be slow as hell.
If there is no other way would this be something for a feature request ?
While volzhs answer is valid for static brushes i needed a way to draw like one is able to in the canvasItem draw method (draw_circle, draw_rect, draw_polygon…)
So here is what i ended up with:
Disclaimer: While this is working i am sure there are more efficient solutions
Create the mask renderer
1. Create a Viewport and set Render Target to enabled 2. Add a Node2D (or any CanvasItem) as child and use the _draw method to draw your mask. Paint everything which should be visible with white.
Use the mask
In GDScript use my_viewport.get_render_target_texture() to get your texture.
If you want to only show masked areas just plug that texture into a LightMask2D (See link posted by volzhs). In this case you are done and can stop reading.
If you want the reverse case (hide everything masked) you need to write a shader (at least that was the easiest way i could think of). Don’t fret, its easy.
Create a material and set the shader to new CanvasItemShaderGraph.
In the fragment shader wire it up like seen below:
In the shader we defined two parameter (Uniforms): One is the Texture we want to mask and the other our mask texture.
In GDScript you can provide them to the shader like:
Thats it.
This approach is using a 4 channel (r,g,b,a) image for our mask and only uses 1, tho.
If it is somehow possible to use only one chanel images that should improve efficiency.
Hi, can you post a demo with source, i really don’t understand how to use your code :(, thanks!!