[Bf-blender-cvs] [64e535cab51] temp-3d-texturing-brush-b: Use pixel encoding to reduce memory needs.

Jeroen Bakker noreply at git.blender.org
Mon Mar 14 14:54:15 CET 2022


Commit: 64e535cab51cd0f8632dc6be756a4ea671961e85
Author: Jeroen Bakker
Date:   Mon Mar 14 14:54:06 2022 +0100
Branches: temp-3d-texturing-brush-b
https://developer.blender.org/rB64e535cab51cd0f8632dc6be756a4ea671961e85

Use pixel encoding to reduce memory needs.

===================================================================

M	source/blender/editors/sculpt_paint/CMakeLists.txt
A	source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
M	source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
A	source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_d.cc

===================================================================

diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 3fa8eed7338..3c82c07c604 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -65,9 +65,11 @@ set(SRC
   sculpt_paint_color.c
   sculpt_pose.c
   sculpt_smooth.c
-  sculpt_texture_paint_b.cc
-  sculpt_texture_paint_pixel_extraction_b.cc
+  #sculpt_texture_paint_b.cc
+  sculpt_texture_paint_d.cc
+  #sculpt_texture_paint_pixel_extraction_b.cc
   #sculpt_texture_paint_pixel_extraction_c.cc
+  sculpt_texture_paint_pixel_extraction_d.cc
   sculpt_transform.c
   sculpt_undo.c
   sculpt_uv.c
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
new file mode 100644
index 00000000000..b28332b3d16
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_pbvh.h"
+
+#include "PIL_time_utildefines.h"
+
+#include "BLI_math_color_blend.h"
+#include "BLI_task.h"
+#include "BLI_vector.hh"
+
+#include "IMB_rasterizer.hh"
+
+#include "WM_types.h"
+
+#include "bmesh.h"
+
+#include "ED_uvedit.h"
+
+#include "sculpt_intern.h"
+#include "sculpt_texture_paint_intern.hh"
+
+namespace blender::ed::sculpt_paint::texture_paint {
+namespace painting {
+
+static Pixel get_start_pixel(const PixelsPackage &encoded_pixels,
+                             const Vector<Triangle> &triangles,
+                             const MVert *mvert,
+                             const MLoopUV *ldata_uv)
+{
+  Pixel result;
+  const Triangle &triangle = triangles[encoded_pixels.triangle_index];
+  const float3 weights = encoded_pixels.start_edge_coord;
+  interp_v3_v3v3v3(result.pos,
+                   mvert[triangle.vert_indices[0]].co,
+                   mvert[triangle.vert_indices[1]].co,
+                   mvert[triangle.vert_indices[2]].co,
+                   weights);
+  interp_v3_v3v3v3(result.uv,
+                   ldata_uv[triangle.loop_indices[0]].uv,
+                   ldata_uv[triangle.loop_indices[1]].uv,
+                   ldata_uv[triangle.loop_indices[2]].uv,
+                   weights);
+
+  return result;
+}
+
+static Pixel get_delta_pixel(const PixelsPackage &encoded_pixels,
+                             const Vector<Triangle> &triangles,
+                             const Pixel &start_pixel,
+                             const MVert *mvert,
+                             const MLoopUV *ldata_uv
+
+)
+{
+  Pixel result;
+  const Triangle &triangle = triangles[encoded_pixels.triangle_index];
+  const float3 weights = encoded_pixels.start_edge_coord + triangle.add_edge_coord_x;
+  interp_v3_v3v3v3(result.pos,
+                   mvert[triangle.vert_indices[0]].co,
+                   mvert[triangle.vert_indices[1]].co,
+                   mvert[triangle.vert_indices[2]].co,
+                   weights);
+  interp_v3_v3v3v3(result.uv,
+                   ldata_uv[triangle.loop_indices[0]].uv,
+                   ldata_uv[triangle.loop_indices[1]].uv,
+                   ldata_uv[triangle.loop_indices[2]].uv,
+                   weights);
+  result.pos -= start_pixel.pos;
+  result.uv -= start_pixel.uv;
+  return result;
+}
+
+static void add(Pixel &dst, const Pixel &lh)
+{
+  dst.pos += lh.pos;
+  dst.uv += lh.uv;
+}
+
+static void do_task_cb_ex(void *__restrict userdata,
+                          const int n,
+                          const TaskParallelTLS *__restrict tls)
+{
+  TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
+  Object *ob = data->ob;
+  SculptSession *ss = ob->sculpt;
+  ImBuf *image_buffer = ss->mode.texture_paint.drawing_target;
+  const Brush *brush = data->brush;
+  PBVHNode *node = data->nodes[n];
+  NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+  BLI_assert(node_data != nullptr);
+
+  const int thread_id = BLI_task_parallel_thread_id(tls);
+
+  SculptBrushTest test;
+  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]);
+  float4 brush_linear;
+  srgb_to_linearrgb_v3_v3(brush_linear, brush_srgb);
+  brush_linear[3] = 1.0f;
+  MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
+  Mesh *mesh = static_cast<Mesh *>(ob->data);
+  MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
+
+  const float brush_strength = ss->cache->bstrength;
+
+  for (PixelsPackage &encoded_pixels : node_data->encoded_pixels) {
+    Triangle &triangle = node_data->triangles[encoded_pixels.triangle_index];
+    int pixel_offset = encoded_pixels.start_image_coordinate.y * image_buffer->x +
+                       encoded_pixels.start_image_coordinate.x;
+    float3 edge_coord = encoded_pixels.start_edge_coord;
+    Pixel pixel = get_start_pixel(encoded_pixels, node_data->triangles, mvert, ldata_uv);
+    const Pixel add_pixel = get_delta_pixel(
+        encoded_pixels, node_data->triangles, pixel, mvert, ldata_uv);
+    bool pixels_painted = false;
+    for (int x = 0; x < encoded_pixels.num_pixels; x++) {
+      if (!sculpt_brush_test_sq_fn(&test, pixel.pos)) {
+        add(pixel, add_pixel);
+        pixel_offset += 1;
+        continue;
+      }
+
+      float *color = &image_buffer->rect_float[pixel_offset * 4];
+      const float3 normal(0.0f, 0.0f, 0.0f);
+      const float3 face_normal(0.0f, 0.0f, 0.0f);
+      const float mask = 0.0f;
+      const float falloff_strength = SCULPT_brush_strength_factor(
+          ss, brush, pixel.pos, sqrtf(test.dist), normal, face_normal, mask, 0, thread_id);
+
+      blend_color_interpolate_float(color, color, brush_linear, falloff_strength * brush_strength);
+      pixels_painted = true;
+
+      edge_coord += triangle.add_edge_coord_x;
+      pixel_offset++;
+      add(pixel, add_pixel);
+    }
+
+    if (pixels_painted) {
+      BLI_rcti_do_minmax_v(&node_data->dirty_region, encoded_pixels.start_image_coordinate);
+      BLI_rcti_do_minmax_v(
+          &node_data->dirty_region,
+          int2(encoded_pixels.start_image_coordinate.x + encoded_pixels.num_pixels + 1,
+               encoded_pixels.start_image_coordinate.y));
+      node_data->flags.dirty = true;
+    }
+  }
+}
+}  // namespace painting
+
+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);
+
+  ImageData image_data;
+  if (!ImageData::init_active_image(ob, &image_data)) {
+    return;
+  }
+
+  ss->mode.texture_paint.drawing_target = image_data.image_buffer;
+
+  TexturePaintingUserData data = {nullptr};
+  data.ob = ob;
+  data.brush = brush;
+  data.nodes = nodes;
+
+  TaskParallelSettings settings;
+  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+
+  TIMEIT_START(texture_painting);
+  BLI_task_parallel_range(0, totnode, &data, painting::do_task_cb_ex, &settings);
+  TIMEIT_END(texture_painting);
+
+  ss->mode.texture_paint.drawing_target = nullptr;
+}
+
+void SCULPT_init_texture_paint(Object *ob)
+{
+  SculptSession *ss = ob->sculpt;
+  ImageData image_data;
+  if (!ImageData::init_active_image(ob, &image_data)) {
+    return;
+  }
+  ss->mode.texture_paint.drawing_target = image_data.image_buffer;
+  PBVHNode **nodes;
+  int totnode;
+  BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+  SCULPT_extract_pixels(ob, nodes, totnode);
+
+  MEM_freeN(nodes);
+
+  ss->mode.texture_paint.drawing_target = nullptr;
+}
+
+void SCULPT_flush_texture_paint(Object *ob)
+{
+  ImageData image_data;
+  if (!ImageData::init_active_image(ob, &image_data)) {
+    return;
+  }
+
+  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/editors/sculpt_paint/sculpt_texture_paint_intern.hh b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
index 31864148588..12aa041ab69 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
@@ -1,5 +1,27 @@
 namespace blender::ed::sculpt_paint::texture_paint {
 
+struct Polygon {
+};
+
+struct Triangle {
+  int3 loop_indices;
+  int3 vert_indices;
+  int poly_index;
+  float3 add_edge_coord_x;
+};
+
+struct 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list