Blender V4.3
extract_mesh_vbo_uv.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 "BLI_array_utils.hh"
11#include "BLI_string.h"
12
13#include "BKE_attribute.hh"
14
15#include "draw_subdivision.hh"
16#include "extract_mesh.hh"
17
18namespace blender::draw {
19
20/* Initialize the vertex format to be used for UVs. Return true if any UV layer is
21 * found, false otherwise. */
23 const MeshBatchCache &cache,
24 const CustomData *cd_ldata,
25 const eMRExtractType extract_type,
26 uint32_t &r_uv_layers)
27{
29
30 uint32_t uv_layers = cache.cd_used.uv;
31 /* HACK to fix #68857 */
32 if (extract_type == MR_EXTRACT_BMESH && cache.cd_used.edit_uv == 1) {
33 int layer = CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2);
34 if (layer != -1 && !CustomData_layer_is_anonymous(cd_ldata, CD_PROP_FLOAT2, layer)) {
35 uv_layers |= (1 << layer);
36 }
37 }
38
39 r_uv_layers = 0;
40
41 for (int i = 0; i < MAX_MTFACE; i++) {
42 if (uv_layers & (1 << i)) {
43 char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
44 const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_PROP_FLOAT2, i);
45
46 /* not all UV layers are guaranteed to exist, since the list of available UV
47 * layers is generated for the evaluated mesh, which is needed to show modifier
48 * results in editmode, but the actual mesh might be the base mesh.
49 */
50 if (layer_name) {
51 r_uv_layers |= (1 << i);
52 GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
53 /* UV layer name. */
54 SNPRINTF(attr_name, "a%s", attr_safe_name);
56 /* Active render layer name. */
57 if (i == CustomData_get_render_layer(cd_ldata, CD_PROP_FLOAT2)) {
59 }
60 /* Active display layer name. */
61 if (i == CustomData_get_active_layer(cd_ldata, CD_PROP_FLOAT2)) {
63 /* Alias to `pos` for edit uvs. */
65 }
66 /* Stencil mask uv layer name. */
67 if (i == CustomData_get_stencil_layer(cd_ldata, CD_PROP_FLOAT2)) {
69 }
70 }
71 }
72 }
73
74 if (format->attr_len == 0) {
76 return false;
77 }
78
79 return true;
80}
81
82void extract_uv_maps(const MeshRenderData &mr, const MeshBatchCache &cache, gpu::VertBuf &vbo)
83{
85
86 const CustomData *cd_ldata = (mr.extract_type == MR_EXTRACT_BMESH) ? &mr.bm->ldata :
87 &mr.mesh->corner_data;
88 int v_len = mr.corners_num;
89 uint32_t uv_layers = cache.cd_used.uv;
90 if (!mesh_extract_uv_format_init(&format, cache, cd_ldata, mr.extract_type, uv_layers)) {
91 /* VBO will not be used, only allocate minimum of memory. */
92 v_len = 1;
93 }
94
96 GPU_vertbuf_data_alloc(vbo, v_len);
97
98 Vector<int> uv_indices;
99 for (const int i : IndexRange(MAX_MTFACE)) {
100 if (uv_layers & (1 << i)) {
101 uv_indices.append(i);
102 }
103 }
104
105 MutableSpan<float2> uv_data = vbo.data<float2>();
107 if (mr.extract_type == MR_EXTRACT_BMESH) {
108 const BMesh &bm = *mr.bm;
109 for (const int i : uv_indices.index_range()) {
110 MutableSpan<float2> data = uv_data.slice(i * bm.totloop, bm.totloop);
111 const int offset = CustomData_get_n_offset(cd_ldata, CD_PROP_FLOAT2, uv_indices[i]);
112 threading::parallel_for(IndexRange(bm.totface), 2048, [&](const IndexRange range) {
113 for (const int face_index : range) {
114 const BMFace &face = *BM_face_at_index(&const_cast<BMesh &>(bm), face_index);
115 const BMLoop *loop = BM_FACE_FIRST_LOOP(&face);
116 for ([[maybe_unused]] const int i : IndexRange(face.len)) {
117 const int index = BM_elem_index_get(loop);
118 data[index] = BM_ELEM_CD_GET_FLOAT_P(loop, offset);
119 loop = loop->next;
120 }
121 }
122 });
123 }
124 }
125 else {
126 const bke::AttributeAccessor attributes = mr.mesh->attributes();
127 for (const int i : uv_indices.index_range()) {
128 const StringRef name = CustomData_get_layer_name(cd_ldata, CD_PROP_FLOAT2, uv_indices[i]);
129 const VArray uv_map = *attributes.lookup_or_default<float2>(
130 name, bke::AttrDomain::Corner, float2(0));
131 array_utils::copy(uv_map, uv_data.slice(i * mr.corners_num, mr.corners_num));
132 }
133 }
134 });
135}
136
137void extract_uv_maps_subdiv(const DRWSubdivCache &subdiv_cache,
138 const MeshBatchCache &cache,
139 gpu::VertBuf &vbo)
140{
141 const Mesh *coarse_mesh = subdiv_cache.mesh;
142 GPUVertFormat format = {0};
143
144 uint v_len = subdiv_cache.num_subdiv_loops;
145 uint uv_layers;
147 &format, cache, &coarse_mesh->corner_data, MR_EXTRACT_MESH, uv_layers))
148 {
149 /* TODO(kevindietrich): handle this more gracefully. */
150 v_len = 1;
151 }
152
154
155 if (uv_layers == 0) {
156 return;
157 }
158
159 /* Index of the UV layer in the compact buffer. Used UV layers are stored in a single buffer. */
160 int pack_layer_index = 0;
161 for (int i = 0; i < MAX_MTFACE; i++) {
162 if (uv_layers & (1 << i)) {
163 const int offset = int(subdiv_cache.num_subdiv_loops) * pack_layer_index++;
164 draw_subdiv_extract_uvs(subdiv_cache, &vbo, i, offset);
165 }
166 }
167}
168
169} // namespace blender::draw
bool CustomData_layer_is_anonymous(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_stencil_layer(const CustomData *data, eCustomDataType type)
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_active_layer(const CustomData *data, eCustomDataType type)
int CustomData_get_render_layer(const CustomData *data, eCustomDataType type)
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
unsigned int uint
@ CD_PROP_FLOAT2
#define MAX_MTFACE
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)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
void GPU_vertformat_safe_attr_name(const char *attr_name, char *r_safe_name, uint max_len)
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
#define GPU_MAX_SAFE_ATTR_NAME
void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias)
void GPU_vertformat_deinterleave(GPUVertFormat *format)
@ GPU_COMP_F32
constexpr int64_t size_in_bytes() const
Definition BLI_span.hh:502
void append(const T &value)
MutableSpan< T > data()
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
Extraction of Mesh data into VBO to feed to GPU.
format
static bool mesh_extract_uv_format_init(GPUVertFormat *format, const MeshBatchCache &cache, const CustomData *cd_ldata, const eMRExtractType extract_type, uint32_t &r_uv_layers)
void draw_subdiv_extract_uvs(const DRWSubdivCache &cache, gpu::VertBuf *uvs, const int face_varying_channel, const int dst_offset)
void extract_uv_maps(const MeshRenderData &mr, const MeshBatchCache &cache, gpu::VertBuf &vbo)
void extract_uv_maps_subdiv(const DRWSubdivCache &subdiv_cache, const MeshBatchCache &cache, gpu::VertBuf &vbo)
void memory_bandwidth_bound_task(const int64_t approximate_bytes_touched, const Function &function)
Definition BLI_task.hh:243
unsigned int uint32_t
Definition stdint.h:80
CustomData ldata
CustomData corner_data