From 209e6a547c7fe39f4c6a3d5eee89de56cd7f293e Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Wed, 9 Mar 2022 11:30:01 +0100 Subject: Small changes --- source/blender/editors/sculpt_paint/sculpt.c | 1 + .../editors/sculpt_paint/sculpt_texture_paint_b.cc | 148 +++++++++++---------- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index f19c3c66c9a..8c3a13fe5b8 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -2235,6 +2235,7 @@ static float brush_strength(const Sculpt *sd, case SCULPT_TOOL_SLIDE_RELAX: return alpha * pressure * overlap * feather * 2.0f; case SCULPT_TOOL_PAINT: + case SCULPT_TOOL_TEXTURE_PAINT: final_pressure = pressure * pressure; return final_pressure * overlap * feather; case SCULPT_TOOL_SMEAR: diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc index f83a5de0f43..81e5767cf6b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc +++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc @@ -68,8 +68,8 @@ struct NodeData { flags.dirty = false; for (PixelData &pixel : pixels) { if (pixel.flags.dirty) { - const int pixel_offset = (pixel.pixel_pos[1] * image_buffer.x + pixel.pixel_pos[0]) * 4; - copy_v4_v4(&image_buffer.rect_float[pixel_offset], pixel.content); + const int pixel_offset = (pixel.pixel_pos[1] * image_buffer.x + pixel.pixel_pos[0]); + copy_v4_v4(&image_buffer.rect_float[pixel_offset * 4], pixel.content); pixel.flags.dirty = false; } } @@ -91,7 +91,13 @@ struct NodeData { } }; -namespace shaders { +struct TexturePaintingUserData { + Object *ob; + Brush *brush; + PBVHNode **nodes; +}; + +namespace rasterization { using namespace imbuf::rasterizer; @@ -195,18 +201,54 @@ class NodeDataDrawingTarget : public AbstractDrawingTarget; -} // namespace shaders +static void init_rasterization_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + TexturePaintingUserData *data = static_cast(userdata); + Object *ob = data->ob; + SculptSession *ss = ob->sculpt; + PBVHNode *node = data->nodes[n]; + + NodeData *node_data = static_cast(BKE_pbvh_node_texture_paint_data_get(node)); + // TODO: reinit when texturing on different image? + if (node_data != nullptr) { + return; + } + + TIMEIT_START(init_texture_paint_for_node); + node_data = MEM_new(__func__); + node_data->init_pixels_rasterization(ob, node, ss->mode.texture_paint.drawing_target); + BKE_pbvh_node_texture_paint_data_set(node, node_data, NodeData::free_func); + TIMEIT_END(init_texture_paint_for_node); +} + +static void init_using_rasterization(Object *ob, int totnode, PBVHNode **nodes) +{ + TIMEIT_START(init_using_rasterization); + TexturePaintingUserData data = {nullptr}; + data.ob = ob; + data.nodes = nodes; + + TaskParallelSettings settings; + BKE_pbvh_parallel_range_settings(&settings, true, totnode); + BLI_task_parallel_range(0, totnode, &data, init_rasterization_task_cb_ex, &settings); + TIMEIT_END(init_using_rasterization); +} + +} // namespace rasterization void NodeData::init_pixels_rasterization(Object *ob, PBVHNode *node, ImBuf *image_buffer) { + using namespace rasterization; Mesh *mesh = static_cast(ob->data); MLoopUV *ldata_uv = static_cast(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV)); if (ldata_uv == nullptr) { return; } - shaders::RasterizerType rasterizer; - shaders::NodeDataPair node_data_pair; + RasterizerType rasterizer; + NodeDataPair node_data_pair; rasterizer.vertex_shader().image_size = float2(image_buffer->x, image_buffer->y); rasterizer.fragment_shader().image_buffer = image_buffer; node_data_pair.node_data = this; @@ -234,9 +276,9 @@ void NodeData::init_pixels_rasterization(Object *ob, PBVHNode *node, ImBuf *imag const int v2_loop_index = p->loopstart + triangle + 1; const int v3_loop_index = p->loopstart + triangle + 2; - shaders::VertexInput v1(mvert[v1_index].co, ldata_uv[v1_loop_index].uv); - shaders::VertexInput v2(mvert[v2_index].co, ldata_uv[v2_loop_index].uv); - shaders::VertexInput v3(mvert[v3_index].co, ldata_uv[v3_loop_index].uv); + VertexInput v1(mvert[v1_index].co, ldata_uv[v1_loop_index].uv); + VertexInput v2(mvert[v2_index].co, ldata_uv[v2_loop_index].uv); + VertexInput v3(mvert[v3_index].co, ldata_uv[v3_loop_index].uv); rasterizer.draw_triangle(v1, v2, v3); } } @@ -245,12 +287,7 @@ void NodeData::init_pixels_rasterization(Object *ob, PBVHNode *node, ImBuf *imag rasterizer.deactivate_drawing_target(); } -struct TexturePaintingUserData { - Object *ob; - Brush *brush; - PBVHNode **nodes; -}; - +namespace painting { static void do_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls)) @@ -267,58 +304,30 @@ static void do_task_cb_ex(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, brush->falloff_shape); + float3 brush_srgb(brush->rgb[0], brush->rgb[1], brush->rgb[2]); + float3 brush_linear; + srgb_to_linearrgb_v3_v3(brush_linear, brush_srgb); + + const float brush_strength = ss->cache->bstrength; + for (PixelData &pixel : node_data->pixels) { if (!sculpt_brush_test_sq_fn(&test, pixel.local_pos)) { continue; } const float falloff_strength = BKE_brush_curve_strength(brush, sqrtf(test.dist), test.radius); - interp_v3_v3v3(pixel.content, pixel.content, brush->rgb, falloff_strength); + interp_v3_v3v3(pixel.content, pixel.content, brush_linear, falloff_strength * brush_strength); pixel.content[3] = 1.0f; pixel.flags.dirty = true; BLI_rcti_do_minmax_v(&node_data->dirty_region, pixel.pixel_pos); node_data->flags.dirty = true; } } - -static void init_rasterization_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - TexturePaintingUserData *data = static_cast(userdata); - Object *ob = data->ob; - SculptSession *ss = ob->sculpt; - PBVHNode *node = data->nodes[n]; - - NodeData *node_data = static_cast(BKE_pbvh_node_texture_paint_data_get(node)); - // TODO: reinit when texturing on different image? - if (node_data != nullptr) { - return; - } - - TIMEIT_START(init_texture_paint_for_node); - node_data = MEM_new(__func__); - node_data->init_pixels_rasterization(ob, node, ss->mode.texture_paint.drawing_target); - BKE_pbvh_node_texture_paint_data_set(node, node_data, NodeData::free_func); - TIMEIT_END(init_texture_paint_for_node); -} - -static void init_using_rasterization(Object *ob, int totnode, PBVHNode **nodes) -{ - TIMEIT_START(init_using_rasterization); - TexturePaintingUserData data = {nullptr}; - data.ob = ob; - data.nodes = nodes; - - TaskParallelSettings settings; - BKE_pbvh_parallel_range_settings(&settings, true, totnode); - - BLI_task_parallel_range(0, totnode, &data, init_rasterization_task_cb_ex, &settings); - TIMEIT_END(init_using_rasterization); -} +} // namespace painting struct BucketEntry { PBVHNode *node; const MPoly *poly; + rctf uv_bounds; }; struct Bucket { static const int Size = 16; @@ -336,6 +345,9 @@ static bool init_using_intersection(SculptSession *ss, { const int pixel_offset = xy[1] * image_buffer->x + xy[0]; for (BucketEntry &entry : bucket.entries) { + if (!BLI_rctf_isect_pt_v(&entry.uv_bounds, uv)) { + continue; + } const MPoly *p = entry.poly; const MLoop *loopstart = &ss->mloop[p->loopstart]; @@ -365,8 +377,7 @@ static bool init_using_intersection(SculptSession *ss, PixelData new_pixel; new_pixel.local_pos = local_pos; new_pixel.pixel_pos = xy; - copy_v4_fl(&image_buffer->rect_float[pixel_offset * 4], 1.0); - new_pixel.content = float4(image_buffer->rect_float[pixel_offset * 4]); + new_pixel.content = float4(&image_buffer->rect_float[pixel_offset * 4]); new_pixel.flags.dirty = false; PBVHNode *node = entry.node; @@ -424,8 +435,7 @@ static bool init_using_intersection(SculptSession *ss, PixelData new_pixel; new_pixel.local_pos = local_pos; new_pixel.pixel_pos = xy; - new_pixel.content = float4(image_buffer->rect_float[pixel_offset * 4]); - copy_v4_fl(&image_buffer->rect_float[pixel_offset * 4], 1.0); + new_pixel.content = float4(&image_buffer->rect_float[pixel_offset * 4]); new_pixel.flags.dirty = false; node_data->pixels.append(new_pixel); return true; @@ -469,8 +479,7 @@ static void init_using_intersection(Object *ob, int totnode, PBVHNode **nodes) int pixels_added = 0; Bucket bucket; for (int y_bucket = 0; y_bucket < image_buffer->y; y_bucket += Bucket::Size) { - printf("%d: %d pixels added.\n", y_bucket, - pixels_added); + printf("%d: %d pixels added.\n", y_bucket, pixels_added); for (int x_bucket = 0; x_bucket < image_buffer->x; x_bucket += Bucket::Size) { bucket.entries.clear(); BLI_rctf_init(&bucket.bounds, @@ -500,24 +509,17 @@ static void init_using_intersection(Object *ob, int totnode, PBVHNode **nodes) rctf poly_bound; BLI_rctf_init_minmax(&poly_bound); - for (int triangle = 0; triangle < p->totloop - 2; triangle++) { - const int v1_loop_index = p->loopstart; - const int v2_loop_index = p->loopstart + triangle + 1; - const int v3_loop_index = p->loopstart + triangle + 2; - const float2 v1_uv = ldata_uv[v1_loop_index].uv; - const float2 v2_uv = ldata_uv[v2_loop_index].uv; - const float2 v3_uv = ldata_uv[v3_loop_index].uv; - BLI_rctf_do_minmax_v(&poly_bound, v1_uv); - BLI_rctf_do_minmax_v(&poly_bound, v2_uv); - BLI_rctf_do_minmax_v(&poly_bound, v3_uv); - BLI_rctf_do_minmax_v(&node_data->uv_region, v1_uv); - BLI_rctf_do_minmax_v(&node_data->uv_region, v2_uv); - BLI_rctf_do_minmax_v(&node_data->uv_region, v3_uv); + for (int l = 0; l < p->totloop; l++) { + const int v_loop_index = p->loopstart + l; + const float2 v_uv = ldata_uv[v_loop_index].uv; + BLI_rctf_do_minmax_v(&poly_bound, v_uv); + BLI_rctf_do_minmax_v(&node_data->uv_region, v_uv); } if (BLI_rctf_isect(&bucket.bounds, &poly_bound, nullptr)) { BucketEntry entry; entry.node = node; entry.poly = p; + entry.uv_bounds = poly_bound; bucket.entries.append(entry); } } @@ -604,7 +606,7 @@ void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int BKE_pbvh_parallel_range_settings(&settings, true, totnode); TIMEIT_START(texture_painting); - BLI_task_parallel_range(0, totnode, &data, do_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, painting::do_task_cb_ex, &settings); TIMEIT_END(texture_painting); ss->mode.texture_paint.drawing_target = nullptr; @@ -623,7 +625,7 @@ void SCULPT_init_texture_paint(Object *ob) BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); const bool do_rasterization = false; if (do_rasterization) { - init_using_rasterization(ob, totnode, nodes); + rasterization::init_using_rasterization(ob, totnode, nodes); } else { init_using_intersection(ob, totnode, nodes); -- cgit v1.2.3