Blender V4.5
sculpt_paint_color.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_brush_types.h"
10#include "DNA_meshdata_types.h"
11
12#include "BLI_color.hh"
14#include "BLI_hash.h"
16#include "BLI_math_matrix.hh"
17#include "BLI_math_vector.hh"
18#include "BLI_vector.hh"
19
20#include "BKE_attribute.hh"
21#include "BKE_brush.hh"
22#include "BKE_colorband.hh"
23#include "BKE_colortools.hh"
24#include "BKE_customdata.hh"
25#include "BKE_mesh.hh"
26#include "BKE_paint.hh"
27#include "BKE_paint_bvh.hh"
28
30
31#include "mesh_brush_common.hh"
32#include "sculpt_automask.hh"
33#include "sculpt_color.hh"
34#include "sculpt_intern.hh"
35#include "sculpt_smooth.hh"
36
37#include "IMB_imbuf.hh"
38
39#include <cmath>
40#include <cstdlib>
41
43
44static void calc_local_positions(const float4x4 &mat,
45 const Span<int> verts,
46 const Span<float3> positions,
47 const MutableSpan<float3> local_positions)
48{
49 for (const int i : verts.index_range()) {
50 local_positions[i] = math::transform_point(mat, positions[verts[i]]);
51 }
52}
53
54template<typename Func> inline void to_static_color_type(const CPPType &type, const Func &func)
55{
56 if (type.is<ColorGeometry4f>()) {
57 func(MPropCol());
58 }
59 else if (type.is<ColorGeometry4b>()) {
60 func(MLoopCol());
61 }
62}
63
64template<typename T> float4 to_float(const T &src);
65
66template<> float4 to_float(const MLoopCol &src)
67{
68 float4 dst;
69 rgba_uchar_to_float(dst, reinterpret_cast<const uchar *>(&src));
71 return dst;
72}
73template<> float4 to_float(const MPropCol &src)
74{
75 return src.color;
76}
77
78template<typename T> void from_float(const float4 &src, T &dst);
79
80template<> void from_float(const float4 &src, MLoopCol &dst)
81{
82 float4 temp;
83 linearrgb_to_srgb_v3_v3(temp, src);
84 temp[3] = src[3];
85 rgba_float_to_uchar(reinterpret_cast<uchar *>(&dst), temp);
86}
87template<> void from_float(const float4 &src, MPropCol &dst)
88{
89 copy_v4_v4(dst.color, src);
90}
91
92template<typename T>
94 const Span<int> corner_verts,
95 const GroupedSpan<int> vert_to_face_map,
96 const GSpan color_attribute,
97 const bke::AttrDomain color_domain,
98 const int vert)
99{
100 const T *colors_typed = static_cast<const T *>(color_attribute.data());
101 if (color_domain == bke::AttrDomain::Corner) {
102 float4 r_color(0.0f);
103 for (const int face : vert_to_face_map[vert]) {
104 const int corner = bke::mesh::face_find_corner_from_vert(faces[face], corner_verts, vert);
105 r_color += to_float(colors_typed[corner]);
106 }
107 return r_color / float(vert_to_face_map[vert].size());
108 }
109 return to_float(colors_typed[vert]);
110}
111
112template<typename T>
114 const Span<int> corner_verts,
115 const GroupedSpan<int> vert_to_face_map,
116 const GMutableSpan color_attribute,
117 const bke::AttrDomain color_domain,
118 const int vert,
119 const float4 &color)
120{
121 if (color_domain == bke::AttrDomain::Corner) {
122 for (const int i_face : vert_to_face_map[vert]) {
123 const IndexRange face = faces[i_face];
124 MutableSpan<T> colors{static_cast<T *>(color_attribute.data()) + face.start(), face.size()};
125 Span<int> face_verts = corner_verts.slice(face);
126
127 for (const int i : IndexRange(face.size())) {
128 if (face_verts[i] == vert) {
129 from_float(color, colors[i]);
130 }
131 }
132 }
133 }
134 else {
135 from_float(color, static_cast<T *>(color_attribute.data())[vert]);
136 }
137}
138
140 const Span<int> corner_verts,
141 const GroupedSpan<int> vert_to_face_map,
142 const GSpan color_attribute,
143 const bke::AttrDomain color_domain,
144 const int vert)
145{
147 to_static_color_type(color_attribute.type(), [&](auto dummy) {
148 using T = decltype(dummy);
149 color = color_vert_get<T>(
150 faces, corner_verts, vert_to_face_map, color_attribute, color_domain, vert);
151 });
152 return color;
153}
154
156 const Span<int> corner_verts,
157 const GroupedSpan<int> vert_to_face_map,
158 const bke::AttrDomain color_domain,
159 const int vert,
160 const float4 &color,
161 const GMutableSpan color_attribute)
162{
163 to_static_color_type(color_attribute.type(), [&](auto dummy) {
164 using T = decltype(dummy);
165 color_vert_set<T>(
166 faces, corner_verts, vert_to_face_map, color_attribute, color_domain, vert, color);
167 });
168}
169
171 GMutableSpan color_attribute,
172 MutableSpan<float4> r_colors)
173{
174 to_static_color_type(color_attribute.type(), [&](auto dummy) {
175 using T = decltype(dummy);
176 T *colors_typed = static_cast<T *>(color_attribute.data());
177 for (const int i : indices.index_range()) {
178 T temp = colors_typed[indices[i]];
179 from_float(r_colors[i], colors_typed[indices[i]]);
180 r_colors[i] = to_float(temp);
181 }
182 });
183}
184
185void gather_colors(const GSpan color_attribute,
186 const Span<int> indices,
187 MutableSpan<float4> r_colors)
188{
189 to_static_color_type(color_attribute.type(), [&](auto dummy) {
190 using T = decltype(dummy);
191 const T *colors_typed = static_cast<const T *>(color_attribute.data());
192 for (const int i : indices.index_range()) {
193 r_colors[i] = to_float(colors_typed[indices[i]]);
194 }
195 });
196}
197
199 const Span<int> corner_verts,
200 const GroupedSpan<int> vert_to_face_map,
201 const GSpan color_attribute,
202 const bke::AttrDomain color_domain,
203 const Span<int> verts,
204 const MutableSpan<float4> r_colors)
205{
206 if (color_domain == bke::AttrDomain::Point) {
207 gather_colors(color_attribute, verts, r_colors);
208 }
209 else {
210 to_static_color_type(color_attribute.type(), [&](auto dummy) {
211 using T = decltype(dummy);
212 for (const int i : verts.index_range()) {
213 r_colors[i] = color_vert_get<T>(
214 faces, corner_verts, vert_to_face_map, color_attribute, color_domain, verts[i]);
215 }
216 });
217 }
218}
219
221{
222 const bke::AttributeAccessor attributes = mesh.attributes();
223 const StringRef name = mesh.active_color_attribute;
224 const bke::GAttributeReader colors = attributes.lookup(name);
225 if (!colors) {
226 return {};
227 }
229 if ((CD_TYPE_AS_MASK(data_type) & CD_MASK_COLOR_ALL) == 0) {
230 return {};
231 }
233 return {};
234 }
235 return colors;
236}
237
239{
240 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
241 const StringRef name = mesh.active_color_attribute;
242 bke::GSpanAttributeWriter colors = attributes.lookup_for_write_span(name);
243 if (!colors) {
244 return {};
245 }
247 if ((CD_TYPE_AS_MASK(data_type) & CD_MASK_COLOR_ALL) == 0) {
248 colors.finish();
249 return {};
250 }
252 colors.finish();
253 return {};
254 }
255 return colors;
256}
257
269
270static void do_color_smooth_task(const Depsgraph &depsgraph,
271 const Object &object,
272 const Span<float3> vert_positions,
273 const Span<float3> vert_normals,
275 const Span<int> corner_verts,
276 const GroupedSpan<int> vert_to_face_map,
277 const MeshAttributeData &attribute_data,
278 const Brush &brush,
279 const bke::pbvh::MeshNode &node,
281 bke::GSpanAttributeWriter &color_attribute)
282{
283 const SculptSession &ss = *object.sculpt;
284 const StrokeCache &cache = *ss.cache;
285
286 const Span<int> verts = node.verts();
287
288 tls.factors.resize(verts.size());
289 const MutableSpan<float> factors = tls.factors;
290 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
291 filter_region_clip_factors(ss, vert_positions, verts, factors);
292 if (brush.flag & BRUSH_FRONTFACE) {
293 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
294 }
295
296 tls.distances.resize(verts.size());
297 const MutableSpan<float> distances = tls.distances;
299 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
300 filter_distances_with_radius(cache.radius, distances, factors);
301 apply_hardness_to_distances(cache, distances);
302 calc_brush_strength_factors(cache, brush, distances, factors);
303
304 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
305
306 calc_brush_texture_factors(ss, brush, vert_positions, verts, factors);
307 scale_factors(factors, cache.bstrength);
308
309 tls.colors.resize(verts.size());
310 MutableSpan<float4> colors = tls.colors;
311 for (const int i : verts.index_range()) {
312 colors[i] = color_vert_get(faces,
313 corner_verts,
314 vert_to_face_map,
315 color_attribute.span,
316 color_attribute.domain,
317 verts[i]);
318 }
319
321 corner_verts,
322 vert_to_face_map,
323 attribute_data.hide_poly,
324 verts,
326 tls.neighbor_data);
327
328 tls.new_colors.resize(verts.size());
329 MutableSpan<float4> new_colors = tls.new_colors;
331 corner_verts,
332 vert_to_face_map,
333 color_attribute.span,
334 color_attribute.domain,
335 neighbors,
336 new_colors);
337
338 for (const int i : colors.index_range()) {
339 blend_color_interpolate_float(new_colors[i], colors[i], new_colors[i], factors[i]);
340 }
341
342 for (const int i : verts.index_range()) {
344 corner_verts,
345 vert_to_face_map,
346 color_attribute.domain,
347 verts[i],
348 new_colors[i],
349 color_attribute.span);
350 }
351}
352
353static void do_paint_brush_task(const Scene &scene,
354 const Depsgraph &depsgraph,
355 Object &object,
356 const Span<float3> vert_positions,
357 const Span<float3> vert_normals,
359 const Span<int> corner_verts,
360 const GroupedSpan<int> vert_to_face_map,
361 const MeshAttributeData &attribute_data,
362 const Paint &paint,
363 const Brush &brush,
364 const float4x4 &mat,
365 const float4 wet_mix_sampled_color,
368 const MutableSpan<float4> mix_colors,
369 bke::GSpanAttributeWriter &color_attribute)
370{
371 const SculptSession &ss = *object.sculpt;
372 const StrokeCache &cache = *ss.cache;
373
374 const float bstrength = fabsf(ss.cache->bstrength);
375 const float alpha = BKE_brush_alpha_get(&scene, &brush);
376
377 const Span<int> verts = node.verts();
378
379 tls.factors.resize(verts.size());
380 const MutableSpan<float> factors = tls.factors;
381 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
382 filter_region_clip_factors(ss, vert_positions, verts, factors);
383 if (brush.flag & BRUSH_FRONTFACE) {
384 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
385 }
386
387 float radius;
388
389 tls.distances.resize(verts.size());
390 const MutableSpan<float> distances = tls.distances;
391 if (brush.tip_roundness < 1.0f) {
392 tls.positions.resize(verts.size());
393 calc_local_positions(mat, verts, vert_positions, tls.positions);
394 calc_brush_cube_distances<float3>(brush, tls.positions, distances);
395 radius = 1.0f;
396 }
397 else {
399 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
400 radius = cache.radius;
401 }
402 filter_distances_with_radius(radius, distances, factors);
403 apply_hardness_to_distances(radius, cache.hardness, distances);
405 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, radius, factors);
406
408 if (cache.automasking) {
409 tls.auto_mask.resize(verts.size());
410 auto_mask = tls.auto_mask;
411 auto_mask.fill(1.0f);
413 scale_factors(factors, auto_mask);
414 }
415
416 calc_brush_texture_factors(ss, brush, vert_positions, verts, factors);
417 scale_factors(factors, bstrength);
418
419 const float density = ss.cache->paint_brush.density;
420 if (density < 1.0f) {
422 const float seed = ss.cache->paint_brush.density_seed.value_or(0.0f);
423 for (const int i : verts.index_range()) {
424 const float hash_noise = BLI_hash_int_01(seed * 1000 * verts[i]);
425 if (hash_noise > density) {
426 const float noise = density * hash_noise;
427 factors[i] *= noise;
428 }
429 }
430 }
431
432 float3 brush_color_rgb = ss.cache->invert ?
433 BKE_brush_secondary_color_get(&scene, &paint, &brush) :
434 BKE_brush_color_get(&scene, &paint, &brush);
435
436 IMB_colormanagement_srgb_to_scene_linear_v3(brush_color_rgb, brush_color_rgb);
437
438 const std::optional<BrushColorJitterSettings> color_jitter_settings =
440 if (color_jitter_settings) {
441 brush_color_rgb = BKE_paint_randomize_color(*color_jitter_settings,
444 ss.cache->pressure,
445 brush_color_rgb);
446 }
447
448 float4 brush_color(brush_color_rgb, 1.0f);
449
450 const Span<float4> orig_colors = orig_color_data_get_mesh(object, node);
451
452 MutableSpan<float4> color_buffer = gather_data_mesh(mix_colors.as_span(), verts, tls.mix_colors);
453
454 if (brush.flag & BRUSH_USE_GRADIENT) {
455 switch (brush.gradient_stroke_mode) {
457 BKE_colorband_evaluate(brush.gradient, ss.cache->pressure, brush_color);
458 break;
460 float coord = fmod(ss.cache->stroke_distance / brush.gradient_spacing, 1.0);
461 BKE_colorband_evaluate(brush.gradient, coord, brush_color);
462 break;
463 }
466 brush.gradient, ss.cache->stroke_distance / brush.gradient_spacing, brush_color);
467 break;
468 }
469 }
470 }
471
472 tls.new_colors.resize(verts.size());
473 MutableSpan<float4> new_colors = tls.new_colors;
474 for (const int i : verts.index_range()) {
475 new_colors[i] = color_vert_get(faces,
476 corner_verts,
477 vert_to_face_map,
478 color_attribute.span,
479 color_attribute.domain,
480 verts[i]);
481 }
482
483 for (const int i : verts.index_range()) {
484 /* Brush paint color, brush test falloff and flow. */
485 float4 paint_color = brush_color * factors[i] * ss.cache->paint_brush.flow;
486 float4 wet_mix_color = wet_mix_sampled_color * factors[i] * ss.cache->paint_brush.flow;
487
488 /* Interpolate with the wet_mix color for wet paint mixing. */
490 paint_color, paint_color, wet_mix_color, ss.cache->paint_brush.wet_mix);
491 blend_color_mix_float(color_buffer[i], color_buffer[i], paint_color);
492
493 /* Final mix over the original color using brush alpha. We apply auto-making again
494 * at this point to avoid washing out non-binary masking modes like cavity masking. */
495 float automasking = auto_mask.is_empty() ? 1.0f : auto_mask[i];
496 const float4 buffer_color = float4(color_buffer[i]) * alpha * automasking;
497
498 IMB_blend_color_float(new_colors[i], orig_colors[i], buffer_color, IMB_BlendMode(brush.blend));
499 new_colors[i] = math::clamp(new_colors[i], 0.0f, 1.0f);
500 }
501
502 scatter_data_mesh(color_buffer.as_span(), verts, mix_colors);
503
504 for (const int i : verts.index_range()) {
506 corner_verts,
507 vert_to_face_map,
508 color_attribute.domain,
509 verts[i],
510 new_colors[i],
511 color_attribute.span);
512 }
513}
514
519
520static void do_sample_wet_paint_task(const Object &object,
521 const Span<float3> vert_positions,
523 const Span<int> corner_verts,
524 const GroupedSpan<int> vert_to_face_map,
525 const Span<bool> hide_vert,
526 const GSpan color_attribute,
527 const bke::AttrDomain color_domain,
528 const Brush &brush,
529 const bke::pbvh::MeshNode &node,
531 SampleWetPaintData &swptd)
532{
533 const SculptSession &ss = *object.sculpt;
534 const float radius = ss.cache->radius * brush.wet_paint_radius_factor;
535
536 const Span<int> verts = node.verts();
537
538 tls.factors.resize(verts.size());
539 const MutableSpan<float> factors = tls.factors;
540 fill_factor_from_hide(hide_vert, verts, factors);
541
542 tls.distances.resize(verts.size());
543 const MutableSpan<float> distances = tls.distances;
545 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
546 filter_distances_with_radius(radius, distances, factors);
547
548 for (const int i : verts.index_range()) {
549 if (factors[i] > 0.0f) {
550 swptd.color += color_vert_get(
551 faces, corner_verts, vert_to_face_map, color_attribute, color_domain, verts[i]);
552 swptd.tot_samples++;
553 }
554 }
555}
556
557void do_paint_brush(const Scene &scene,
558 const Depsgraph &depsgraph,
559 PaintModeSettings &paint_mode_settings,
560 const Sculpt &sd,
561 Object &ob,
562 const IndexMask &node_mask,
563 const IndexMask &texnode_mask)
564{
565 if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) {
566 SCULPT_do_paint_brush_image(scene, depsgraph, paint_mode_settings, sd, ob, texnode_mask);
567 return;
568 }
569
570 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
571 SculptSession &ss = *ob.sculpt;
574
575 if (!ss.cache->paint_brush.density_seed) {
577 }
578
580 return;
581 }
582
584
585 float4x4 mat;
586
587 /* If the brush is round the tip does not need to be aligned to the surface, so this saves a
588 * whole iteration over the affected nodes. */
589 if (brush.tip_roundness < 1.0f) {
590 SCULPT_cube_tip_init(sd, ob, brush, mat.ptr());
591
592 if (is_zero_m4(mat.ptr())) {
593 return;
594 }
595 }
596
597 Mesh &mesh = *static_cast<Mesh *>(ob.data);
598 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
599 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
600 const OffsetIndices<int> faces = mesh.faces();
601 const Span<int> corner_verts = mesh.corner_verts();
602 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
603 const MeshAttributeData attribute_data(mesh);
605 if (!color_attribute) {
606 return;
607 }
608
609 if (ss.cache->alt_smooth) {
611 node_mask.foreach_index(GrainSize(1), [&](const int i) {
612 ColorPaintLocalData &tls = all_tls.local();
614 ob,
615 vert_positions,
616 vert_normals,
617 faces,
618 corner_verts,
619 vert_to_face_map,
620 attribute_data,
621 brush,
622 nodes[i],
623 tls,
624 color_attribute);
625 });
626 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
627 color_attribute.finish();
628 return;
629 }
630
631 /* Regular Paint mode. */
632
633 /* Wet paint color sampling. */
634 float4 wet_color(0);
635 if (ss.cache->paint_brush.wet_mix > 0.0f) {
638 node_mask.index_range(),
639 1,
641 [&](const IndexRange range, SampleWetPaintData swptd) {
642 ColorPaintLocalData &tls = all_tls.local();
643 node_mask.slice(range).foreach_index([&](const int i) {
644 do_sample_wet_paint_task(ob,
645 vert_positions,
646 faces,
647 corner_verts,
648 vert_to_face_map,
649 attribute_data.hide_vert,
650 color_attribute.span,
651 color_attribute.domain,
652 brush,
653 nodes[i],
654 tls,
655 swptd);
656 });
657 return swptd;
658 },
659 [](const SampleWetPaintData &a, const SampleWetPaintData &b) {
660 SampleWetPaintData joined{};
661 joined.color = a.color + b.color;
662 joined.tot_samples = a.tot_samples + b.tot_samples;
663 return joined;
664 });
665
666 if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) {
667 wet_color = math::clamp(swptd.color / float(swptd.tot_samples), 0.0f, 1.0f);
668
669 if (ss.cache->first_time) {
670 ss.cache->paint_brush.wet_mix_prev_color = wet_color;
671 }
673 wet_color,
676 ss.cache->paint_brush.wet_mix_prev_color = math::clamp(wet_color, 0.0f, 1.0f);
677 }
678 }
679
680 if (ss.cache->paint_brush.mix_colors.is_empty()) {
681 ss.cache->paint_brush.mix_colors = Array<float4>(mesh.verts_num, float4(0));
682 }
683
685 node_mask.foreach_index(GrainSize(1), [&](const int i) {
686 ColorPaintLocalData &tls = all_tls.local();
687 do_paint_brush_task(scene,
688 depsgraph,
689 ob,
690 vert_positions,
691 vert_normals,
692 faces,
693 corner_verts,
694 vert_to_face_map,
695 attribute_data,
696 sd.paint,
697 brush,
698 mat,
699 wet_color,
700 nodes[i],
701 tls,
702 ss.cache->paint_brush.mix_colors,
703 color_attribute);
704 });
705 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
706 color_attribute.finish();
707}
708
709static void do_smear_brush_task(const Depsgraph &depsgraph,
710 Object &object,
711 const Span<float3> vert_positions,
712 const Span<float3> vert_normals,
714 const Span<int> corner_verts,
715 const GroupedSpan<int> vert_to_face_map,
716 const MeshAttributeData &attribute_data,
717 const Brush &brush,
720 bke::GSpanAttributeWriter &color_attribute)
721{
722 const SculptSession &ss = *object.sculpt;
723 const StrokeCache &cache = *ss.cache;
724 const float strength = ss.cache->bstrength;
725
726 const Span<int> verts = node.verts();
727
728 tls.factors.resize(verts.size());
729 const MutableSpan<float> factors = tls.factors;
730 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
731 filter_region_clip_factors(ss, vert_positions, verts, factors);
732 if (brush.flag & BRUSH_FRONTFACE) {
733 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
734 }
735
736 tls.distances.resize(verts.size());
737 const MutableSpan<float> distances = tls.distances;
739 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
740 filter_distances_with_radius(cache.radius, distances, factors);
741 apply_hardness_to_distances(cache, distances);
742 calc_brush_strength_factors(cache, brush, distances, factors);
743
744 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
745
746 calc_brush_texture_factors(ss, brush, vert_positions, verts, factors);
747 scale_factors(factors, strength);
748
749 float3 brush_delta;
750 if (brush.flag & BRUSH_ANCHORED) {
751 brush_delta = ss.cache->grab_delta_symm;
752 }
753 else {
754 brush_delta = ss.cache->location_symm - ss.cache->last_location_symm;
755 }
756
757 Vector<int> neighbors;
758 Vector<int> neighbor_neighbors;
759
760 for (const int i : verts.index_range()) {
761 if (factors[i] == 0.0f) {
762 continue;
763 }
764 const int vert = verts[i];
765 const float3 &no = vert_normals[vert];
766
767 float3 current_disp;
768 switch (brush.smear_deform_type) {
770 current_disp = brush_delta;
771 break;
773 current_disp = ss.cache->location_symm - vert_positions[vert];
774 break;
776 current_disp = vert_positions[vert] - ss.cache->location_symm;
777 break;
778 }
779
780 /* Project into vertex plane. */
781 current_disp += no * -math::dot(current_disp, no);
782
783 const float3 current_disp_norm = math::normalize(current_disp);
784
785 current_disp = current_disp_norm * strength;
786
787 float4 accum(0);
788 float totw = 0.0f;
789
790 /*
791 * NOTE: we have to do a nested iteration here to avoid
792 * blocky artifacts on quad topologies. The runtime cost
793 * is not as bad as it seems due to neighbor iteration
794 * in the sculpt code being cache bound; once the data is in
795 * the cache iterating over it a few more times is not terribly
796 * costly.
797 */
798
799 for (const int neighbor : vert_neighbors_get_mesh(
800 faces, corner_verts, vert_to_face_map, attribute_data.hide_poly, vert, neighbors))
801 {
802 const float3 &nco = vert_positions[neighbor];
803 for (const int neighbor_neighbor : vert_neighbors_get_mesh(faces,
804 corner_verts,
805 vert_to_face_map,
806 attribute_data.hide_poly,
807 neighbor,
808 neighbor_neighbors))
809 {
810 if (neighbor_neighbor == vert) {
811 continue;
812 }
813
814 float3 vert_disp = vert_positions[neighbor_neighbor] - vert_positions[vert];
815
816 /* Weight by how close we are to our target distance from vd.co. */
817 float w = (1.0f + fabsf(math::length(vert_disp) / strength - 1.0f));
818
819 /* TODO: use cotangents (or at least face areas) here. */
820 float len = math::distance(vert_positions[neighbor_neighbor], nco);
821 if (len > 0.0f) {
822 len = strength / len;
823 }
824 else { /* Coincident point. */
825 len = 1.0f;
826 }
827
828 /* Multiply weight with edge lengths (in the future this will be
829 * cotangent weights or face areas). */
830 w *= len;
831
832 /* Build directional weight. */
833
834 /* Project into vertex plane. */
835 vert_disp += no * -math::dot(no, vert_disp);
836 const float3 vert_disp_norm = math::normalize(vert_disp);
837
838 if (math::dot(current_disp_norm, vert_disp_norm) >= 0.0f) {
839 continue;
840 }
841
842 const float4 &neighbor_color = ss.cache->paint_brush.prev_colors[neighbor_neighbor];
843 float color_interp = -math::dot(current_disp_norm, vert_disp_norm);
844
845 /* Square directional weight to get a somewhat sharper result. */
846 w *= color_interp * color_interp;
847
848 accum += neighbor_color * w;
849 totw += w;
850 }
851 }
852
853 if (totw != 0.0f) {
854 accum /= totw;
855 }
856
858 faces, corner_verts, vert_to_face_map, color_attribute.span, color_attribute.domain, vert);
859 blend_color_interpolate_float(col, ss.cache->paint_brush.prev_colors[vert], accum, factors[i]);
861 corner_verts,
862 vert_to_face_map,
863 color_attribute.domain,
864 vert,
865 col,
866 color_attribute.span);
867 }
868}
869
870void do_smear_brush(const Depsgraph &depsgraph,
871 const Sculpt &sd,
872 Object &ob,
873 const IndexMask &node_mask)
874{
875 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
876 SculptSession &ss = *ob.sculpt;
879
880 Mesh &mesh = *static_cast<Mesh *>(ob.data);
881 if (ss.cache->bstrength == 0.0f) {
882 return;
883 }
884
885 const OffsetIndices<int> faces = mesh.faces();
886 const Span<int> corner_verts = mesh.corner_verts();
887 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
888 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
889 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
890 const MeshAttributeData attribute_data(mesh);
891
893 if (!color_attribute) {
894 return;
895 }
896
897 if (ss.cache->paint_brush.prev_colors.is_empty()) {
899 threading::parallel_for(IndexRange(mesh.verts_num), 1024, [&](const IndexRange range) {
900 for (const int vert : range) {
901 ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces,
902 corner_verts,
903 vert_to_face_map,
904 color_attribute.span,
905 color_attribute.domain,
906 vert);
907 }
908 });
909 }
910
911 BKE_curvemapping_init(brush.curve);
912
913 /* Smooth colors mode. */
914 if (ss.cache->alt_smooth) {
916 node_mask.foreach_index(GrainSize(1), [&](const int i) {
917 ColorPaintLocalData &tls = all_tls.local();
918 do_color_smooth_task(depsgraph,
919 ob,
920 vert_positions,
921 vert_normals,
922 faces,
923 corner_verts,
924 vert_to_face_map,
925 attribute_data,
926 brush,
927 nodes[i],
928 tls,
929 color_attribute);
930 });
931 }
932 else {
933 /* Smear mode. */
934 node_mask.foreach_index(GrainSize(1), [&](const int i) {
935 for (const int vert : nodes[i].verts()) {
936 ss.cache->paint_brush.prev_colors[vert] = color_vert_get(faces,
937 corner_verts,
938 vert_to_face_map,
939 color_attribute.span,
940 color_attribute.domain,
941 vert);
942 }
943 });
944 threading::EnumerableThreadSpecific<ColorPaintLocalData> all_tls;
945 node_mask.foreach_index(GrainSize(1), [&](const int i) {
946 ColorPaintLocalData &tls = all_tls.local();
948 ob,
949 vert_positions,
950 vert_normals,
951 faces,
952 corner_verts,
953 vert_to_face_map,
954 attribute_data,
955 brush,
956 nodes[i],
957 tls,
958 color_attribute);
959 });
960 }
961 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
962 color_attribute.finish();
963}
964
965} // namespace blender::ed::sculpt_paint::color
#define ATTR_DOMAIN_MASK_COLOR
#define ATTR_DOMAIN_AS_MASK(domain)
const float * BKE_brush_secondary_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1172
const std::optional< BrushColorJitterSettings > BKE_brush_color_jitter_get_settings(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1137
float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1269
const float * BKE_brush_color_get(const Scene *scene, const Paint *paint, const Brush *brush)
Definition brush.cc:1128
void BKE_brush_calc_curve_factors(eBrushCurvePreset preset, const CurveMapping *cumap, blender::Span< float > distances, float brush_radius, blender::MutableSpan< float > factors)
Definition brush.cc:1381
bool BKE_colorband_evaluate(const ColorBand *coba, float in, float out[4])
Definition colorband.cc:395
void BKE_curvemapping_init(CurveMapping *cumap)
CustomData interface, see also DNA_customdata_types.h.
#define CD_TYPE_AS_MASK(_type)
blender::float3 BKE_paint_randomize_color(const BrushColorJitterSettings &color_jitter, const blender::float3 &initial_hsv_jitter, const float distance, const float pressure, const blender::float3 &color)
Definition paint.cc:1853
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:641
A BVH for high poly meshes.
#define BLI_assert(a)
Definition BLI_assert.h:46
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition BLI_hash.h:92
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
bool is_zero_m4(const float mat[4][4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE bool is_finite_v4(const float v[4]) ATTR_WARN_UNUSED_RESULT
unsigned char uchar
eBrushCurvePreset
@ BRUSH_SMEAR_DEFORM_PINCH
@ BRUSH_SMEAR_DEFORM_EXPAND
@ BRUSH_SMEAR_DEFORM_DRAG
@ BRUSH_FRONTFACE
@ BRUSH_ANCHORED
@ BRUSH_USE_GRADIENT
@ BRUSH_GRADIENT_SPACING_CLAMP
@ BRUSH_GRADIENT_PRESSURE
@ BRUSH_GRADIENT_SPACING_REPEAT
eBrushFalloffShape
struct MLoopCol MLoopCol
struct MPropCol MPropCol
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
IMB_BlendMode
Definition IMB_imbuf.hh:185
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition rectop.cc:117
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
static unsigned long seed
Definition btSoftBody.h:39
void resize(const int64_t new_size)
bool is() const
const CPPType & type() const
const CPPType & type() const
const void * data() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr Span< T > as_span() const
Definition BLI_span.hh:661
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:137
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Definition pbvh.cc:600
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
#define fabsf(x)
static ushort indices[]
static float verts[][3]
uint col
VecBase< float, 4 > float4
#define CD_MASK_COLOR_ALL
ccl_device_inline float2 fmod(const float2 a, const float b)
#define T
static char faces[256]
int face_find_corner_from_vert(const IndexRange face, const Span< int > corner_verts, const int vert)
Definition BKE_mesh.hh:311
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2912
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2435
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2416
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh)
static void do_paint_brush_task(const Scene &scene, const Depsgraph &depsgraph, Object &object, const Span< float3 > vert_positions, const Span< float3 > vert_normals, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const Paint &paint, const Brush &brush, const float4x4 &mat, const float4 wet_mix_sampled_color, bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, const MutableSpan< float4 > mix_colors, bke::GSpanAttributeWriter &color_attribute)
void gather_colors_vert(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, GSpan color_attribute, bke::AttrDomain color_domain, Span< int > verts, MutableSpan< float4 > r_colors)
void do_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
float4 color_vert_get(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, GSpan color_attribute, bke::AttrDomain color_domain, int vert)
static void do_sample_wet_paint_task(const Object &object, const Span< float3 > vert_positions, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_vert, const GSpan color_attribute, const bke::AttrDomain color_domain, const Brush &brush, const bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, SampleWetPaintData &swptd)
void gather_colors(GSpan color_attribute, Span< int > indices, MutableSpan< float4 > r_colors)
void color_vert_set(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, bke::AttrDomain color_domain, int vert, const float4 &color, GMutableSpan color_attribute)
void swap_gathered_colors(Span< int > indices, GMutableSpan color_attribute, MutableSpan< float4 > r_colors)
void do_paint_brush(const Scene &scene, const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, const IndexMask &node_mask, const IndexMask &texnode_mask)
void from_float(const float4 &src, T &dst)
static void do_smear_brush_task(const Depsgraph &depsgraph, Object &object, const Span< float3 > vert_positions, const Span< float3 > vert_normals, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const Brush &brush, bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, bke::GSpanAttributeWriter &color_attribute)
bke::GAttributeReader active_color_attribute(const Mesh &mesh)
void to_static_color_type(const CPPType &type, const Func &func)
static void do_color_smooth_task(const Depsgraph &depsgraph, const Object &object, const Span< float3 > vert_positions, const Span< float3 > vert_normals, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const Brush &brush, const bke::pbvh::MeshNode &node, ColorPaintLocalData &tls, bke::GSpanAttributeWriter &color_attribute)
static void calc_local_positions(const float4x4 &mat, const Span< int > verts, const Span< float3 > positions, const MutableSpan< float3 > local_positions)
float4 to_float(const T &src)
void neighbor_color_average(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const GSpan color_attribute, const bke::AttrDomain color_domain, const GroupedSpan< int > vert_neighbors, const MutableSpan< float4 > smooth_colors)
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6807
void calc_brush_strength_factors(const StrokeCache &cache, const Brush &brush, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7167
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:7140
GroupedSpan< int > calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, Vector< int > &r_offset_data, Vector< int > &r_data)
Definition sculpt.cc:7596
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7089
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6956
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7493
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6419
Span< float4 > orig_color_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void calc_brush_distances(const SculptSession &ss, Span< float3 > vert_positions, Span< int > vert, eBrushFalloffShape falloff_shape, MutableSpan< float > r_distances)
Definition sculpt.cc:7039
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6379
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert, MutableSpan< float > factors)
Definition sculpt.cc:7176
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6898
void calc_brush_cube_distances(const Brush &brush, const Span< T > positions, const MutableSpan< float > r_distances)
Definition sculpt.cc:7101
Span< int > vert_neighbors_get_mesh(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face, const Span< bool > hide_poly, const int vert, Vector< int > &r_neighbors)
Definition sculpt.cc:430
void fill_factor_from_hide(Span< bool > hide_vert, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6759
T clamp(const T &a, const T &min, const T &max)
T distance(const T &a, const T &b)
T length(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
Definition BLI_color.hh:342
VecBase< float, 3 > float3
ColorSceneLinearByteEncoded4b< eAlpha::Premultiplied > ColorGeometry4b
Definition BLI_color.hh:343
static void to_static_color_type(const eCustomDataType type, const Func &func)
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:543
void SCULPT_cube_tip_init(const Sculpt &, const Object &ob, const Brush &brush, float mat[4][4])
Definition sculpt.cc:6312
void SCULPT_do_paint_brush_image(const Scene &scene, const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, const blender::IndexMask &node_mask)
bool SCULPT_use_image_paint_brush(PaintModeSettings &settings, Object &ob)
struct ColorBand * gradient
float wet_paint_radius_factor
int curve_preset
struct CurveMapping * curve
char falloff_shape
short blend
char gradient_stroke_mode
int gradient_spacing
int smear_deform_type
float tip_roundness
struct SculptSession * sculpt
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:437
const c_style_mat & ptr() const
std::unique_ptr< auto_mask::Cache > automasking
std::optional< blender::float3 > initial_hsv_jitter
struct blender::ed::sculpt_paint::StrokeCache::@041260147022120342012126303054022276247065002140 paint_brush
i
Definition text_draw.cc:230
uint len