Blender V4.3
extract_mesh_vbo_sculpt_data.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_array_utils.hh"
12#include "BLI_string.h"
13
14#include "BKE_attribute.hh"
15#include "BKE_mesh.hh"
16#include "BKE_paint.hh"
17
18#include "draw_subdivision.hh"
19#include "extract_mesh.hh"
20
21namespace blender::draw {
22
24{
25 static GPUVertFormat format = {0};
26 if (format.attr_len == 0) {
29 }
30 return format;
31}
32
34{
37
38 struct gpuSculptData {
39 uchar4 face_set_color;
40 float mask;
41 };
42
43 MutableSpan vbo_data = vbo.data<gpuSculptData>();
44
45 const int default_face_set = mr.mesh->face_sets_color_default;
46 const int face_set_seed = mr.mesh->face_sets_color_seed;
48 const BMesh &bm = *mr.bm;
49 const int mask_offset = CustomData_get_offset_named(
50 &mr.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
51 const int face_set_offset = CustomData_get_offset_named(
52 &mr.bm->pdata, CD_PROP_INT32, ".sculpt_face_set");
53 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
54 for (const int face_index : range) {
55 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
56 const IndexRange face_range(BM_elem_index_get(BM_FACE_FIRST_LOOP(&face)), face.len);
57
58 uchar4 face_set_color(UCHAR_MAX);
59 if (face_set_offset != -1) {
60 const int face_set_id = BM_ELEM_CD_GET_INT(&face, face_set_offset);
61 if (face_set_id != default_face_set) {
62 BKE_paint_face_set_overlay_color_get(face_set_id, face_set_seed, face_set_color);
63 }
64 }
65 vbo_data.slice(face_range).fill(gpuSculptData{face_set_color, 0.0f});
66
67 if (mask_offset != -1) {
68 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
69 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
70 const int index = BM_elem_index_get(loop);
71 vbo_data[index].mask = BM_ELEM_CD_GET_FLOAT(loop->v, mask_offset);
72 loop = loop->next;
73 }
74 }
75 }
76 });
77 }
78 else {
79 const OffsetIndices faces = mr.faces;
80 const Span<int> corner_verts = mr.corner_verts;
81 const bke::AttributeAccessor attributes = mr.mesh->attributes();
82 const VArraySpan mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point);
83 const VArraySpan face_set = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
84 threading::parallel_for(faces.index_range(), 1024, [&](const IndexRange range) {
85 for (const int face_index : range) {
86 const IndexRange face = faces[face_index];
87 uchar4 face_set_color(UCHAR_MAX);
88 if (!face_set.is_empty()) {
89 const int face_set_id = face_set[face_index];
90 if (face_set_id != default_face_set) {
91 BKE_paint_face_set_overlay_color_get(face_set_id, face_set_seed, face_set_color);
92 }
93 }
94 vbo_data.slice(face).fill(gpuSculptData{face_set_color, 0.0f});
95
96 if (!mask.is_empty()) {
97 for (const int corner : face) {
98 vbo_data[corner].mask = mask[corner_verts[corner]];
99 }
100 }
101 }
102 });
103 }
104}
105
107 const DRWSubdivCache &subdiv_cache,
108 gpu::VertBuf &vbo)
109{
110 const Mesh &coarse_mesh = *mr.mesh;
111 const int subdiv_corners_num = subdiv_cache.num_subdiv_loops;
112
113 /* First, interpolate mask if available. */
114 gpu::VertBuf *mask_vbo = nullptr;
115 gpu::VertBuf *subdiv_mask_vbo = nullptr;
116
117 const bke::AttributeAccessor attributes = coarse_mesh.attributes();
118
119 if (const VArray mask = *attributes.lookup<float>(".sculpt_mask", bke::AttrDomain::Point)) {
120 GPUVertFormat mask_format = {0};
121 GPU_vertformat_attr_add(&mask_format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
122 const Span<int> corner_verts = coarse_mesh.corner_verts();
123 mask_vbo = GPU_vertbuf_calloc();
124 GPU_vertbuf_init_with_format(*mask_vbo, mask_format);
125 GPU_vertbuf_data_alloc(*mask_vbo, corner_verts.size());
126
127 MutableSpan mask_vbo_data = mask_vbo->data<float>();
128 array_utils::gather(mask, corner_verts, mask_vbo_data);
129
130 subdiv_mask_vbo = GPU_vertbuf_calloc();
131 GPU_vertbuf_init_build_on_device(*subdiv_mask_vbo, mask_format, subdiv_corners_num);
132
133 draw_subdiv_interp_custom_data(subdiv_cache, *mask_vbo, *subdiv_mask_vbo, GPU_COMP_F32, 1, 0);
134 }
135
136 /* Then, gather face sets. */
137 GPUVertFormat face_set_format = {0};
139
140 gpu::VertBuf *face_set_vbo = GPU_vertbuf_calloc();
141 GPU_vertbuf_init_with_format(*face_set_vbo, face_set_format);
142 GPU_vertbuf_data_alloc(*face_set_vbo, subdiv_corners_num);
143
144 struct gpuFaceSet {
146 };
147
148 MutableSpan face_set_vbo_data = face_set_vbo->data<gpuFaceSet>();
149 const VArraySpan face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
150 if (face_sets.is_empty()) {
151 face_set_vbo_data.fill({uchar4{UCHAR_MAX}});
152 }
153 else {
154 const Span<int> subdiv_loop_face_index(subdiv_cache.subdiv_loop_face_index,
155 subdiv_corners_num);
156 const int default_face_set = coarse_mesh.face_sets_color_default;
157 const int face_set_seed = coarse_mesh.face_sets_color_seed;
158 threading::parallel_for(IndexRange(subdiv_corners_num), 4096, [&](const IndexRange range) {
159 for (const int i : range) {
160 const int face_index = subdiv_loop_face_index[i];
161
162 uchar4 face_set_color(UCHAR_MAX);
163 const int face_set_id = face_sets[face_index];
164 /* Skip for the default color Face Set to render it white. */
165 if (face_set_id != default_face_set) {
166 BKE_paint_face_set_overlay_color_get(face_set_id, face_set_seed, face_set_color);
167 }
168
169 copy_v3_v3_uchar(face_set_vbo_data[i].color, face_set_color);
170 }
171 });
172 }
173
174 /* Finally, interleave mask and face sets. */
176 draw_subdiv_build_sculpt_data_buffer(subdiv_cache, subdiv_mask_vbo, face_set_vbo, &vbo);
177
178 if (mask_vbo) {
179 GPU_vertbuf_discard(mask_vbo);
180 GPU_vertbuf_discard(subdiv_mask_vbo);
181 }
182 GPU_vertbuf_discard(face_set_vbo);
183}
184
185} // namespace blender::draw
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void BKE_paint_face_set_overlay_color_get(int face_set, int seed, uchar r_color[4])
Definition paint.cc:2886
MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3])
@ CD_PROP_FLOAT
@ CD_PROP_INT32
void GPU_vertbuf_init_build_on_device(blender::gpu::VertBuf &verts, const GPUVertFormat &format, uint v_len)
#define GPU_vertbuf_init_with_format(verts, format)
blender::gpu::VertBuf * GPU_vertbuf_calloc()
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertbuf_discard(blender::gpu::VertBuf *)
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
@ GPU_COMP_U8
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
ATTR_WARN_UNUSED_RESULT BMesh * bm
AttributeSet attributes
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr int64_t size() const
Definition BLI_span.hh:253
MutableSpan< T > data()
Extraction of Mesh data into VBO to feed to GPU.
IndexRange range
format
ccl_device_inline float4 mask(const int4 mask, const float4 a)
static const GPUVertFormat & get_sculpt_data_format()
void draw_subdiv_build_sculpt_data_buffer(const DRWSubdivCache &cache, gpu::VertBuf *mask_vbo, gpu::VertBuf *face_set_vbo, gpu::VertBuf *sculpt_data)
void draw_subdiv_interp_custom_data(const DRWSubdivCache &cache, gpu::VertBuf &src_data, gpu::VertBuf &dst_data, int comp_type, int dimensions, int dst_offset)
void extract_sculpt_data(const MeshRenderData &mr, gpu::VertBuf &vbo)
void extract_sculpt_data_subdiv(const MeshRenderData &mr, const DRWSubdivCache &subdiv_cache, gpu::VertBuf &vbo)
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:95
CustomData vdata
CustomData pdata
int totface
int face_sets_color_seed
int face_sets_color_default