|
|
|
|
Reply From: |
sash-rc |
blend_rect()
uses alpha from source image (base_data
in your case).
In order to achieve your task (as you described) you can use:
blit_rect_mask()
which uses a mask image, which you can fill()
with (half) transparent color.
And faster options like
- mix two textures in fragment shader on screen
- overlay two CanvasItem nodes like TextureRect and control transparency of topmost one with
self_modulate
.
Thanks! Great tips!
Andrea | 2021-08-25 10:59
So, i tried your method, which makes totally sense, but i couldnt make it work (i think because i do not understand correctly how blend and blit works)
to summarize:
the current_data
is the “picture” that need to be updated regularly.
On this picture, i need to add base_data
, i need to blend it with a value called ratio=0.1
. The effect i look for is to slowly fade from current into base (each iteration the current picture get a little bit more similar to the base)
Therefore, i created a new empty picture and called ratio_data.fill(Color(1,1,1,ratio))
Now i tried with:
-
current_data.blit_rect_mask(base_data, ratio_data, rect, vec)
=> the value goes immediatly back to base_data
(no blending based on the ratio)
-
I swapped current data and ratio data current_data.blit_rect_mask(ratio_data, base_data, rect, vec)
=> every pixel of current jump to Color(1,1,1,ratio)
-
current_data.blend_rect_mask(base_data, ratio_data, rect, vec)
=> the value goes to Color(0,0,0,1) (no idea where this comes from)
-
again swapped ratio and base, same result as above, all pixels goes to Color(0,0,0,1)
-
I tried inverting the value of ratio toratio_data=fill(Color(1,1,1,1-ratio)
, as well as Color(ratio,ratio,ratio,ratio)
, but same results as above
Is there something i’m doing wrong?
I believe that the mask is used as a boolean, either one pixel is replaced, or it is not, depending if the alfa of the mask is 0 or >0.
Shaders and modulate are not of any use (i’m using the pixel in the image to store data, it’s not just visual).
I tried doing shader computation in the past but there are more issue than solution there.
Compute shaders - hot to get data back - Archive - Godot Forum
Andrea | 2021-08-30 12:07
I believe that the mask is used as a boolean
I just tested, and it appears you’re right: unexpectedly Godot’s implementation is a weird or there’s a bug: mask works in boolean mode.
However if you manually set alpha for one image you could achieve result with blend_rect
:
var img1 : Image = Image.new()
var img2 : Image = Image.new()
var size : Vector2 = Vector2(10, 10)
var r : Rect2 = Rect2(Vector2.ZERO, size)
func prepare_images():
img1.create(size.x, size.y, false, Image.FORMAT_RGBA8)
img2.create(size.x, size.y, false, Image.FORMAT_RGBA8)
img1.fill(Color.red)
img1.lock()
for x in range(size.x):
img1.set_pixel(x, x, Color.yellow)
img1.unlock()
img2.fill(Color.blue)
func blend_test(rate : float):
# -------- apply "mask"
img2.lock()
for x in range(size.x):
for y in range(size.y):
var cl : Color = img2.get_pixel(x, y)
cl.a = rate
img2.set_pixel(x, y, cl)
img2.unlock()
img1.blend_rect(img2, r, Vector2.ZERO)
img1.save_png("res://test.png")
func _ready() -> void:
prepare_images()
blend_test(0.3) # 0.0 .. 1.0
But please note this could be slow. But as alternative, you can render canvas items to viewport texture.
sash-rc | 2021-08-30 19:57
Yeah, I tried blend_rect
the second picture without mask by making it half transparent first, didn’t work (can’t remember exactly what the result was, I’ll let you know asap)
On my project i found a workaround: in my case 90% of the pixels are identical between the two images, so i don’t actually need to blend all of them.
I stored the coordinate of the different pixels in an array, and blended them only with a manual set_pixel()
.
When the blending brings back the pixels to be identical again, i remove them from the array.
It works but the efficiency is strictly depending on how much the two pictures are different
Andrea | 2021-08-30 21:42
The code I posted works for me.
sash-rc | 2021-08-30 22:34
you are right, it worked, i was using a value of ratio that was too small, and the 8bit value of the pixel Color was not precise enough for it.
now i got a new problem to solve
Andrea | 2021-08-31 16:50