Is there a way to composite images in Godot?
Asked Answered
A

4

0

I'd like to make a paint program and am trying to figure out an efficient way to lay down brush strokes. Basically, I need to create one image to be the canvas, and then repeatedly draw the brush head over it following the path the user modes the pen in.

I'm having trouble figuring out how to do this in Godot. In OpenGL it would be straight forward - create an offscreen buffer, and for each point of my brush stroke and draw a quad which bounds the brush head. Then when I'm done, the offscreen buffer will have the complete stroke. This would also let me do things like change the scale, rotation and opacity of the brush head along the path of the stroke. I could also not be restricted to just alpha blending by writing a custom shader to mix the brush with the background. I could also set a data type of the buffer.

I'm trying to find the equivalent in Godot. SubViewport gives you an offscreen buffer, but you can't pick the data format and rather than drawing geometry to it immediately you need to create node, add it to the subviewport and then wait on the Godot engine to draw everything in a separate thread. Is there a way to composite more directly like the OpenGL example I gave, or do I have to try and work around this with SubViewports?

Adrianadriana answered 17/4, 2023 at 16:59 Comment(0)
O
0

You can also use image class and blit I guess but I have no experience with that personally. I know some have done it. Not sure how optimal it was.

Also while constantly creating new objects is not optimal you can have a canvasitem node be ready and waiting and just draw on it with couple of options for how to update it, clear or no clear.

Obaza answered 17/4, 2023 at 18:16 Comment(0)
S
0

You can draw into any CanvasItem derived node using basic drawing functions. Check the class reference for the list of function. As for getting the image, you'll have to use Viewports, it's the only functionality in Godot that can work as an offscreen framebuffer afaik.

Sabatier answered 17/4, 2023 at 18:22 Comment(0)
A
0

Obaza Bliting with the image class is not very helpful. You cannot scale or rotate the image you are overlaying, nor use custom shaders.

Adrianadriana answered 17/4, 2023 at 18:26 Comment(0)
S
0

Not sure what you're really after but here are two "strokes" drawn on CanvasItem using shader powered CanvasItem::draw_rect()

extends CanvasItem

func _draw():
	for i in range(50):
		draw_set_transform(Vector2(300,300), i * .05, Vector2(1.0, 1.0))
		draw_rect(Rect2(50, -50, 100, 100), Color(0.0, 0.0, 0.0, .7))
	
	for i in range(50):
		draw_set_transform(Vector2(500,300), 1.5+ i * .05, Vector2(1.0, 1.0))
		draw_rect(Rect2(150, -50, 70, 70), Color(1.0, 0.0, 0.0, .2))
shader_type canvas_item;
render_mode blend_mix;

void fragment(){
	COLOR.a = smoothstep(1.0, .1,  2.0 * length(UV-vec2(.5))) * COLOR.a;
}
Sabatier answered 17/4, 2023 at 19:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.