paint: fix mask opacity handling
This commit is contained in:
@@ -219,19 +219,14 @@ void export_texture_run_layers(char *path, slot_layer_t_array_t *layers, char *o
|
||||
gpu_texture_t *mask = empty;
|
||||
slot_layer_t_array_t *l1masks = slot_layer_get_masks(l1, true);
|
||||
if (l1masks != NULL && !bake_material) {
|
||||
if (l1masks->length > 1) {
|
||||
layers_make_temp_mask_img();
|
||||
draw_begin(pipes_temp_mask_image, true, 0x00000000);
|
||||
draw_end();
|
||||
slot_layer_t *l1 = GC_ALLOC_INIT(slot_layer_t, {.texpaint = pipes_temp_mask_image});
|
||||
for (i32 i = 0; i < l1masks->length; ++i) {
|
||||
layers_merge_layer(l1, l1masks->buffer[i], false);
|
||||
}
|
||||
mask = pipes_temp_mask_image;
|
||||
}
|
||||
else {
|
||||
mask = l1masks->buffer[0]->texpaint;
|
||||
layers_make_temp_mask_img();
|
||||
draw_begin(pipes_temp_mask_image, true, 0xffffffff);
|
||||
draw_end();
|
||||
slot_layer_t *l1 = GC_ALLOC_INIT(slot_layer_t, {.texpaint = pipes_temp_mask_image});
|
||||
for (i32 i = 0; i < l1masks->length; ++i) {
|
||||
layers_merge_layer(l1, l1masks->buffer[i], false);
|
||||
}
|
||||
mask = pipes_temp_mask_image;
|
||||
}
|
||||
|
||||
if (l1->paint_base) {
|
||||
|
||||
@@ -480,7 +480,6 @@ void make_material_restore_paint_material();
|
||||
parse_node_preview_result_t *make_material_parse_node_preview_material(ui_node_t *node, ui_node_canvas_t *group, ui_node_t_array_t *parents);
|
||||
void make_material_parse_brush();
|
||||
char *make_material_blend_mode(node_shader_t *kong, i32 blending, char *cola, char *colb, char *opac);
|
||||
char *make_material_blend_mode_mask(node_shader_t *kong, i32 blending, char *cola, char *colb, char *opac);
|
||||
f32 make_material_get_displace_strength();
|
||||
void ui_viewnodes_init();
|
||||
void ui_viewnodes_on_node_remove(ui_node_t *n);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
|
||||
#include "global.h"
|
||||
|
||||
shader_context_t *make_material_default_scon = NULL;
|
||||
material_context_t *make_material_default_mcon = NULL;
|
||||
static shader_context_t *make_material_saved_scon = NULL;
|
||||
static material_context_t *make_material_saved_mcon = NULL;
|
||||
shader_context_t *make_material_default_scon = NULL;
|
||||
material_context_t *make_material_default_mcon = NULL;
|
||||
static shader_context_t *make_material_saved_scon = NULL;
|
||||
static material_context_t *make_material_saved_mcon = NULL;
|
||||
|
||||
bool make_material_get_mout() {
|
||||
for (i32 i = 0; i < g_context->material->canvas->nodes->length; ++i) {
|
||||
@@ -512,61 +512,6 @@ char *make_material_blend_mode(node_shader_t *kong, i32 blending, char *cola, ch
|
||||
}
|
||||
}
|
||||
|
||||
char *make_material_blend_mode_mask(node_shader_t *kong, i32 blending, char *cola, char *colb, char *opac) {
|
||||
if (blending == BLEND_TYPE_MIX) {
|
||||
return string("lerp(%s, %s, %s)", cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_DARKEN) {
|
||||
return string("lerp(%s, min(%s, %s), %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_MULTIPLY) {
|
||||
return string("lerp(%s, %s * %s, %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_BURN) {
|
||||
return string("lerp(%s, 1.0 - (1.0 - %s) / %s, %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_LIGHTEN) {
|
||||
return string("max(%s, %s * %s)", cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_SCREEN) {
|
||||
return string("(1.0 - ((1.0 - %s) + %s * (1.0 - %s)) * (1.0 - %s))", opac, opac, colb, cola);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_DODGE) {
|
||||
return string("lerp(%s, %s / (1.0 - %s), %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_ADD) {
|
||||
return string("lerp(%s, %s + %s, %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_OVERLAY) {
|
||||
// return "lerp(" + cola + ", " + cola + " < 0.5 ? 2.0 * " + cola + " * " + colb + " : 1.0 - 2.0 * (1.0 - " + cola + ") * (1.0 - " + colb + "), " + opac
|
||||
// + ")";
|
||||
char *res = string("%s_res", string_replace_all(cola, ".", "_"));
|
||||
node_shader_write_frag(kong, string("var %s: float;", res));
|
||||
node_shader_write_frag(kong, string("if (%s < 0.5) { %s = 2.0 * %s * %s; } else { %s = 1.0 - 2.0 * (1.0 - %s) * (1.0 - %s); }", cola, res, cola, colb,
|
||||
res, cola, colb));
|
||||
return string("lerp(%s, %s, %s)", cola, res, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_SOFT_LIGHT) {
|
||||
return string("((1.0 - %s) * %s + %s * ((1.0 - %s) * %s * %s + %s * (1.0 - (1.0 - %s) * (1.0 - %s))))", opac, cola, opac, cola, colb, cola, cola, colb,
|
||||
cola);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_LINEAR_LIGHT) {
|
||||
return string("(%s + %s * (2.0 * (%s - 0.5)))", cola, opac, colb);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_DIFFERENCE) {
|
||||
return string("lerp(%s, abs(%s - %s), %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_SUBTRACT) {
|
||||
return string("lerp(%s, %s - %s, %s)", cola, cola, colb, opac);
|
||||
}
|
||||
else if (blending == BLEND_TYPE_DIVIDE) {
|
||||
return string("(1.0 - %s) * %s + %s * %s / %s", opac, cola, opac, cola, colb);
|
||||
}
|
||||
else { // BlendHue, BlendSaturation, BlendColor, BlendValue
|
||||
return string("lerp(%s, %s, %s)", cola, colb, opac);
|
||||
}
|
||||
}
|
||||
|
||||
f32 make_material_get_displace_strength() {
|
||||
vec4_t sc = context_main_object()->base->transform->scale;
|
||||
return g_config->displace_strength * 0.1 * sc.x;
|
||||
|
||||
@@ -341,7 +341,7 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
|
||||
}
|
||||
if (has_visible) {
|
||||
char *texpaint_mask = string("texpaint_mask%s", i32_to_string(l->id));
|
||||
node_shader_write_frag(kong, string("var %s: float = 0.0;", texpaint_mask));
|
||||
node_shader_write_frag(kong, string("var %s: float = 1.0;", texpaint_mask));
|
||||
for (i32 i = 0; i < masks->length; ++i) {
|
||||
slot_layer_t *m = masks->buffer[i];
|
||||
if (!slot_layer_is_visible(m)) {
|
||||
@@ -352,10 +352,9 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
|
||||
node_shader_write_frag(kong, string("var texpaint_mask_sample%s: float = sample_lod(texpaint%s, sampler_linear, %s, 0.0).r;",
|
||||
i32_to_string(m->id), i32_to_string(m->id), tex_coord));
|
||||
|
||||
f32 opac = slot_layer_get_opacity(m);
|
||||
char *mask = make_material_blend_mode_mask(kong, m->blending, texpaint_mask, string("texpaint_mask_sample%s", i32_to_string(m->id)),
|
||||
string("float(%s)", f32_to_string(opac)));
|
||||
node_shader_write_frag(kong, string("%s = %s;", texpaint_mask, mask));
|
||||
f32 opac = slot_layer_get_opacity(m);
|
||||
node_shader_write_frag(kong, string("%s *= lerp(1.0, %s, float(%s));", texpaint_mask,
|
||||
string("texpaint_mask_sample%s", i32_to_string(m->id)), f32_to_string(opac)));
|
||||
node_shader_write_frag(kong, "}");
|
||||
}
|
||||
node_shader_write_frag(kong, string("texpaint_opac *= clamp(%s, 0.0, 1.0);", texpaint_mask));
|
||||
@@ -632,7 +631,7 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
|
||||
node_shader_write_frag(kong, string("var mask_view: float = sample_lod(texpaint%s, sampler_linear, tex_coord, 0.0).r;", i32_to_string(id)));
|
||||
}
|
||||
else {
|
||||
node_shader_write_frag(kong, "var mask_view: float = 0.0;");
|
||||
node_shader_write_frag(kong, "var mask_view: float = 1.0;");
|
||||
for (i32 i = 0; i < slot_layer_get_masks(g_context->layer, true)->length; ++i) {
|
||||
slot_layer_t *m = slot_layer_get_masks(g_context->layer, true)->buffer[i];
|
||||
if (!slot_layer_is_visible(m)) {
|
||||
@@ -640,10 +639,8 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
|
||||
}
|
||||
node_shader_write_frag(kong, string("var mask_sample%s: float = sample_lod(texpaint_view_mask%s, sampler_linear, tex_coord, 0.0).r;",
|
||||
i32_to_string(m->id), i32_to_string(m->id)));
|
||||
f32 opac = slot_layer_get_opacity(m);
|
||||
char *mask = make_material_blend_mode_mask(kong, m->blending, "mask_view", string("mask_sample%s", i32_to_string(m->id)),
|
||||
string("float(%s)", f32_to_string(opac)));
|
||||
node_shader_write_frag(kong, string("mask_view = %s;", mask));
|
||||
f32 opac = slot_layer_get_opacity(m);
|
||||
node_shader_write_frag(kong, string("mask_view *= lerp(1.0, mask_sample%s, float(%s));", i32_to_string(m->id), f32_to_string(opac)));
|
||||
}
|
||||
}
|
||||
node_shader_write_frag(kong, "output[1] = float4(mask_view, mask_view, mask_view, 1.0);");
|
||||
|
||||
+21
-15
@@ -99,7 +99,7 @@ slot_layer_t *slot_layer_create(char *ext, layer_slot_type_t type, slot_layer_t
|
||||
i32 id = (raw->id + 1);
|
||||
raw->name = string("Mask %d", id);
|
||||
char *format = "RGBA32"; // Full bits for undo support, R8 is used
|
||||
raw->blending = BLEND_TYPE_ADD;
|
||||
raw->blending = BLEND_TYPE_MIX;
|
||||
|
||||
{
|
||||
render_target_t *t = render_target_create();
|
||||
@@ -1696,7 +1696,18 @@ void layers_merge_layer(slot_layer_t *l0, slot_layer_t *l1, bool use_mask) {
|
||||
// for (let i: i32 = 1; i < l1masks.length - 1; ++i) {
|
||||
// merge_layer(l1masks[i + 1], l1masks[i]);
|
||||
// }
|
||||
mask = l1masks->buffer[0]->texpaint;
|
||||
layers_make_temp_mask_img();
|
||||
_gpu_begin(pipes_temp_mask_image, NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
|
||||
gpu_set_pipeline(pipes_merge_mask);
|
||||
gpu_set_texture(pipes_tex0_merge_mask, l1masks->buffer[0]->texpaint);
|
||||
gpu_set_texture(pipes_texa_merge_mask, empty);
|
||||
gpu_set_float(pipes_opac_merge_mask, l1masks->buffer[0]->mask_opacity);
|
||||
gpu_set_int(pipes_blending_merge_mask, BLEND_TYPE_MIX);
|
||||
gpu_set_vertex_buffer(const_data_screen_aligned_vb);
|
||||
gpu_set_index_buffer(const_data_screen_aligned_ib);
|
||||
gpu_draw();
|
||||
gpu_end();
|
||||
mask = pipes_temp_mask_image;
|
||||
}
|
||||
|
||||
if (slot_layer_is_mask(l1)) {
|
||||
@@ -1705,7 +1716,7 @@ void layers_merge_layer(slot_layer_t *l0, slot_layer_t *l1, bool use_mask) {
|
||||
gpu_set_texture(pipes_tex0_merge_mask, l1->texpaint);
|
||||
gpu_set_texture(pipes_texa_merge_mask, layers_temp_image);
|
||||
gpu_set_float(pipes_opac_merge_mask, slot_layer_get_opacity(l1));
|
||||
gpu_set_int(pipes_blending_merge_mask, l1->blending);
|
||||
gpu_set_int(pipes_blending_merge_mask, BLEND_TYPE_MIX);
|
||||
gpu_set_vertex_buffer(const_data_screen_aligned_vb);
|
||||
gpu_set_index_buffer(const_data_screen_aligned_ib);
|
||||
gpu_draw();
|
||||
@@ -1814,19 +1825,14 @@ slot_layer_t *layers_flatten(bool height_to_normal, slot_layer_t_array_t *layers
|
||||
gpu_texture_t *mask = empty;
|
||||
slot_layer_t_array_t *l1masks = slot_layer_get_masks(l1, true);
|
||||
if (l1masks != NULL) {
|
||||
if (l1masks->length > 1) {
|
||||
layers_make_temp_mask_img();
|
||||
draw_begin(pipes_temp_mask_image, GPU_CLEAR_COLOR, 0x00000000);
|
||||
draw_end();
|
||||
slot_layer_t *l1 = GC_ALLOC_INIT(slot_layer_t, {.texpaint = pipes_temp_mask_image});
|
||||
for (i32 i = 0; i < l1masks->length; ++i) {
|
||||
layers_merge_layer(l1, l1masks->buffer[i], false);
|
||||
}
|
||||
mask = pipes_temp_mask_image;
|
||||
}
|
||||
else {
|
||||
mask = l1masks->buffer[0]->texpaint;
|
||||
layers_make_temp_mask_img();
|
||||
draw_begin(pipes_temp_mask_image, GPU_CLEAR_COLOR, 0xffffffff);
|
||||
draw_end();
|
||||
slot_layer_t *l1 = GC_ALLOC_INIT(slot_layer_t, {.texpaint = pipes_temp_mask_image});
|
||||
for (i32 i = 0; i < l1masks->length; ++i) {
|
||||
layers_merge_layer(l1, l1masks->buffer[i], false);
|
||||
}
|
||||
mask = pipes_temp_mask_image;
|
||||
}
|
||||
|
||||
if (l1->paint_base) {
|
||||
|
||||
@@ -447,13 +447,10 @@ void tab_layers_draw_layer_slot_full(slot_layer_t *l, i32 i) {
|
||||
}
|
||||
|
||||
// Blending combo
|
||||
if (!slot_layer_is_group(l)) {
|
||||
if (!slot_layer_is_group(l) && !slot_layer_is_mask(l)) {
|
||||
ui->_x = uix + uiw * 0.60;
|
||||
ui->_y = uiy;
|
||||
ui->_w = uiw * 0.30;
|
||||
if (slot_layer_is_mask(l)) {
|
||||
ui->_y += center;
|
||||
}
|
||||
tab_layers_combo_blending(l, false);
|
||||
}
|
||||
|
||||
@@ -641,7 +638,7 @@ void tab_layers_draw_layer_context_menu_draw() {
|
||||
ui_menu_keep_open = true;
|
||||
}
|
||||
|
||||
if (!slot_layer_is_group(l)) {
|
||||
if (!slot_layer_is_group(l) && !slot_layer_is_mask(l)) {
|
||||
if (tab_layers_combo_blending(l, true)->changed) {
|
||||
ui_menu_keep_open = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user