Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt_paint_image.cc
| Show First 20 Lines • Show All 112 Lines • ▼ Show 20 Lines | public: | ||||
| } | } | ||||
| const char *get_colorspace_name(ImBuf *image_buffer) | const char *get_colorspace_name(ImBuf *image_buffer) | ||||
| { | { | ||||
| return IMB_colormanagement_get_rect_colorspace(image_buffer); | return IMB_colormanagement_get_rect_colorspace(image_buffer); | ||||
| } | } | ||||
| }; | }; | ||||
| static float paint_automasking_interp(SculptSession *ss, | |||||
| const UVPrimitivePaintInput &prim, | |||||
| const float2 uv) | |||||
| { | |||||
| if (!ss->cache->automasking) { | |||||
| return 1.0f; | |||||
| } | |||||
| PBVHData &pbvh_data = BKE_pbvh_pixels_data_get(*ss->pbvh); | |||||
| AutomaskingNodeData automask_data = {}; | |||||
| automask_data.have_orig_data = false; | |||||
| automask_data.initializing = false; | |||||
| PBVHVertRef v1, v2, v3; | |||||
| /* Not sure we need to use BKE_pbvh_index_to_vertex if texture paint | |||||
| * only works in PBVH_FACES, at least for now. | |||||
| */ | |||||
jbakker: Remove commented out code. | |||||
| BLI_assert(BKE_pbvh_type(ss->pbvh) == PBVH_FACES); | |||||
| int3 &tri = pbvh_data.geom_primitives.vert_indices[prim.geometry_primitive_index]; | |||||
| v1.i = tri[0]; | |||||
| v2.i = tri[1]; | |||||
| v3.i = tri[2]; | |||||
| float a = SCULPT_automasking_factor_get(ss->cache->automasking, ss, v1, &automask_data); | |||||
| float b = SCULPT_automasking_factor_get(ss->cache->automasking, ss, v2, &automask_data); | |||||
| float c = SCULPT_automasking_factor_get(ss->cache->automasking, ss, v3, &automask_data); | |||||
| return a * uv[0] + b * uv[1] + c * (1.0 - uv[0] - uv[1]); | |||||
| } | |||||
| template<typename ImageBuffer> class PaintingKernel { | template<typename ImageBuffer> class PaintingKernel { | ||||
| ImageBuffer image_accessor; | ImageBuffer image_accessor; | ||||
| SculptSession *ss; | SculptSession *ss; | ||||
| const Brush *brush; | const Brush *brush; | ||||
| const int thread_id; | const int thread_id; | ||||
| const float3 *vert_positions_; | const float3 *vert_positions_; | ||||
| Show All 28 Lines | public: | ||||
| { | { | ||||
| image_accessor.set_image_position(image_buffer, pixel_row.start_image_coordinate); | image_accessor.set_image_position(image_buffer, pixel_row.start_image_coordinate); | ||||
| const UVPrimitivePaintInput paint_input = uv_primitives.get_paint_input( | const UVPrimitivePaintInput paint_input = uv_primitives.get_paint_input( | ||||
| pixel_row.uv_primitive_index); | pixel_row.uv_primitive_index); | ||||
| float3 pixel_pos = get_start_pixel_pos(geom_primitives, paint_input, pixel_row); | float3 pixel_pos = get_start_pixel_pos(geom_primitives, paint_input, pixel_row); | ||||
| const float3 delta_pixel_pos = get_delta_pixel_pos( | const float3 delta_pixel_pos = get_delta_pixel_pos( | ||||
| geom_primitives, paint_input, pixel_row, pixel_pos); | geom_primitives, paint_input, pixel_row, pixel_pos); | ||||
| bool pixels_painted = false; | bool pixels_painted = false; | ||||
| float2 uv = pixel_row.start_barycentric_coord; | |||||
| for (int x = 0; x < pixel_row.num_pixels; x++) { | for (int x = 0; x < pixel_row.num_pixels; x++) { | ||||
| if (!brush_test_fn(&test, pixel_pos)) { | if (!brush_test_fn(&test, pixel_pos)) { | ||||
| pixel_pos += delta_pixel_pos; | pixel_pos += delta_pixel_pos; | ||||
| uv += paint_input.delta_barycentric_coord_u; | |||||
| image_accessor.next_pixel(); | image_accessor.next_pixel(); | ||||
| continue; | continue; | ||||
| } | } | ||||
| float4 color = image_accessor.read_pixel(image_buffer); | float4 color = image_accessor.read_pixel(image_buffer); | ||||
| const float3 normal(0.0f, 0.0f, 0.0f); | const float3 normal(0.0f, 0.0f, 0.0f); | ||||
| const float3 face_normal(0.0f, 0.0f, 0.0f); | const float3 face_normal(0.0f, 0.0f, 0.0f); | ||||
| const float mask = 0.0f; | const float mask = 0.0f; | ||||
| const float falloff_strength = SCULPT_brush_strength_factor( | float falloff_strength = SCULPT_brush_strength_factor(ss, | ||||
| ss, | |||||
| brush, | brush, | ||||
| pixel_pos, | pixel_pos, | ||||
| sqrtf(test.dist), | sqrtf(test.dist), | ||||
| normal, | normal, | ||||
| face_normal, | face_normal, | ||||
| mask, | mask, | ||||
| BKE_pbvh_make_vref(PBVH_REF_NONE), | BKE_pbvh_make_vref(PBVH_REF_NONE), | ||||
| thread_id, | thread_id, | ||||
| automask_data); | automask_data); | ||||
| falloff_strength *= paint_automasking_interp(ss, paint_input, uv); | |||||
| float4 paint_color = brush_color * falloff_strength * brush_strength; | float4 paint_color = brush_color * falloff_strength * brush_strength; | ||||
| float4 buffer_color; | float4 buffer_color; | ||||
| blend_color_mix_float(buffer_color, color, paint_color); | blend_color_mix_float(buffer_color, color, paint_color); | ||||
| buffer_color *= brush->alpha; | buffer_color *= brush->alpha; | ||||
| IMB_blend_color_float(color, color, buffer_color, static_cast<IMB_BlendMode>(brush->blend)); | IMB_blend_color_float(color, color, buffer_color, static_cast<IMB_BlendMode>(brush->blend)); | ||||
| image_accessor.write_pixel(image_buffer, color); | image_accessor.write_pixel(image_buffer, color); | ||||
| pixels_painted = true; | pixels_painted = true; | ||||
| image_accessor.next_pixel(); | image_accessor.next_pixel(); | ||||
| pixel_pos += delta_pixel_pos; | pixel_pos += delta_pixel_pos; | ||||
| uv += paint_input.delta_barycentric_coord_u; | |||||
| } | } | ||||
| return pixels_painted; | return pixels_painted; | ||||
| } | } | ||||
| void init_brush_color(ImBuf *image_buffer) | void init_brush_color(ImBuf *image_buffer) | ||||
| { | { | ||||
| const char *to_colorspace = image_accessor.get_colorspace_name(image_buffer); | const char *to_colorspace = image_accessor.get_colorspace_name(image_buffer); | ||||
| if (last_used_color_space == to_colorspace) { | if (last_used_color_space == to_colorspace) { | ||||
| ▲ Show 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | static void do_paint_pixels(void *__restrict userdata, | ||||
| const float(*positions)[3] = SCULPT_mesh_deformed_positions_get(ss); | const float(*positions)[3] = SCULPT_mesh_deformed_positions_get(ss); | ||||
| std::vector<bool> brush_test = init_uv_primitives_brush_test( | std::vector<bool> brush_test = init_uv_primitives_brush_test( | ||||
| ss, pbvh_data.geom_primitives, node_data.uv_primitives, positions); | ss, pbvh_data.geom_primitives, node_data.uv_primitives, positions); | ||||
| PaintingKernel<ImageBufferFloat4> kernel_float4(ss, brush, thread_id, positions); | PaintingKernel<ImageBufferFloat4> kernel_float4(ss, brush, thread_id, positions); | ||||
| PaintingKernel<ImageBufferByte4> kernel_byte4(ss, brush, thread_id, positions); | PaintingKernel<ImageBufferByte4> kernel_byte4(ss, brush, thread_id, positions); | ||||
| AutomaskingNodeData automask_data; | AutomaskingNodeData automask_data = {0}; | ||||
| SCULPT_automasking_node_begin(ob, ss, ss->cache->automasking, &automask_data, data->nodes[n]); | automask_data.have_orig_data = false; | ||||
| ImageUser image_user = *data->image_data.image_user; | ImageUser image_user = *data->image_data.image_user; | ||||
| bool pixels_updated = false; | bool pixels_updated = false; | ||||
| for (UDIMTilePixels &tile_data : node_data.tiles) { | for (UDIMTilePixels &tile_data : node_data.tiles) { | ||||
| LISTBASE_FOREACH (ImageTile *, tile, &data->image_data.image->tiles) { | LISTBASE_FOREACH (ImageTile *, tile, &data->image_data.image->tiles) { | ||||
| ImageTileWrapper image_tile(tile); | ImageTileWrapper image_tile(tile); | ||||
| if (image_tile.get_tile_number() == tile_data.tile_number) { | if (image_tile.get_tile_number() == tile_data.tile_number) { | ||||
| image_user.tile = image_tile.get_tile_number(); | image_user.tile = image_tile.get_tile_number(); | ||||
| ▲ Show 20 Lines • Show All 180 Lines • ▼ Show 20 Lines | void SCULPT_do_paint_brush_image( | ||||
| data.ob = ob; | data.ob = ob; | ||||
| data.brush = brush; | data.brush = brush; | ||||
| data.nodes = nodes; | data.nodes = nodes; | ||||
| if (!ImageData::init_active_image(ob, &data.image_data, paint_mode_settings)) { | if (!ImageData::init_active_image(ob, &data.image_data, paint_mode_settings)) { | ||||
| return; | return; | ||||
| } | } | ||||
| SCULPT_automasking_cache_check(ob, ob->sculpt, ob->sculpt->cache->automasking, nodes, totnode); | |||||
| TaskParallelSettings settings; | TaskParallelSettings settings; | ||||
| BKE_pbvh_parallel_range_settings(&settings, true, totnode); | BKE_pbvh_parallel_range_settings(&settings, true, totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings); | BLI_task_parallel_range(0, totnode, &data, do_push_undo_tile, &settings); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_paint_pixels, &settings); | BLI_task_parallel_range(0, totnode, &data, do_paint_pixels, &settings); | ||||
| TaskParallelSettings settings_flush; | TaskParallelSettings settings_flush; | ||||
| BKE_pbvh_parallel_range_settings(&settings_flush, false, totnode); | BKE_pbvh_parallel_range_settings(&settings_flush, false, totnode); | ||||
| BLI_task_parallel_range(0, totnode, &data, do_mark_dirty_regions, &settings_flush); | BLI_task_parallel_range(0, totnode, &data, do_mark_dirty_regions, &settings_flush); | ||||
| } | } | ||||
| } | } | ||||
Remove commented out code.