68 {
int(FilterType::Fill),
"FILL", 0,
"Fill",
"Fill with a specific color"},
69 {
int(FilterType::Hue),
"HUE", 0,
"Hue",
"Change hue"},
70 {
int(FilterType::Saturation),
"SATURATION", 0,
"Saturation",
"Change saturation"},
71 {
int(FilterType::Value),
"VALUE", 0,
"Value",
"Change value"},
72 {
int(FilterType::Brightness),
"BRIGHTNESS", 0,
"Brightness",
"Change brightness"},
73 {
int(FilterType::Contrast),
"CONTRAST", 0,
"Contrast",
"Change contrast"},
74 {
int(FilterType::Smooth),
"SMOOTH", 0,
"Smooth",
"Smooth colors"},
75 {
int(FilterType::Red),
"RED", 0,
"Red",
"Change red channel"},
76 {
int(FilterType::Green),
"GREEN", 0,
"Green",
"Change green channel"},
77 {
int(FilterType::Blue),
"BLUE", 0,
"Blue",
"Change blue channel"},
78 {0,
nullptr, 0,
nullptr,
nullptr},
93 for (
float &factor : factors) {
94 factor = std::clamp(factor,
min,
max);
105 const float filter_strength,
106 const float *filter_fill_color,
128 for (
const int i :
verts.index_range()) {
129 new_colors[i][3] = orig_colors[i][3];
133 case FilterType::Fill: {
135 for (
const int i :
verts.index_range()) {
136 float fill_color_rgba[4];
137 copy_v3_v3(fill_color_rgba, filter_fill_color);
138 fill_color_rgba[3] = 1.0f;
144 case FilterType::Hue: {
145 for (
const int i :
verts.index_range()) {
148 const float hue = hsv_color[0];
149 hsv_color[0] =
fmod((hsv_color[0] +
fabs(factors[i])) -
hue, 1);
154 case FilterType::Saturation: {
155 for (
const int i :
verts.index_range()) {
159 if (hsv_color[1] > 0.001f) {
160 hsv_color[1] = std::clamp(hsv_color[1] + factors[i] * hsv_color[1], 0.0f, 1.0f);
169 case FilterType::Value: {
170 for (
const int i :
verts.index_range()) {
173 hsv_color[2] = std::clamp(hsv_color[2] + factors[i], 0.0f, 1.0f);
178 case FilterType::Red: {
179 for (
const int i :
verts.index_range()) {
181 new_colors[i][0] = std::clamp(orig_colors[i][0] + factors[i], 0.0f, 1.0f);
185 case FilterType::Green: {
186 for (
const int i :
verts.index_range()) {
188 new_colors[i][1] = std::clamp(orig_colors[i][1] + factors[i], 0.0f, 1.0f);
192 case FilterType::Blue: {
193 for (
const int i :
verts.index_range()) {
195 new_colors[i][2] = std::clamp(orig_colors[i][2] + factors[i], 0.0f, 1.0f);
199 case FilterType::Brightness: {
201 for (
const int i :
verts.index_range()) {
202 const float brightness = factors[i];
203 const float contrast = 0;
204 float delta = contrast / 2.0f;
205 const float gain = 1.0f - delta * 2.0f;
207 const float offset = gain * (brightness + delta);
208 for (
int component = 0; component < 3; component++) {
209 new_colors[i][component] = std::clamp(
210 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
215 case FilterType::Contrast: {
217 for (
const int i :
verts.index_range()) {
218 const float brightness = 0;
219 const float contrast = factors[i];
220 float delta = contrast / 2.0f;
221 float gain = 1.0f - delta * 2.0f;
225 gain = 1.0f / ((gain != 0.0f) ? gain : FLT_EPSILON);
226 offset = gain * (brightness - delta);
230 offset = gain * (brightness + delta);
232 for (
int component = 0; component < 3; component++) {
233 new_colors[i][component] = std::clamp(
234 gain * orig_colors[i][component] + offset, 0.0f, 1.0f);
239 case FilterType::Smooth: {
244 for (
const int i :
verts.index_range()) {
248 color_attribute.
span,
262 color_attribute.
span,
267 for (
const int i :
verts.index_range()) {
268 const int vert =
verts[i];
270 if (factors[i] < 0.0f) {
271 interp_v4_v4v4(average_colors[i], average_colors[i], colors[i], 0.5f);
274 bool copy_alpha = colors[i][3] == average_colors[i][3];
276 if (factors[i] < 0.0f) {
277 float delta_color[4];
281 sub_v4_v4(delta_color, average_colors[i]);
290 new_colors[i] =
math::clamp(new_colors[i], 0.0f, 1.0f);
294 new_colors[i][3] = average_colors[i][3];
301 for (
const int i :
verts.index_range()) {
308 color_attribute.
span);
329 node_mask.foreach_index(
GrainSize(1), [&](
const int i) {
332 faces, corner_verts, vert_to_face_map, colors, color_attribute.
domain, vert);
341 for ([[maybe_unused]]
const int iteration :
IndexRange(2)) {
342 node_mask.foreach_index(
GrainSize(1), [&](
const int i) {
350 tls.averaged_colors.resize(
verts.size());
353 pre_smoothed_color.
as_span(), vert_neighbors, averaged_colors);
355 for (
const int i :
verts.index_range()) {
357 pre_smoothed_color[
verts[i]], averaged_colors[i], 0.5f);
378 if (filter_strength < 0.0 && ss.filter_cache->pre_smoothed_color.is_empty()) {
435 const float len = (
event->prev_press_xy[0] -
event->xy[0]) * 0.001f;
459 float mval_fl[2] = {
float(mval[0]),
float(mval[1])};
462 if (use_automasking) {
536 const char *ui_name =
nullptr;
556 ot->name =
"Filter Color";
557 ot->idname =
"SCULPT_OT_color_filter";
558 ot->description =
"Applies a filter to modify the active color attribute";
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
#define SCULPT_FACE_SET_NONE
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
void BKE_sculpt_color_layer_create_if_needed(Object *object)
A BVH for high poly meshes.
void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
void rgb_to_hsv_v(const float rgb[3], float r_hsv[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)
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v4_v4v4(float r[4], const float a[4], const float b[4], float t)
MINLINE void sub_v4_v4(float r[4], const float a[4])
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
#define BLT_I18NCONTEXT_ID_MESH
@ V3D_SHADING_VERTEX_COLOR
void ED_image_paint_brush_type_update_sticky_shading_color(bContext *C, Object *ob)
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its hue
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
BPy_StructRNA * depsgraph
void resize(const int64_t new_size)
constexpr Span< T > as_span() const
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_device_inline float2 fmod(const float2 a, const float b)
ccl_device_inline float2 fabs(const float2 a)
pbvh::Tree * pbvh_get(Object &object)
std::unique_ptr< Cache > cache_init(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh)
static std::string sculpt_color_filter_get_name(wmOperatorType *, PointerRNA *ptr)
static const float fill_filter_default_color[4]
static void color_filter_task(const Depsgraph &depsgraph, Object &ob, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const FilterType mode, const float filter_strength, const float *filter_fill_color, const bke::pbvh::MeshNode &node, LocalData &tls, bke::GSpanAttributeWriter &color_attribute)
static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static BLI_NOINLINE void clamp_factors(const MutableSpan< float > factors, const float min, const float max)
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)
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)
static int sculpt_color_filter_init(bContext *C, wmOperator *op)
void SCULPT_OT_color_filter(wmOperatorType *ot)
static int sculpt_color_filter_exec(bContext *C, wmOperator *op)
bke::GAttributeReader active_color_attribute(const Mesh &mesh)
static void sculpt_color_presmooth_init(const Mesh &mesh, Object &object)
static void sculpt_color_filter_end(bContext *C, Object &ob)
static void sculpt_color_filter_apply(bContext *C, wmOperator *op, Object &ob)
static void sculpt_color_filter_ui(bContext *, wmOperator *op)
static EnumPropertyItem prop_color_filter_types[]
static int sculpt_color_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
void cache_init(bContext *C, Object &ob, const Sculpt &sd, undo::Type undo_type, const float mval_fl[2], float area_normal_radius, float start_strength)
void register_operator_props(wmOperatorType *ot)
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 Span< Vector< int > > vert_neighbors, const MutableSpan< float4 > smooth_colors)
void neighbor_data_average_mesh(const Span< T > src, const Span< Vector< int > > vert_neighbors, const MutableSpan< T > dst)
void push_end(Object &ob)
void push_begin(const Scene &scene, Object &ob, const wmOperator *op)
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
void flush_update_step(bContext *C, UpdateType update_type)
void scale_factors(MutableSpan< float > factors, float strength)
Span< float4 > orig_color_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
T clamp(const T &a, const T &min, const T &max)
T interpolate(const T &a, const T &b, const FactorT &t)
VecBase< float, 3 > float3
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
bool RNA_property_enum_name_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **r_name)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_property_enum_get(PointerRNA *ptr, PropertyRNA *prop)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_float_color(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_translation_context(PropertyRNA *prop, const char *context)
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
bool SCULPT_mode_poll(bContext *C)
bool SCULPT_handles_colors_report(const Object &object, ReportList *reports)
struct SculptSession * sculpt
blender::ed::sculpt_paint::filter::Cache * filter_cache
Span< int > verts() const
VArraySpan< bool > hide_vert
Vector< float4 > new_colors
Vector< float4 > average_colors
Vector< Vector< int > > vert_neighbors
float start_filter_strength
std::unique_ptr< auto_mask::Cache > automasking
Array< float4 > pre_smoothed_color
struct ReportList * reports
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)