diff options
author | Jeroen Bakker <jeroen@blender.org> | 2022-03-07 17:23:30 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2022-03-07 17:23:30 +0300 |
commit | 4cbeae12fd7d2da0144674548c589b8bb3dc736e (patch) | |
tree | 02a40ac36ede1713a09b1e22dc6242d3309c84e9 | |
parent | b522eb820707a601c747b47eaf0f4d711611ba34 (diff) |
Texture painting second experiment.
-rw-r--r-- | source/blender/blenkernel/BKE_pbvh.h | 17 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 30 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt.c | 11 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_texture_paint_a.cc | 5 | ||||
-rw-r--r-- | source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc | 315 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_rasterizer.hh | 5 | ||||
-rw-r--r-- | source/blender/imbuf/intern/rasterizer_target.hh | 11 |
10 files changed, 314 insertions, 85 deletions
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 6c8880fea7c..9078db149f2 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -46,6 +46,12 @@ typedef struct { float (*color)[4]; } PBVHColorBufferNode; +typedef void (*PBVHNodeTexturePaintDataFreeFunc)(void *ptr); +typedef struct PBVHTexturePaintingNode { + void *data; + PBVHNodeTexturePaintDataFreeFunc free_func; +} PBVHTexturePaintingNode; + typedef enum { PBVH_Leaf = 1 << 0, @@ -416,7 +422,7 @@ BLI_INLINE struct BMVert *PBVH_cast_bmvert(void *src) } BLI_INLINE float *PBVH_cast_float_ptr(void *src) { - return static_cast<float*>(src); + return static_cast<float *>(src); } #else BLI_INLINE struct BMVert *PBVH_cast_bmvert(void *src) @@ -501,7 +507,8 @@ void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int m vi.co = vi.bm_vert->co; \ vi.fno = vi.bm_vert->no; \ vi.index = BM_elem_index_get(vi.bm_vert); \ - vi.mask = PBVH_cast_float_ptr(BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset)); \ + vi.mask = PBVH_cast_float_ptr( \ + BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset)); \ } #define BKE_pbvh_vertex_iter_end \ @@ -547,6 +554,12 @@ const float (*BKE_pbvh_get_vert_normals(const PBVH *pbvh))[3]; PBVHColorBufferNode *BKE_pbvh_node_color_buffer_get(PBVHNode *node); void BKE_pbvh_node_color_buffer_free(PBVH *pbvh); +/* Texture painting. */ +void *BKE_pbvh_node_texture_paint_data_get(const PBVHNode *node); +void BKE_pbvh_node_texture_paint_data_set(PBVHNode *node, + void *texture_paint_data, + PBVHNodeTexturePaintDataFreeFunc free_func); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 3ed3c7badc3..3c379aaa411 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -679,6 +679,7 @@ void BKE_pbvh_free(PBVH *pbvh) if (node->bm_other_verts) { BLI_gset_free(node->bm_other_verts, NULL); } + BKE_pbvh_node_texture_paint_data_set(node, NULL, NULL); } } @@ -3072,3 +3073,32 @@ void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide) { pbvh->respect_hide = respect_hide; } + +/* -------------------------------------------------------------------- */ +/** \name Texture painting operations + * \{ */ + +void *BKE_pbvh_node_texture_paint_data_get(const PBVHNode *node) +{ + BLI_assert(node->flag & PBVH_Leaf); + return node->texture_painting.data; +} + +void BKE_pbvh_node_texture_paint_data_set(PBVHNode *node, + void *texture_paint_data, + PBVHNodeTexturePaintDataFreeFunc free_func) +{ + BLI_assert(node->flag & PBVH_Leaf); + + if (node->texture_painting.data != NULL) { + node->texture_painting.free_func(node->texture_painting.data); + node->texture_painting.data = NULL; + node->texture_painting.free_func = NULL; + } + + if (texture_paint_data != NULL) { + BLI_assert(free_func); + node->texture_painting.data = texture_paint_data; + node->texture_painting.free_func = free_func; + } +} diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 123a6b1b829..6b3108e8460 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -93,6 +93,7 @@ struct PBVHNode { /* Used to store the brush color during a stroke and composite it over the original color */ PBVHColorBufferNode color_buffer; + PBVHTexturePaintingNode texture_painting; }; typedef enum { diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 41fdb37a005..55c90214ac1 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -65,7 +65,7 @@ set(SRC sculpt_paint_color.c sculpt_pose.c sculpt_smooth.c - sculpt_texture_paint_a.cc + sculpt_texture_paint_b.cc sculpt_transform.c sculpt_undo.c sculpt_uv.c diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 525e1be5520..f6b334f2175 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5041,6 +5041,14 @@ void SCULPT_flush_update_step(bContext *C, SculptUpdateType update_flags) multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); } + if (update_flags & SCULPT_UPDATE_TEXTURE) { + /* When using the texture paint brush only the texture changes. The Geometry and shading should + * not be touched.*/ + SCULPT_flush_texture_paint(ob); + ED_region_tag_redraw(region); + return; + } + DEG_id_tag_update(&ob->id, ID_RECALC_SHADING); /* Only current viewport matters, slower update for all viewports will @@ -5256,6 +5264,9 @@ static void sculpt_stroke_update_step(bContext *C, else if (ELEM(brush->sculpt_tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)) { SCULPT_flush_update_step(C, SCULPT_UPDATE_COLOR); } + else if (brush->sculpt_tool == SCULPT_TOOL_TEXTURE_PAINT) { + SCULPT_flush_update_step(C, SCULPT_UPDATE_TEXTURE); + } else { SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS); } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index ad4f13fc438..39aaf4d1276 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -43,6 +43,7 @@ typedef enum SculptUpdateType { SCULPT_UPDATE_MASK = 1 << 1, SCULPT_UPDATE_VISIBILITY = 1 << 2, SCULPT_UPDATE_COLOR = 1 << 3, + SCULPT_UPDATE_TEXTURE = 1 << 4, } SculptUpdateType; typedef struct SculptCursorGeometryInfo { @@ -1613,6 +1614,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in /* Paint Brush. */ void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); +void SCULPT_flush_texture_paint(Object *ob); /* Smear Brush. */ void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode); diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_a.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_a.cc index d3e93574c1a..6e643cdd9b1 100644 --- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_a.cc +++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_a.cc @@ -82,7 +82,6 @@ struct TexturePaintingUserData { Object *ob; Brush *brush; PBVHNode **nodes; - Vector<rctf> region_to_update; }; static void do_task_cb_ex(void *__restrict userdata, @@ -204,5 +203,9 @@ void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int BKE_image_release_ibuf(image, image_buffer, lock); ss->mode.texture_paint.drawing_target = nullptr; } + +void SCULPT_flush_texture_paint(Object *UNUSED(ob)) +{ +} } } // namespace blender::ed::sculpt_paint::texture_paint 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 d3e93574c1a..9ad8be1d8e1 100644 --- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc +++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc @@ -37,6 +37,63 @@ namespace blender::ed::sculpt_paint::texture_paint { +struct PixelData { + struct { + bool dirty : 1; + } flags; + int2 pixel_pos; + float3 local_pos; + float4 content; +}; + +struct NodeData { + struct { + bool dirty : 1; + } flags; + + Vector<PixelData> pixels; + rcti dirty_region; + + NodeData() + { + flags.dirty = false; + BLI_rcti_init_minmax(&dirty_region); + } + + void init_pixels(Object *ob, PBVHNode *node, ImBuf *image_buffer); + void flush(ImBuf &image_buffer) + { + flags.dirty = false; + int pixels_flushed = 0; + 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); + pixel.flags.dirty = false; + pixels_flushed += 1; + } + } + printf("%s: %d pixels flushed\n", __func__, pixels_flushed); + } + + void mark_region(Image &image, ImBuf &image_buffer) + { + printf("%s", __func__); + print_rcti_id(&dirty_region); + BKE_image_partial_update_mark_region( + &image, static_cast<ImageTile *>(image.tiles.first), &image_buffer, &dirty_region); + BLI_rcti_init_minmax(&dirty_region); + } + + static void free_func(void *instance) + { + NodeData *node_data = static_cast<NodeData *>(instance); + MEM_delete(node_data); + } +}; + +namespace shaders { + using namespace imbuf::rasterizer; struct VertexInput { @@ -58,66 +115,110 @@ class VertexShader : public AbstractVertexShader<VertexInput, float3> { } }; -class FragmentShader : public AbstractFragmentShader<float3, float4> { +struct FragmentOutput { + float3 local_pos; +}; + +class FragmentShader : public AbstractFragmentShader<float3, FragmentOutput> { public: - float4 color; - const Brush *brush = nullptr; - SculptBrushTest test; - SculptBrushTestFn sculpt_brush_test_sq_fn; + ImBuf *image_buffer; + public: void fragment(const FragmentInputType &input, FragmentOutputType *r_output) override { - copy_v4_v4(*r_output, color); - float strength = sculpt_brush_test_sq_fn(&test, input) ? - BKE_brush_curve_strength(brush, sqrtf(test.dist), test.radius) : - 0.0f; + r_output->local_pos = input; + } +}; + +struct NodeDataPair { + ImBuf *image_buffer; + NodeData *node_data; - (*r_output)[3] *= strength; + struct { + /* Rasterizer doesn't support glCoord yet, so for now we just store them in a runtime section. + */ + int2 last_known_pixel_pos; + } runtime; +}; + +class AddPixel : public AbstractBlendMode<FragmentOutput, NodeDataPair> { + public: + void blend(NodeDataPair *dest, const FragmentOutput &source) const override + { + PixelData new_pixel; + new_pixel.local_pos = source.local_pos; + new_pixel.pixel_pos = dest->runtime.last_known_pixel_pos; + const int pixel_offset = new_pixel.pixel_pos[1] * dest->image_buffer->x + + new_pixel.pixel_pos[0]; + new_pixel.content = float4(dest->image_buffer->rect_float[pixel_offset * 4]); + new_pixel.flags.dirty = false; + + dest->node_data->pixels.append(new_pixel); + dest->runtime.last_known_pixel_pos[0] += 1; } }; -using RasterizerType = Rasterizer<VertexShader, FragmentShader, AlphaBlendMode>; +class NodeDataDrawingTarget : public AbstractDrawingTarget<NodeDataPair, NodeDataPair> { + private: + NodeDataPair *active_ = nullptr; -struct TexturePaintingUserData { - Object *ob; - Brush *brush; - PBVHNode **nodes; - Vector<rctf> region_to_update; + public: + uint64_t get_width() const + { + return active_->image_buffer->x; + } + uint64_t get_height() const + { + return active_->image_buffer->y; + }; + NodeDataPair *get_pixel_ptr(uint64_t x, uint64_t y) + { + active_->runtime.last_known_pixel_pos = int2(x, y); + return active_; + }; + int64_t get_pixel_stride() const + { + return 0; + }; + bool has_active_target() const + { + return active_ != nullptr; + } + void activate(NodeDataPair *instance) + { + active_ = instance; + }; + void deactivate() + { + active_ = nullptr; + } }; -static void do_task_cb_ex(void *__restrict userdata, - const int n, - const TaskParallelTLS *__restrict UNUSED(tls)) -{ - TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata); - Object *ob = data->ob; - SculptSession *ss = ob->sculpt; - const Brush *brush = data->brush; - ImBuf *drawing_target = ss->mode.texture_paint.drawing_target; - RasterizerType rasterizer; +using RasterizerType = Rasterizer<VertexShader, FragmentShader, AddPixel, NodeDataDrawingTarget>; + +} // namespace shaders +void NodeData::init_pixels(Object *ob, PBVHNode *node, ImBuf *image_buffer) +{ Mesh *mesh = static_cast<Mesh *>(ob->data); MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV)); if (ldata_uv == nullptr) { return; } - rasterizer.activate_drawing_target(drawing_target); - rasterizer.vertex_shader().image_size = float2(drawing_target->x, drawing_target->y); - srgb_to_linearrgb_v3_v3(rasterizer.fragment_shader().color, brush->rgb); - FragmentShader &fragment_shader = rasterizer.fragment_shader(); - fragment_shader.color[3] = 1.0f; - fragment_shader.brush = brush; - fragment_shader.sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( - ss, &fragment_shader.test, brush->falloff_shape); - - PBVHVertexIter vd; + shaders::RasterizerType rasterizer; + shaders::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; + node_data_pair.image_buffer = image_buffer; + rasterizer.activate_drawing_target(&node_data_pair); + SculptSession *ss = ob->sculpt; MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss); - rctf ®ion_to_update = data->region_to_update[n]; - BLI_rctf_init_minmax(®ion_to_update); - BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { + PBVHVertexIter vd; + BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) { MeshElemMap *vert_map = &ss->pmap[vd.index]; for (int j = 0; j < ss->pmap[vd.index].count; j++) { const MPoly *p = &ss->mpoly[vert_map->indices[j]]; @@ -125,12 +226,7 @@ static void do_task_cb_ex(void *__restrict userdata, continue; } - float poly_center[3]; const MLoop *loopstart = &ss->mloop[p->loopstart]; - BKE_mesh_calc_poly_center(p, &ss->mloop[p->loopstart], mvert, poly_center); - if (!fragment_shader.sculpt_brush_test_sq_fn(&fragment_shader.test, poly_center)) { - continue; - } for (int triangle = 0; triangle < p->totloop - 2; triangle++) { const int v1_index = loopstart[0].v; @@ -140,47 +236,104 @@ static void do_task_cb_ex(void *__restrict userdata, const int v2_loop_index = p->loopstart + triangle + 1; const int v3_loop_index = p->loopstart + triangle + 2; - 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); + 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); rasterizer.draw_triangle(v1, v2, v3); - - BLI_rctf_do_minmax_v(®ion_to_update, v1.uv); - BLI_rctf_do_minmax_v(®ion_to_update, v2.uv); - BLI_rctf_do_minmax_v(®ion_to_update, v3.uv); } } } BKE_pbvh_vertex_iter_end; - rasterizer.deactivate_drawing_target(); } +struct TexturePaintingUserData { + Object *ob; + Brush *brush; + PBVHNode **nodes; +}; + +static void do_task_cb_ex(void *__restrict userdata, + const int n, + const TaskParallelTLS *__restrict UNUSED(tls)) +{ + TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata); + Object *ob = data->ob; + SculptSession *ss = ob->sculpt; + const Brush *brush = data->brush; + PBVHNode *node = data->nodes[n]; + NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node)); + + SculptBrushTest test; + SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( + ss, &test, brush->falloff_shape); + + 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); + pixel.flags.dirty = true; + BLI_rcti_do_minmax_v(&node_data->dirty_region, pixel.pixel_pos); + } + node_data->flags.dirty = true; +} + +struct ImageData { + void *lock = nullptr; + Image *image = nullptr; + ImageUser *image_user = nullptr; + ImBuf *image_buffer = nullptr; + + ~ImageData() + { + BKE_image_release_ibuf(image, image_buffer, lock); + } + + static bool init_active_image(Object *ob, ImageData *r_image_data) + { + ED_object_get_active_image( + ob, 1, &r_image_data->image, &r_image_data->image_user, nullptr, nullptr); + if (r_image_data->image == nullptr) { + return false; + } + r_image_data->image_buffer = BKE_image_acquire_ibuf( + r_image_data->image, r_image_data->image_user, &r_image_data->lock); + if (r_image_data->image_buffer == nullptr) { + return false; + } + return true; + } +}; + extern "C" { void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) { SculptSession *ss = ob->sculpt; Brush *brush = BKE_paint_brush(&sd->paint); - void *lock; - Image *image; - ImageUser *image_user; - - ED_object_get_active_image(ob, 1, &image, &image_user, nullptr, nullptr); - if (image == nullptr) { + ImageData image_data; + if (!ImageData::init_active_image(ob, &image_data)) { return; } - ImBuf *image_buffer = BKE_image_acquire_ibuf(image, image_user, &lock); - if (image_buffer == nullptr) { - return; + + for (int n = 0; n < totnode; n++) { + PBVHNode *node = nodes[n]; + NodeData *data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node)); + if (data == nullptr) { + NodeData *node_data = MEM_new<NodeData>(__func__); + node_data->init_pixels(ob, node, image_data.image_buffer); + BKE_pbvh_node_texture_paint_data_set(node, node_data, NodeData::free_func); + } } - ss->mode.texture_paint.drawing_target = image_buffer; + + ss->mode.texture_paint.drawing_target = image_data.image_buffer; TexturePaintingUserData data = {nullptr}; data.ob = ob; data.brush = brush; data.nodes = nodes; - data.region_to_update.resize(totnode); TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); @@ -189,20 +342,34 @@ void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int BLI_task_parallel_range(0, totnode, &data, do_task_cb_ex, &settings); TIMEIT_END(texture_painting); - for (int i = 0; i < totnode; i++) { - rcti region_to_update; - region_to_update.xmin = data.region_to_update[i].xmin * image_buffer->x; - region_to_update.xmax = data.region_to_update[i].xmax * image_buffer->x; - region_to_update.ymin = data.region_to_update[i].ymin * image_buffer->y; - region_to_update.ymax = data.region_to_update[i].ymax * image_buffer->y; + ss->mode.texture_paint.drawing_target = nullptr; +} - /* TODO: Tiled images. */ - BKE_image_partial_update_mark_region( - image, static_cast<ImageTile *>(image->tiles.first), image_buffer, ®ion_to_update); +void SCULPT_flush_texture_paint(Object *ob) +{ + ImageData image_data; + if (!ImageData::init_active_image(ob, &image_data)) { + return; } - BKE_image_release_ibuf(image, image_buffer, lock); - ss->mode.texture_paint.drawing_target = nullptr; + SculptSession *ss = ob->sculpt; + PBVHNode **nodes; + int totnode; + BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); + for (int n = 0; n < totnode; n++) { + PBVHNode *node = nodes[n]; + NodeData *data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node)); + if (data == nullptr) { + continue; + } + + if (data->flags.dirty) { + data->flush(*image_data.image_buffer); + data->mark_region(*image_data.image, *image_data.image_buffer); + } + } + + MEM_freeN(nodes); } } } // namespace blender::ed::sculpt_paint::texture_paint diff --git a/source/blender/imbuf/IMB_rasterizer.hh b/source/blender/imbuf/IMB_rasterizer.hh index 187d980fbab..24306f4514f 100644 --- a/source/blender/imbuf/IMB_rasterizer.hh +++ b/source/blender/imbuf/IMB_rasterizer.hh @@ -269,7 +269,8 @@ class Rasterizer { using VertexOutputType = typename VertexShader::VertexOutputType; using FragmentInputType = typename FragmentShader::FragmentInputType; using FragmentOutputType = typename FragmentShader::FragmentOutputType; - using TargetBufferType = typename DrawingTarget::InnerType; + using TargetBufferType = typename DrawingTarget::BufferType; + using PixelType = typename DrawingTarget::PixelType; /** Check if the vertex shader and the fragment shader can be linked together. */ static_assert(std::is_same_v<InterfaceInnerType, FragmentInputType>); @@ -684,7 +685,7 @@ class Rasterizer { void render_rasterline(const RasterlineType &rasterline) { FragmentInputType data = rasterline.start_data; - float *pixel_ptr = drawing_target_.get_pixel_ptr(rasterline.start_x, rasterline.y); + PixelType *pixel_ptr = drawing_target_.get_pixel_ptr(rasterline.start_x, rasterline.y); for (uint32_t x = rasterline.start_x; x < rasterline.end_x; x++) { FragmentOutputType fragment_out; diff --git a/source/blender/imbuf/intern/rasterizer_target.hh b/source/blender/imbuf/intern/rasterizer_target.hh index 25830b4006a..d181d9e1e06 100644 --- a/source/blender/imbuf/intern/rasterizer_target.hh +++ b/source/blender/imbuf/intern/rasterizer_target.hh @@ -17,19 +17,20 @@ namespace blender::imbuf::rasterizer { * An abstract implementation of a drawing target. Will make it possible to switch to other render * targets then only ImBuf types. */ -template<typename Inner> class AbstractDrawingTarget { +template<typename Buffer, typename Pixel = float> class AbstractDrawingTarget { public: - using InnerType = Inner; + using BufferType = Buffer; + using PixelType = Pixel; virtual uint64_t get_width() const = 0; virtual uint64_t get_height() const = 0; - virtual float *get_pixel_ptr(uint64_t x, uint64_t y) = 0; + virtual PixelType *get_pixel_ptr(uint64_t x, uint64_t y) = 0; virtual int64_t get_pixel_stride() const = 0; virtual bool has_active_target() const = 0; - virtual void activate(Inner *instance) = 0; + virtual void activate(BufferType *instance) = 0; virtual void deactivate() = 0; }; -class ImageBufferDrawingTarget : public AbstractDrawingTarget<ImBuf> { +class ImageBufferDrawingTarget : public AbstractDrawingTarget<ImBuf, float> { private: ImBuf *image_buffer_ = nullptr; |