-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A way to erase pixels or overwrite alpha channel of pixels using the draw_line method() and a new blend mode #10255
Comments
I would precise that this use case concerns blending mode when rendering on texture, not on screen (which wouldn't make much sense because screen has no alpha) |
@Zylann we can still screen capture with alpha though The viewport has |
has anyone figured out a way to erase pixels using the draw_line method? |
@blurymind it's about adding a new blend mode I think, that will use alpha like a regular color, to replace the alpha already in the target buffer. Maybe @reduz knows how to do it? |
@reduz is there a way to erase pixels or overwrite pixels using the draw_line method? |
@Tvs-Frank you can't write the background color to "erase" pixels if your background is not a solid color (or worse, animated) |
I was wondering, is there a way to overwrite pixels? If so, we could over write the pixels with 1 for alpha with pixels with 0 alpha. |
@blurymind you could overwrite alpha pixels as if they were a normal color component, I believe there are blending modes in OpenGL to do that, but Godot doesn't expose them. This is a precision I added at the beginning of the thread, no need to repost the entire code :) I think there is a workaround but it's impractical, you would need to do your own blending with a shader by drawing transparent pixels as a red color on a separate texture, and then blends your image + the red texture together with a shader that erases pixels that come in contact with red pixels, to render it on the final render target which you can then save... but an appropriate control on blending mode would be much more simpler. |
Can we please tag this as a feature request or should I create another
issue for a request?
…On 31 Aug 2017 10:42, "Marc" ***@***.***> wrote:
@blurymind <https://github.com/blurymind> you could overwrite alpha
pixels as if they were a normal color component, I believe there are
blending modes in OpenGL to do that, but Godot doesn't expose them. This is
a precision I added at the beginning of the thread, no need to repost the
entire code :)
I think there is a workaround but it's impractical, you would need to do
your own blending with a shader by drawing transparent pixels as a red
color on a separate texture, and then blends your image + the red texture
together with a shader that erases pixels that come in contact with red
pixels, to render it on the final render target which you can then save...
but an appropriate blending mode would be much more simpler.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#10255 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGMbVYssoQc0hQ7umU3SVdntrVf5ksvOks5sdoAYgaJpZM4O0ygy>
.
|
Sounds like a good feature request. If you can edit the original post for clarity based on the follow-up discussion, that would be great. |
@akien-mga Thank you :) @Zylann another approach could be to have VisualServer.get_default_clear_color() be a color that erases pixels whenever set_transparent_background is true? Not sure what design would be most elegant here |
A Color cannot hold such info beyond having an alpha of zero. What you mean is again a blend mode (say, instead of mixing alpha, OpenGL will replace alpha with a different calculation) |
@Zylann A new blending mode would be awesome to get. Is there anyone interested in implementing it? I updated the title and description in the first post again to reflect that |
@Zylann would we still be using gdscript and draw_line method though? Or are we writing a shader? |
You would still draw anything you want like the engine allows you to. I mentionned shaders just for the "replace alpha" part, but it's not really about coding the shader, mostly specifying a blending mode the Godot way so that OpenGL does what you need in the renderer. Like, blend mode "Add" adds color to the image. "Sub" subtracts it. "Mul" multiplies it. It sounds logical to have a way to say "Replace alpha" then, or something close to what OpenGL needs. This SO threads is a similar problem to yours https://stackoverflow.com/questions/4074955/blending-a-texture-to-erase-alpha-values-softly-with-opengl |
They mention this:
Which is pretty much one of the suggestions we came up with here.. Notably: That said, I would take the option of a new blending mode too. Either would solve it. The question now is which one is a lower hanging fruit and does it fit best with the current design? What would the most elegant gdscript method be to set the masking color that erases pixels? What part of the source code is in charge of blending modes. I wish I knew as much c++ as I do python 🖌 |
I think the best way to do this would be:
|
@blurymind @reduz why not exposing the blend options? They exactly do what an app involving painting would need, and work faster than painting on the CPU and uploading the image every frame (also would miss all features the renderer let us draw). Also maintaining a secondary texture as mask would work, but you would need to redraw on it the same things that you draw on the main texture, when not using the eraser, in order to refill alpha to 1. And when it comes to save as image another rendering would occur to flatten those two textures into one. It would maybe work, but in an impractical way. |
@Zylann there is not much of a blend option to expose, GPU blending is very very limited, not near as complex as what something like Photoshop can do. He can also do this using GPU by drawing to another viewport and use it to blend.. |
Are you sure it's not supported? The SO thread mentionned this: |
@Zylann Exposing higher level blending options will not happen, because Godot tweaks the shader and changes the blend function according to what it's doing internally. In Unity you can do this, but you have to write your own shader passes for forward base, forward add, deferred, shadow, etc. That's not the idea in Godot, as It's meant to be more user friendly. That said, given this is 2D only, adding color replace and alpha replace models should be possible to the list of 2D blend modes. |
@reduz you're right, having a color replace and alpha replace models would be only useful for 2d drawing anyway. I would be very thankful if somebody looks into it and will help in any way possible with testing/examples :) A drawing app is not the only use case for this I can think of either. There are many interesting things that can be done. Cool editor addons can come out of it Even a simple pixel editing app addon could help rapid prototyping without leaving the editor. A dirty mockup used to design gameplay can be made by the designer and later used by an artist for sprite dimensions |
While thinking about implementing GPU-based terrain painting and sculpting, I figured out I needed alpha override blend modes (among other things). Indeed, the case is similar to general texture painting, while in this case the texture is used as a "data" rather than forcibly something to draw as is. What I would need would basically treat the alpha channel like any other channel (R, G, B), which gives the ability to paint on full splatmaps or various other maps that use 4 channels at once. That use case needs a 2D viewport though. Edit: I realized one problem with this, though... if those blend modes are available in 2D only, but those textures are then used in 3D, that means it could create a constant reimport loop due to the fact VisualServer auto-reimport color space of such textures when used for 3D :x |
I second the option to add a blend mode which simply says "replace" or simply "off". Basically just turn off blending when rendering with that shader. The alpha (along with the RGB value) will just be written into the frame buffer as is without blending it with the current value. |
I'm running into this issue as well when working on my texture painter. There seems to be no way to decreate alpha by drawing something, aka erasing. So if the alpha of a pixel is 1, there's no way to get it back down to 0. The painting shader is 2D, so a "alpha replace" 2D blend mode would be perfect and solve all my issues. |
I added this to master a week or so ago, check the render_modes, there
should be a blend_disabled there. If you use SCREEN_TEXTURE you can read
the current pixel value, do your own modifications, and write back whatever
value you want
On Tue, 22 May 2018 at 1:58 am, Bauxitedev ***@***.***> wrote:
I'm running into this issue as well when working on my texture painter
<https://github.com/Bauxitedev/godot-texture-painter>. There seems to be
no way to decreate alpha by drawing something, aka erasing. So if the alpha
of a pixel is 1, there's no way to get it back down to 0. The painting
shader is 2D, so a "alpha replace" 2D blend mode would be perfect and solve
all my issues.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#10255 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AB2vacvhG9_Lo4fKDJX0gxMzQWybms5Iks5t0uQ9gaJpZM4O0ygy>
.
|
Oh look, my PR is even referenced up above :) #18462 :) Couldn't see that on my poor mobile phone |
@BastiaanOlij can you share a simple code snippet demonstrating how this could be applied on a draw operation such as draw_line for example I kind of already posted a minimal example where it doesnt work because of the feature missing. :) I wanna test it out in the weekend and was wondering what to alter in my little example to make it erase pixels |
@blurymind check out the shaders in my terrain editor: Keep in mind, you need a fresh master build for this, it was only added a week or so ago so this is not in any of the official builds and won't be till 3.1 comes out. (and also keep in mind that if you do use SCREEN_TEXTURE, it creates a copy of your viewport texture for the first shader that uses it, so you can't do any overlapping logic) |
@BastiaanOlij so it can only be done via a shader? Is there no way to use a simple draw() method? |
@blurymind thing is, when you're using viewports you're dealing with a texture that lives in GPU memory (whatever the correct term for that is:)). Shaders are the most effective way to write into that but I do see that in the use case you sketch it feels like overkill :) However you don't have simple direct access to it. I guess we could add some sort of interface that allows you to call glTexSubImage2D to overwrite a small part of a texture with a subimage. |
In my usecase, the main problem was that we cant use any of the draw methods to erase pixels - which is required if one is to create a pixel editing tool with a simple eraser brush. The original idea for the addon was to enable editing pixel art inside godot without leaving it- just the ability to draw lines and erase them with a brush. We got the first part down. So in order to be able to also delete pixels, I have to now completely abandon the draw_line method - which is really what is expected to be used in the api for such a thing. I was hoping that one would be able to simply set the color of a line to a specific value - with any alpha value - and that alpha value should be able to overwrite any pixels that the line is drawn ontop of. I think that is what was suggested as another blending mode - surely there is some complexity to achieve it - exposing that functionality to draw methods would make them much more powerful imo. Without it they feel kind of limited to only be able to draw new lines, erase specific lines, or erase the entire canvas. We cant directly erase pixels by drawing lines ontop of them at all |
You can if the viewport in which you draw has a render-target. Any draw method will work, with the appropriate material or shader, nothing complex. This is the actual solution to being able to erase pixels, that's how I prototyped a drawing tool :) |
I managed to delete drawn pixels following @Zylann suggestion. I have the next Node structure (Control Node --> Viewport, Sprite) The viewport has this properties:
The board node is a Sprite with a CanvasItemMaterial on the Material property: On the CanvasItemMaterial the Blend Mode is set to add: Then I can use the method draw_line with an HEX ARGB color to erase previously drawn pixels. I use next color to delete drawn pixels:
|
Can you share your example project?
…On Sun, Mar 10, 2019, 11:12 PM AlvaroAV ***@***.***> wrote:
I managed to delete drawn pixels following @Zylann
<https://github.com/Zylann> suggestion.
I have the next Node structure (Control Node --> Viewport, Sprite)
[image: image]
<https://user-images.githubusercontent.com/5870043/54092784-9a06cf80-4390-11e9-8ed5-2ca50a0e8cc7.png>
The *viewport* has this properties:
- Transparent BG = True
- Clear Mode = Next Frame
The *board* node is a Sprite with a *CanvasItemMaterial* on the Material
property:
[image: image]
<https://user-images.githubusercontent.com/5870043/54092840-7001dd00-4391-11e9-9a6b-041772880b3a.png>
[image: image]
<https://user-images.githubusercontent.com/5870043/54092799-cfabb880-4390-11e9-927e-2d9947e1ffc5.png>
The Blend Mode set to *add* on the CanvasItemMaterial
Then I can use the method draw_line with an HEX ARGB color to erase
previously drawn pixels.
I use next color to delete drawn pixels:
Color("#ff000000")
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#10255 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AGMbVS9xDpQSnLGPAT8t0II3Igf0C6XZks5vVZF3gaJpZM4O0ygy>
.
|
@blurymind I'll try to upload an example project with this working on Godot 3.1 I'm quite busy until weekend, I'll let you know when it's ready |
Any update on this? I've tried @AlvaroAV method but having the texture in add blend mode is problematic if I intend to have multiple textures stacked, need them on normal mode to be able to paint them properly. |
I also managed to clear pixels using what is suggested above: Using a The drawing Very simple demo project: |
Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine. The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker. If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance! |
Eraser: CanvasItemMaterial.BLEND_MODE_SUB |
Please read above, this has been closed for over 3 years, open a proposal if one doesn't exist if you're interested in this feature, but this is long closed and doesn't need resurrection |
Ho that's great... then y just have to wait 3 more years until someone else mentions this again ! |
Open a proposal if you want to see this added, or wait, it's up to you: |
its Canvas Material LIGHT MODE
----------------//----------//--------------- |
I am currently trying to create a tiny pixelart tool for godot, but it's not possible to use the draw_line() method for erasing pixels. There seems to be no way in replacing the alpha value of a pixel with another alpha value at the moment - in the way you can draw with another color on top of old lines.
As @Zylann said
Here is an example code for drawing freehand lines:
color = Color(VisualServer.get_default_clear_color())
Will fail to erase the yellow pixels in the example.
Instead it simply writes the background color and you get this ugly grey color when you export the image with viewport.get_screen_capture():
The ideal solution for me personally is if I could set the color value to (0,0,0,0) and have that act as an eraser.
If we could have Godot actually have VisualServer.get_default_clear_color() be a color that erases pixels whenever set_transparent_background is true- that would make more sense too.
Or perhaps the best approach to this is to have a new blending mode that supports it.
I am assuming that something has to be done to the way godot's draw_line method works when writing to a texture. Any solution to this is very much welcome.
Making it possible will allow people to implement a freehand eraser tool and possibly other very useful things using the draw_line method
The text was updated successfully, but these errors were encountered: