Files
armorpaint/armorlab/sources/nodes/inpaint_node.ts
T

256 lines
8.2 KiB
TypeScript
Raw Normal View History

2024-03-14 23:58:24 +01:00
2024-10-26 15:17:05 +02:00
///include "../plugins/proc_texsynth/proc_texsynth.h"
2024-03-14 23:58:24 +01:00
type inpaint_node_t = {
base?: logic_node_t;
};
2025-03-10 20:38:53 +01:00
let inpaint_node_image: iron_gpu_texture_t = null;
let inpaint_node_mask: iron_gpu_texture_t = null;
let inpaint_node_result: iron_gpu_texture_t = null;
2024-03-14 23:58:24 +01:00
2025-03-10 20:38:53 +01:00
let inpaint_node_temp: iron_gpu_texture_t = null;
2024-08-31 17:24:01 +02:00
let inpaint_node_prompt: string = "";
let inpaint_node_strength: f32 = 0.5;
let inpaint_node_auto: bool = true;
2024-03-14 23:58:24 +01:00
2024-10-19 23:37:47 +02:00
function inpaint_node_create(raw: ui_node_t, args: f32_array_t): inpaint_node_t {
2024-03-14 23:58:24 +01:00
let n: inpaint_node_t = {};
2024-10-21 19:28:43 +02:00
n.base = logic_node_create(n);
2024-03-14 23:58:24 +01:00
n.base.get_as_image = inpaint_node_get_as_image;
n.base.get_cached_image = inpaint_node_get_cached_image;
inpaint_node_init();
return n;
}
function inpaint_node_init() {
if (inpaint_node_image == null) {
2025-03-10 20:38:53 +01:00
inpaint_node_image = gpu_create_render_target(config_get_texture_res_x(), config_get_texture_res_y());
2024-03-14 23:58:24 +01:00
}
if (inpaint_node_mask == null) {
2025-03-10 20:38:53 +01:00
inpaint_node_mask = gpu_create_render_target(config_get_texture_res_x(), config_get_texture_res_y(), tex_format_t.R8);
2025-03-11 19:49:42 +01:00
sys_notify_on_next_frame(function () {
2025-04-24 22:19:44 +02:00
_gpu_begin(inpaint_node_mask, null, clear_flag_t.COLOR, color_from_floats(1.0, 1.0, 1.0, 1.0));
2025-03-10 20:38:53 +01:00
_gpu_end();
2024-03-14 23:58:24 +01:00
});
}
if (inpaint_node_temp == null) {
2025-03-10 20:38:53 +01:00
inpaint_node_temp = gpu_create_render_target(512, 512);
2024-03-14 23:58:24 +01:00
}
if (inpaint_node_result == null) {
2025-03-10 20:38:53 +01:00
inpaint_node_result = gpu_create_render_target(config_get_texture_res_x(), config_get_texture_res_y());
2024-03-14 23:58:24 +01:00
}
}
2024-10-21 19:28:43 +02:00
function inpaint_node_button(node_id: i32) {
let node: ui_node_t = ui_get_node(ui_nodes_get_canvas(true).nodes, node_id);
2024-10-23 14:00:19 +02:00
inpaint_node_auto = node.buttons[0].default_value[0] == 0 ? false : true;
2024-03-14 23:58:24 +01:00
if (!inpaint_node_auto) {
2024-04-24 12:14:47 +02:00
2024-09-03 15:52:05 +02:00
let inpaint_node_strength_handle: ui_handle_t = ui_handle(__ID__);
2024-04-24 12:14:47 +02:00
if (inpaint_node_strength_handle.init) {
inpaint_node_strength_handle.value = inpaint_node_strength;
}
2024-09-03 15:52:05 +02:00
inpaint_node_strength = ui_slider(inpaint_node_strength_handle, tr("strength"), 0, 1, true);
inpaint_node_prompt = ui_text_area(ui_handle(__ID__), ui_align_t.LEFT, true, tr("prompt"), true);
2024-03-20 16:13:54 +01:00
node.buttons[1].height = 1 + string_split(inpaint_node_prompt, "\n").length;
}
else {
node.buttons[1].height = 0;
2024-03-14 23:58:24 +01:00
}
}
2025-03-10 20:38:53 +01:00
function inpaint_node_get_as_image(self: inpaint_node_t, from: i32): iron_gpu_texture_t {
let source: iron_gpu_texture_t = logic_node_input_get_as_image(self.base.inputs[0]);
2024-04-02 15:45:49 +02:00
console_progress(tr("Processing") + " - " + tr("Inpaint"));
2024-03-14 23:58:24 +01:00
2025-03-10 20:26:45 +01:00
draw_begin(inpaint_node_image);
2025-03-02 19:44:26 +01:00
draw_scaled_image(source, 0, 0, config_get_texture_res_x(), config_get_texture_res_y());
2025-03-10 20:26:45 +01:00
draw_end();
2024-03-14 23:58:24 +01:00
2024-08-31 17:24:01 +02:00
if (inpaint_node_auto) {
return inpaint_node_texsynth_inpaint(inpaint_node_image, false, inpaint_node_mask);
}
else {
return inpaint_node_sd_inpaint(inpaint_node_image, inpaint_node_mask);
}
2024-03-14 23:58:24 +01:00
}
2025-03-10 20:38:53 +01:00
function inpaint_node_get_cached_image(self: inpaint_node_t): iron_gpu_texture_t {
2025-03-11 19:49:42 +01:00
sys_notify_on_next_frame(function (self: inpaint_node_t) {
2025-03-10 20:38:53 +01:00
let source: iron_gpu_texture_t = logic_node_input_get_as_image(self.base.inputs[0]);
_gpu_begin(inpaint_node_image);
2025-04-24 22:19:44 +02:00
gpu_set_pipeline(pipes_inpaint_preview);
2025-03-18 12:14:21 +01:00
gpu_set_texture(pipes_tex0_inpaint_preview, source);
gpu_set_texture(pipes_texa_inpaint_preview, inpaint_node_mask);
2025-03-10 20:38:53 +01:00
gpu_set_vertex_buffer(const_data_screen_aligned_vb);
gpu_set_index_buffer(const_data_screen_aligned_ib);
2025-04-24 22:19:44 +02:00
gpu_draw();
2025-03-10 20:38:53 +01:00
_gpu_end();
2024-04-07 09:52:45 +02:00
}, self);
2024-03-14 23:58:24 +01:00
return inpaint_node_image;
}
2025-03-10 20:38:53 +01:00
function inpaint_node_get_target(): iron_gpu_texture_t {
2024-03-14 23:58:24 +01:00
return inpaint_node_mask;
}
2025-03-10 20:38:53 +01:00
function inpaint_node_texsynth_inpaint(image: iron_gpu_texture_t, tiling: bool, mask: iron_gpu_texture_t): iron_gpu_texture_t {
2024-08-31 17:24:01 +02:00
let w: i32 = config_get_texture_res_x();
let h: i32 = config_get_texture_res_y();
2024-03-14 23:58:24 +01:00
2025-03-10 20:38:53 +01:00
let bytes_img: buffer_t = gpu_get_texture_pixels(image);
let bytes_mask: buffer_t = mask != null ? gpu_get_texture_pixels(mask) : buffer_create(w * h);
2024-08-31 17:24:01 +02:00
let bytes_out: buffer_t = buffer_create(w * h * 4);
2024-10-26 15:17:05 +02:00
texsynth_inpaint(w, h, bytes_out.buffer, bytes_img.buffer, bytes_mask.buffer, tiling);
2024-03-14 23:58:24 +01:00
2025-03-10 20:38:53 +01:00
inpaint_node_result = gpu_create_texture_from_bytes(bytes_out, w, h);
2024-04-02 15:45:49 +02:00
return inpaint_node_result;
2024-03-14 23:58:24 +01:00
}
2025-03-10 20:38:53 +01:00
function inpaint_node_sd_inpaint(image: iron_gpu_texture_t, mask: iron_gpu_texture_t): iron_gpu_texture_t {
2024-03-14 23:58:24 +01:00
inpaint_node_init();
2025-03-10 20:38:53 +01:00
let bytes_img: buffer_t = gpu_get_texture_pixels(mask);
2024-10-23 14:00:19 +02:00
let u8_img: buffer_t = bytes_img;
2024-08-31 17:24:01 +02:00
let f32mask: f32_array_t = f32_array_create(4 * 64 * 64);
2024-03-14 23:58:24 +01:00
2024-03-20 16:13:54 +01:00
let vae_encoder_blob: buffer_t = data_get_blob("models/sd_vae_encoder.quant.onnx");
2024-03-21 21:06:41 +01:00
// for (let x: i32 = 0; x < math_floor(image.width / 512); ++x) {
// for (let y: i32 = 0; y < math_floor(image.height / 512); ++y) {
2024-08-31 17:24:01 +02:00
let x: i32 = 0;
let y: i32 = 0;
2024-03-14 23:58:24 +01:00
2024-03-21 21:06:41 +01:00
for (let xx: i32 = 0; xx < 64; ++xx) {
for (let yy: i32 = 0; yy < 64; ++yy) {
2024-03-14 23:58:24 +01:00
// let step = math_floor(512 / 64);
// let j = (yy * step * mask.width + xx * step) + (y * 512 * mask.width + x * 512);
2024-08-31 17:24:01 +02:00
let step: i32 = math_floor(mask.width / 64);
let j: i32 = (yy * step * mask.width + xx * step);
2024-10-23 14:00:19 +02:00
let f: f32 = u8_img[j] / 255.0;
2024-08-31 17:24:01 +02:00
let i: i32 = yy * 64 + xx;
2024-03-14 23:58:24 +01:00
f32mask[i ] = f;
f32mask[i + 64 * 64 ] = f;
f32mask[i + 64 * 64 * 2] = f;
f32mask[i + 64 * 64 * 3] = f;
}
}
2025-03-10 20:26:45 +01:00
draw_begin(inpaint_node_temp);
2024-03-14 23:58:24 +01:00
// g2_drawImage(image, -x * 512, -y * 512);
2025-03-02 19:44:26 +01:00
draw_scaled_image(image, 0, 0, 512, 512);
2025-03-10 20:26:45 +01:00
draw_end();
2024-03-14 23:58:24 +01:00
2025-03-10 20:38:53 +01:00
bytes_img = gpu_get_texture_pixels(inpaint_node_temp);
2024-08-31 17:24:01 +02:00
let u8a: buffer_t = bytes_img;
let f32a: f32_array_t = f32_array_create(3 * 512 * 512);
2024-03-21 21:06:41 +01:00
for (let i: i32 = 0; i < (512 * 512); ++i) {
2024-03-14 23:58:24 +01:00
f32a[i ] = (u8a[i * 4 ] / 255.0) * 2.0 - 1.0;
f32a[i + 512 * 512 ] = (u8a[i * 4 + 1] / 255.0) * 2.0 - 1.0;
f32a[i + 512 * 512 * 2] = (u8a[i * 4 + 2] / 255.0) * 2.0 - 1.0;
}
2024-10-21 19:28:43 +02:00
let tensors: buffer_t[] = [buffer_create_from_raw(f32a.buffer, f32a.length * 4)];
2024-10-19 23:37:47 +02:00
let input_shape: i32_array_t[] = [];
let input_shape0: i32[] = [1, 3, 512, 512];
array_push(input_shape, input_shape0);
let output_shape: i32[] = [1, 4, 64, 64];
let latents_buf: buffer_t = iron_ml_inference(vae_encoder_blob, tensors, input_shape, output_shape, config_raw.gpu_inference);
2024-04-15 21:28:01 +02:00
let latents: f32_array_t = f32_array_create_from_buffer(latents_buf);
2024-03-21 21:06:41 +01:00
for (let i: i32 = 0; i < latents.length; ++i) {
2024-03-14 23:58:24 +01:00
latents[i] = 0.18215 * latents[i];
}
2024-10-19 23:37:47 +02:00
let latents_orig: f32_array_t = array_slice(latents, 0, latents.length);
2024-03-14 23:58:24 +01:00
2024-08-31 17:24:01 +02:00
let noise: f32_array_t = f32_array_create(latents.length);
2024-04-15 21:28:01 +02:00
for (let i: i32 = 0; i < noise.length; ++i) {
noise[i] = math_cos(2.0 * 3.14 * random_node_get_float()) * math_sqrt(-2.0 * math_log(random_node_get_float()));
}
2024-03-14 23:58:24 +01:00
2024-08-31 17:24:01 +02:00
let num_inference_steps: i32 = 50;
let init_timestep: i32 = math_floor(num_inference_steps * inpaint_node_strength);
let timestep: i32 = text_to_photo_node_timesteps[num_inference_steps - init_timestep];
let alphas_cumprod: f32[] = text_to_photo_node_alphas_cumprod;
let sqrt_alpha_prod: f32 = math_pow(alphas_cumprod[timestep], 0.5);
let sqrt_one_minus_alpha_prod: f32 = math_pow(1.0 - alphas_cumprod[timestep], 0.5);
2024-03-21 21:06:41 +01:00
for (let i: i32 = 0; i < latents.length; ++i) {
2024-03-14 23:58:24 +01:00
latents[i] = sqrt_alpha_prod * latents[i] + sqrt_one_minus_alpha_prod * noise[i];
}
2024-08-31 17:24:01 +02:00
let start: i32 = num_inference_steps - init_timestep;
2024-03-14 23:58:24 +01:00
2024-04-02 15:45:49 +02:00
inpaint_node_result = text_to_photo_node_stable_diffusion(inpaint_node_prompt, latents, start, true, f32mask, latents_orig);
return inpaint_node_result;
2024-03-14 23:58:24 +01:00
// }
// }
}
2024-09-03 15:52:05 +02:00
let inpaint_node_def: ui_node_t = {
2024-03-14 23:58:24 +01:00
id: 0,
name: _tr("Inpaint"),
type: "inpaint_node",
x: 0,
y: 0,
color: 0xff4982a0,
inputs: [
{
id: 0,
node_id: 0,
name: _tr("Color"),
type: "RGBA",
color: 0xffc7c729,
2024-04-10 19:39:17 +02:00
default_value: f32_array_create_xyzw(1.0, 1.0, 1.0, 1.0),
min: 0.0,
max: 1.0,
precision: 100,
display: 0
2024-03-14 23:58:24 +01:00
}
],
outputs: [
{
id: 0,
node_id: 0,
name: _tr("Color"),
type: "RGBA",
color: 0xffc7c729,
2024-04-10 19:39:17 +02:00
default_value: f32_array_create_xyzw(0.0, 0.0, 0.0, 1.0),
min: 0.0,
max: 1.0,
precision: 100,
display: 0
2024-03-14 23:58:24 +01:00
}
],
buttons: [
{
name: _tr("auto"),
type: "BOOL",
2024-04-10 19:39:17 +02:00
output: 0,
2024-04-24 12:14:47 +02:00
default_value: f32_array_create_x(1),
2024-04-10 19:39:17 +02:00
data: null,
min: 0.0,
max: 1.0,
precision: 100,
height: 0
2024-03-14 23:58:24 +01:00
},
{
2024-10-21 19:28:43 +02:00
name: "inpaint_node_button",
2024-03-14 23:58:24 +01:00
type: "CUSTOM",
2024-04-10 19:39:17 +02:00
output: -1,
2024-10-21 19:28:43 +02:00
default_value: f32_array_create_x(0),
2024-04-10 19:39:17 +02:00
data: null,
min: 0.0,
max: 1.0,
precision: 100,
2024-03-14 23:58:24 +01:00
height: 0
}
2024-04-10 19:39:17 +02:00
],
width: 0
2024-03-14 23:58:24 +01:00
};