paint: sculpt layer fixes

This commit is contained in:
luboslenco
2026-05-28 17:55:23 +02:00
parent 1d9e1111c6
commit 5d93d4c86a
9 changed files with 176 additions and 40 deletions
+2 -2
View File
@@ -602,8 +602,8 @@ void render_path_raytrace_init();
void render_path_raytrace_raytrace_init(char *shader_name, bool build);
void render_path_raytrace_draw(bool use_live_layer);
node_shader_context_t *sculpt_make_sculpt_run(material_t *data, material_context_t *matcon);
void sculpt_make_mesh_run(node_shader_t *kong, slot_layer_t *l);
void sculpt_import_mesh_pack_to_texture(mesh_data_t *mesh, slot_layer_t *l);
void sculpt_make_mesh_run(node_shader_t *kong, slot_layer_t_array_t *sculpt_layers, i32_array_t *sculpt_indices);
void sculpt_import_mesh_pack_to_texture(mesh_data_t *mesh, gpu_texture_t *target);
void sculpt_init_sculpt_texture(slot_layer_t *l, mesh_data_t *md);
void sculpt_init();
void sculpt_layers_create_sculpt_layer();
+1
View File
@@ -110,6 +110,7 @@ void import_mesh_finish_import(void *_) {
render_path_raytrace_ready = false;
g_context->paint_body = NULL;
tab_meshes_reset_preview_map();
base_update_workflow();
if (import_mesh_needs_unwrap) {
import_mesh_needs_unwrap = false;
+13
View File
@@ -60,6 +60,19 @@ node_shader_context_t *make_depth_run(material_t *data, material_context_t *matc
node_shader_write_vert(kong, "output.pos = constants.VP * float4(output.wposition.xyz, 1.0);");
// {
// slot_layer_t_array_t *sculpt_layers = any_array_create_from_raw((void *[]){}, 0);
// i32_array_t *sculpt_indices = i32_array_create(0);
// for (i32 i = 0; i < project_layers->length; ++i) {
// slot_layer_t *l = project_layers->buffer[i];
// if (l->texpaint_sculpt != NULL && slot_layer_is_visible(l)) {
// any_array_push(sculpt_layers, l);
// i32_array_push(sculpt_indices, i);
// }
// }
// sculpt_make_mesh_run(kong, sculpt_layers, sculpt_indices);
// }
con_depth->data->color_writes_red = u8_array_create_from_raw(
(u8[]){
false,
+12 -6
View File
@@ -162,11 +162,17 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
kong->frag_n = true;
node_shader_add_function(kong, str_pack_float_int16);
for (i32 i = 0; i < project_layers->length; ++i) {
slot_layer_t *l = project_layers->buffer[i];
if (l->texpaint_sculpt != NULL) {
sculpt_make_mesh_run(kong, l);
{
slot_layer_t_array_t *sculpt_layers = any_array_create_from_raw((void *[]){}, 0);
i32_array_t *sculpt_indices = i32_array_create(0);
for (i32 i = 0; i < project_layers->length; ++i) {
slot_layer_t *l = project_layers->buffer[i];
if (l->texpaint_sculpt != NULL && slot_layer_is_visible(l)) {
any_array_push(sculpt_layers, l);
i32_array_push(sculpt_indices, i);
}
}
sculpt_make_mesh_run(kong, sculpt_layers, sculpt_indices);
}
if (g_context->colorid_viewport_mask && g_context->tool != TOOL_TYPE_COLORID) {
@@ -371,8 +377,8 @@ node_shader_context_t *make_mesh_run(material_t *data, i32 layer_pass) {
node_shader_write_frag(kong, "basecol = texpaint_sample.rgb * texpaint_opac;");
}
else {
node_shader_write_frag(kong, string("basecol = %s;",
make_material_blend_mode(kong, slot_layer_get_blending(l), "basecol", "texpaint_sample.rgb", "texpaint_opac")));
node_shader_write_frag(kong, string("basecol = %s;", make_material_blend_mode(kong, slot_layer_get_blending(l), "basecol",
"texpaint_sample.rgb", "texpaint_opac")));
}
}
+42 -2
View File
@@ -584,8 +584,48 @@ node_shader_context_t *make_paint_run(material_t *data, material_context_t *matc
}
parser_material_finalize(con_paint);
parser_material_triplanar = false;
parser_material_sample_keep_aspect = false;
parser_material_triplanar = false;
parser_material_sample_keep_aspect = false;
{
slot_layer_t_array_t *sculpt_layers = any_array_create_from_raw((void *[]){}, 0);
i32_array_t *sculpt_indices = i32_array_create(0);
for (i32 i = 0; i < project_layers->length; ++i) {
slot_layer_t *l = project_layers->buffer[i];
if (l->texpaint_sculpt != NULL && slot_layer_is_visible(l)) {
any_array_push(sculpt_layers, l);
i32_array_push(sculpt_indices, i);
}
}
i32 scount = sculpt_layers->length;
if (scount > 0) {
i32 idx0 = sculpt_indices->buffer[0];
node_shader_add_constant(kong, string("texpaint_sculpt_size%d: float2", idx0), string("_size(_texpaint_sculpt%d)", idx0));
for (i32 i = 0; i < scount; ++i) {
i32 idx = sculpt_indices->buffer[i];
node_shader_add_texture(kong, string("texpaint_sculpt%d", idx), string("_texpaint_sculpt%d", idx));
}
if (scount > 1) {
node_shader_add_texture(kong, "texpaint_sculpt_base", "_texpaint_sculpt_base");
}
node_shader_write_attrib_vert(kong, string("var sculpt_uv_paint: uint2 = uint2(uint(float(vertex_id()) %% constants.texpaint_sculpt_size%d.x), "
"uint(float(vertex_id()) / constants.texpaint_sculpt_size%d.y));",
idx0, idx0));
node_shader_write_attrib_vert(kong, string("var sculpt_pos_paint: float4 = texpaint_sculpt%d[sculpt_uv_paint];", idx0));
for (i32 i = 1; i < scount; ++i) {
i32 idx = sculpt_indices->buffer[i];
node_shader_write_attrib_vert(
kong, string("sculpt_pos_paint = sculpt_pos_paint + texpaint_sculpt%d[sculpt_uv_paint] - texpaint_sculpt_base[sculpt_uv_paint];", idx));
}
node_shader_write_attrib_vert(kong, "output.ndc = constants.WVP * float4(sculpt_pos_paint.xyz, 1.0);");
if (kong->frag_wposition) {
node_shader_write_attrib_vert(kong, "output.wposition = (constants.W * float4(sculpt_pos_paint.xyz, 1.0)).xyz;");
}
}
}
con_paint->data->shader_from_source = true;
gpu_create_shaders_from_kong(node_shader_get(kong), &con_paint->data->vertex_shader, &con_paint->data->fragment_shader,
&con_paint->data->_->vertex_shader_size, &con_paint->data->_->fragment_shader_size);
+87 -26
View File
@@ -1,7 +1,7 @@
#include "global.h"
void sculpt_import_mesh_pack_to_texture(mesh_data_t *mesh, slot_layer_t *l) {
void sculpt_import_mesh_pack_to_texture(mesh_data_t *mesh, gpu_texture_t *target) {
buffer_t *b = buffer_create(config_get_texture_res_x() * config_get_texture_res_y() * 4 * 4);
for (i32 i = 0; i < math_floor(mesh->index_array->length); ++i) {
i32 index = mesh->index_array->buffer[i];
@@ -24,7 +24,7 @@ void sculpt_import_mesh_pack_to_texture(mesh_data_t *mesh, slot_layer_t *l) {
}
gpu_texture_t *imgmesh = gpu_create_texture_from_bytes(b, config_get_texture_res_x(), config_get_texture_res_y(), GPU_TEXTURE_FORMAT_RGBA128);
draw_begin(l->texpaint_sculpt, false, 0);
draw_begin(target, false, 0);
draw_set_pipeline(pipes_copy128);
draw_scaled_image(imgmesh, 0, 0, config_get_texture_res_x(), config_get_texture_res_y());
draw_set_pipeline(NULL);
@@ -211,38 +211,73 @@ node_shader_context_t *sculpt_make_sculpt_run(material_t *data, material_context
return con_paint;
}
void sculpt_make_mesh_run(node_shader_t *kong, slot_layer_t *l) {
void sculpt_make_mesh_run(node_shader_t *kong, slot_layer_t_array_t *sculpt_layers, i32_array_t *sculpt_indices) {
i32 count = sculpt_layers->length;
if (count == 0) {
return;
}
i32 idx0 = sculpt_indices->buffer[0];
node_shader_add_constant(kong, "WVP: float4x4", "_world_view_proj_matrix");
i32 lid = array_index_of(project_layers, l);
node_shader_add_texture(kong, "texpaint_sculpt", string("_texpaint_sculpt%s", i32_to_string(lid)));
node_shader_add_constant(kong, "texpaint_sculpt_size: float2", string("_size(_texpaint_sculpt%s)", i32_to_string(lid)));
// node_shader_write_vert(kong, "var meshpos: float3 = sample_lod(texpaint_sculpt, sampler_linear, uint2(vertex_id() % constants.texpaint_sculpt_size.x,
// vertex_id() / constants.texpaint_sculpt_size.y), 0.0).xyz;");
node_shader_write_vert(kong, "var meshpos: float4 = texpaint_sculpt[uint2(uint(float(vertex_id()) % constants.texpaint_sculpt_size.x), "
"uint(float(vertex_id()) / constants.texpaint_sculpt_size.y))];");
// + input.pos.xyz * 0.000001
node_shader_write_vert(kong, "output.pos = constants.WVP * float4(meshpos.xyz, 1.0);");
kong->frag_n = false;
node_shader_add_constant(kong, "N: float3x3", "_normal_matrix");
node_shader_add_out(kong, "wnormal: float3");
kong->frag_n = false;
node_shader_add_constant(kong, string("texpaint_sculpt_size%d: float2", idx0), string("_size(_texpaint_sculpt%d)", idx0));
for (i32 i = 0; i < count; ++i) {
i32 idx = sculpt_indices->buffer[i];
node_shader_add_texture(kong, string("texpaint_sculpt%d", idx), string("_texpaint_sculpt%d", idx));
}
if (count > 1) {
node_shader_add_texture(kong, "texpaint_sculpt_base", "_texpaint_sculpt_base");
}
// Position
node_shader_write_vert(kong, string("var sculpt_uv: uint2 = uint2(uint(float(vertex_id()) %% constants.texpaint_sculpt_size%d.x), "
"uint(float(vertex_id()) / constants.texpaint_sculpt_size%d.y));",
idx0, idx0));
node_shader_write_vert(kong, string("var texpaint_sculpt_sample: float4 = texpaint_sculpt%d[sculpt_uv];", idx0));
node_shader_write_vert(kong, "var sculpt_pos: float3 = texpaint_sculpt_sample.xyz;");
for (i32 i = 1; i < count; ++i) {
i32 idx = sculpt_indices->buffer[i];
node_shader_write_vert(kong, string("var texpaint_sculpt_sample_%d: float4 = texpaint_sculpt%d[sculpt_uv];", idx, idx));
node_shader_write_vert(kong, string("var texpaint_sculpt_base_sample_%d: float4 = texpaint_sculpt_base[sculpt_uv];", idx));
node_shader_write_vert(kong, string("sculpt_pos = sculpt_pos + texpaint_sculpt_sample_%d.xyz - texpaint_sculpt_base_sample_%d.xyz;", idx, idx));
}
node_shader_write_vert(kong, "output.pos = constants.WVP * float4(sculpt_pos, 1.0);");
// Normal
node_shader_write_attrib_vert(kong, "var base_vertex0: float = float(vertex_id()) - (float(vertex_id()) % float(3));");
node_shader_write_attrib_vert(kong, "var base_vertex1: float = base_vertex0 + 1.0;");
node_shader_write_attrib_vert(kong, "var base_vertex2: float = base_vertex0 + 2.0;");
// node_shader_write_attrib_vert(kong, "var meshpos0: float3 = sample_lod(texpaint_sculpt, sampler_linear, uint2(base_vertex0 %
// constants.texpaint_sculpt_size.x, base_vertex0 / constants.texpaint_sculpt_size.y), 0.0).xyz;"); node_shader_write_attrib_vert(kong, "var meshpos1:
// float3 = sample_lod(texpaint_sculpt, sampler_linear, uint2(base_vertex1 % constants.texpaint_sculpt_size.x, base_vertex1 /
// constants.texpaint_sculpt_size.y), 0.0).xyz;"); node_shader_write_attrib_vert(kong, "var meshpos2: float3 = sample_lod(texpaint_sculpt, sampler_linear,
// uint2(base_vertex2 % constants.texpaint_sculpt_size.x, base_vertex2 / constants.texpaint_sculpt_size.y), 0.0).xyz;");
node_shader_write_attrib_vert(kong, "var meshpos0: float4 = texpaint_sculpt[uint2(uint(base_vertex0 % constants.texpaint_sculpt_size.x), uint(base_vertex0 "
"/ constants.texpaint_sculpt_size.y))];");
node_shader_write_attrib_vert(kong, "var meshpos1: float4 = texpaint_sculpt[uint2(uint(base_vertex1 % constants.texpaint_sculpt_size.x), uint(base_vertex1 "
"/ constants.texpaint_sculpt_size.y))];");
node_shader_write_attrib_vert(kong, "var meshpos2: float4 = texpaint_sculpt[uint2(uint(base_vertex2 % constants.texpaint_sculpt_size.x), uint(base_vertex2 "
"/ constants.texpaint_sculpt_size.y))];");
node_shader_write_attrib_vert(
kong,
string("var uv0: uint2 = uint2(uint(base_vertex0 %% constants.texpaint_sculpt_size%d.x), uint(base_vertex0 / constants.texpaint_sculpt_size%d.y));",
idx0, idx0));
node_shader_write_attrib_vert(
kong,
string("var uv1: uint2 = uint2(uint(base_vertex1 %% constants.texpaint_sculpt_size%d.x), uint(base_vertex1 / constants.texpaint_sculpt_size%d.y));",
idx0, idx0));
node_shader_write_attrib_vert(
kong,
string("var uv2: uint2 = uint2(uint(base_vertex2 %% constants.texpaint_sculpt_size%d.x), uint(base_vertex2 / constants.texpaint_sculpt_size%d.y));",
idx0, idx0));
node_shader_write_attrib_vert(kong, string("var meshpos0: float4 = texpaint_sculpt%d[uv0];", idx0));
node_shader_write_attrib_vert(kong, string("var meshpos1: float4 = texpaint_sculpt%d[uv1];", idx0));
node_shader_write_attrib_vert(kong, string("var meshpos2: float4 = texpaint_sculpt%d[uv2];", idx0));
for (i32 i = 1; i < count; ++i) {
i32 idx = sculpt_indices->buffer[i];
node_shader_write_attrib_vert(kong, string("meshpos0 = meshpos0 + texpaint_sculpt%d[uv0] - texpaint_sculpt_base[uv0];", idx));
node_shader_write_attrib_vert(kong, string("meshpos1 = meshpos1 + texpaint_sculpt%d[uv1] - texpaint_sculpt_base[uv1];", idx));
node_shader_write_attrib_vert(kong, string("meshpos2 = meshpos2 + texpaint_sculpt%d[uv2] - texpaint_sculpt_base[uv2];", idx));
}
node_shader_write_attrib_vert(kong, "var meshnor: float3 = normalize(cross(meshpos2.xyz - meshpos1.xyz, meshpos0.xyz - meshpos1.xyz));");
node_shader_write_attrib_vert(kong, "output.wnormal = constants.N * meshnor;");
node_shader_write_attrib_frag(kong, "var n: float3 = normalize(input.wnormal);");
}
@@ -256,7 +291,29 @@ void sculpt_init_sculpt_texture(slot_layer_t *l, mesh_data_t *md) {
t->format = "RGBA128";
l->texpaint_sculpt = render_path_create_render_target(t)->_image;
}
sculpt_import_mesh_pack_to_texture(md, l);
sculpt_import_mesh_pack_to_texture(md, l->texpaint_sculpt);
i32 sculpt_layer_count = 0;
for (i32 i = 0; i < project_layers->length; ++i) {
if (project_layers->buffer[i]->texpaint_sculpt != NULL) {
sculpt_layer_count++;
}
}
if (any_map_get(render_path_render_targets, "texpaint_sculpt_base") == NULL) {
render_target_t *t = render_target_create();
t->name = "texpaint_sculpt_base";
t->width = config_get_texture_res_x();
t->height = config_get_texture_res_y();
t->format = "RGBA128";
render_path_create_render_target(t);
}
if (sculpt_layer_count == 1) {
render_path_set_target("texpaint_sculpt_base", NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
render_path_bind_target(string("texpaint_sculpt%s", i32_to_string(id)), "tex");
render_path_draw_shader("Scene/copy_pass/copyRGBA128_pass");
}
}
void sculpt_init() {
@@ -296,6 +353,10 @@ void sculpt_init() {
md = mesh_data_create(raw);
mesh_object_set_data(g_context->paint_object, md);
if (g_context->merged_object != NULL) {
util_mesh_merge(NULL);
}
make_material_parse_paint_material(true);
make_material_parse_mesh_material();
+13 -2
View File
@@ -433,6 +433,17 @@ void render_path_paint_commands_paint(bool dilation) {
if (read_tc) {
render_path_bind_target("gbuffer2", "gbuffer2");
}
i32 sculpt_layer_count = 0;
for (i32 i = 0; i < project_layers->length; ++i) {
slot_layer_t *sl = project_layers->buffer[i];
if (sl->texpaint_sculpt != NULL && slot_layer_is_visible(sl)) {
render_path_bind_target(string("texpaint_sculpt%d", sl->id), string("texpaint_sculpt%d", sl->id));
sculpt_layer_count++;
}
}
if (sculpt_layer_count > 1) {
render_path_bind_target("texpaint_sculpt_base", "texpaint_sculpt_base");
}
object_t *bullet = scene_get_child(".Bullet");
bool bullet_vis = bullet != NULL && bullet->visible;
if (bullet != NULL) {
@@ -703,8 +714,8 @@ void render_path_paint_commands_cursor() {
return;
}
f32 mx = g_context->paint_vec.x;
f32 my = 1.0 - g_context->paint_vec.y;
f32 mx = g_context->paint_vec.x;
f32 my = 1.0 - g_context->paint_vec.y;
f32 brush_nodes_radius = 1.0; // g_context->brush_nodes_radius; // Prevent cursor jumping constantly if randomness is used in brush nodes
if (context_is_decal() && !g_context->paint2d) {
+2 -2
View File
@@ -1168,7 +1168,7 @@ void layers_update_fill_layers() {
if (l->texpaint_sculpt != NULL) {
i32 tid = l->id;
i32 hid = history_undo_i - 1 < 0 ? g_config->undo_steps - 1 : history_undo_i - 1;
sculpt_import_mesh_pack_to_texture(g_context->paint_object->data, l);
sculpt_import_mesh_pack_to_texture(g_context->paint_object->data, l->texpaint_sculpt);
render_path_set_target(string("texpaint_sculpt_undo%d", hid), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
render_path_bind_target(string("texpaint_sculpt%d", tid), "tex");
render_path_draw_shader("Scene/copy_pass/copyRGBA128_pass");
@@ -1248,7 +1248,7 @@ void layers_update_fill_layer(bool parse_paint) {
if (g_context->layer->texpaint_sculpt != NULL) {
i32 tid = g_context->layer->id;
i32 hid = history_undo_i - 1 < 0 ? g_config->undo_steps - 1 : history_undo_i - 1;
sculpt_import_mesh_pack_to_texture(g_context->paint_object->data, g_context->layer);
sculpt_import_mesh_pack_to_texture(g_context->paint_object->data, g_context->layer->texpaint_sculpt);
render_path_set_target(string("texpaint_sculpt_undo%d", hid), NULL, NULL, GPU_CLEAR_NONE, 0, 0.0);
render_path_bind_target(string("texpaint_sculpt%d", tid), "tex");
render_path_draw_shader("Scene/copy_pass/copyRGBA128_pass");
+4
View File
@@ -381,6 +381,10 @@ gpu_texture_t *uniforms_ext_tex_link(object_t *object, material_data_t *mat, cha
i32 tid = parse_int(substring(link, string_length(link) - 1, string_length(link)));
return tid < project_layers->length ? project_layers->buffer[tid]->texpaint_pack : NULL;
}
if (string_equals(link, "_texpaint_sculpt_base")) {
render_target_t *rt = any_map_get(render_path_render_targets, "texpaint_sculpt_base");
return rt != NULL ? rt->_image : NULL;
}
if (starts_with(link, "_texpaint_sculpt")) {
i32 tid = parse_int(substring(link, string_length(link) - 1, string_length(link)));
return tid < project_layers->length ? project_layers->buffer[tid]->texpaint_sculpt : NULL;