Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern/mesh_extractors')
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh.h107
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc229
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc3
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc31
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc94
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc6
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc72
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc30
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc489
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc88
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc125
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc79
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc59
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc65
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc2
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc48
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc32
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc4
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc132
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc109
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc97
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc10
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc89
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc163
-rw-r--r--source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc48
25 files changed, 2017 insertions, 194 deletions
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.h b/source/blender/draw/intern/mesh_extractors/extract_mesh.h
index d9f397fd8b8..37eb4f80442 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh.h
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.h
@@ -39,6 +39,8 @@
extern "C" {
#endif
+struct DRWSubdivCache;
+
#define MIN_RANGE_LEN 1024
/* ---------------------------------------------------------------------- */
@@ -82,7 +84,8 @@ typedef struct MeshRenderData {
const float (*bm_poly_centers)[3];
int *v_origindex, *e_origindex, *p_origindex;
- int crease_ofs;
+ int edge_crease_ofs;
+ int vert_crease_ofs;
int bweight_ofs;
int freestyle_edge_ofs;
int freestyle_face_ofs;
@@ -98,8 +101,9 @@ typedef struct MeshRenderData {
BMFace *efa_act_uv;
/* Data created on-demand (usually not for #BMesh based data). */
MLoopTri *mlooptri;
+ const float (*vert_normals)[3];
+ const float (*poly_normals)[3];
float (*loop_normals)[3];
- float (*poly_normals)[3];
int *lverts, *ledges;
struct {
@@ -168,39 +172,43 @@ BLI_INLINE const float *bm_face_no_get(const MeshRenderData *mr, const BMFace *e
/* ---------------------------------------------------------------------- */
/** \name Mesh Elements Extract Struct
* \{ */
+
/* TODO(jbakker): move parameters inside a struct. */
-typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr,
- BMLoop **elt,
- const int elt_index,
- void *data);
+
+typedef void(ExtractTriBMeshFn)(const MeshRenderData *mr, BMLoop **elt, int elt_index, void *data);
typedef void(ExtractTriMeshFn)(const MeshRenderData *mr,
const MLoopTri *mlt,
- const int elt_index,
+ int elt_index,
void *data);
typedef void(ExtractPolyBMeshFn)(const MeshRenderData *mr,
const BMFace *f,
- const int f_index,
+ int f_index,
void *data);
typedef void(ExtractPolyMeshFn)(const MeshRenderData *mr,
const MPoly *mp,
- const int mp_index,
+ int mp_index,
void *data);
typedef void(ExtractLEdgeBMeshFn)(const MeshRenderData *mr,
const BMEdge *eed,
- const int ledge_index,
+ int ledge_index,
void *data);
typedef void(ExtractLEdgeMeshFn)(const MeshRenderData *mr,
const MEdge *med,
- const int ledge_index,
+ int ledge_index,
void *data);
typedef void(ExtractLVertBMeshFn)(const MeshRenderData *mr,
const BMVert *eve,
- const int lvert_index,
+ int lvert_index,
void *data);
typedef void(ExtractLVertMeshFn)(const MeshRenderData *mr,
const MVert *mv,
- const int lvert_index,
+ int lvert_index,
void *data);
+typedef void(ExtractLooseGeomSubdivFn)(const struct DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *data);
typedef void(ExtractInitFn)(const MeshRenderData *mr,
struct MeshBatchCache *cache,
void *buffer,
@@ -211,6 +219,27 @@ typedef void(ExtractFinishFn)(const MeshRenderData *mr,
void *data);
typedef void(ExtractTaskReduceFn)(void *userdata, void *task_userdata);
+typedef void(ExtractInitSubdivFn)(const struct DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *data);
+typedef void(ExtractIterSubdivBMeshFn)(const struct DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_quad);
+typedef void(ExtractIterSubdivMeshFn)(const struct DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad);
+typedef void(ExtractFinishSubdivFn)(const struct DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *data);
+
typedef struct MeshExtract {
/** Executed on main thread and return user data for iteration functions. */
ExtractInitFn *init;
@@ -223,9 +252,15 @@ typedef struct MeshExtract {
ExtractLEdgeMeshFn *iter_ledge_mesh;
ExtractLVertBMeshFn *iter_lvert_bm;
ExtractLVertMeshFn *iter_lvert_mesh;
+ ExtractLooseGeomSubdivFn *iter_loose_geom_subdiv;
/** Executed on one worker thread after all elements iterations. */
ExtractTaskReduceFn *task_reduce;
ExtractFinishFn *finish;
+ /** Executed on main thread for subdivision evaluation. */
+ ExtractInitSubdivFn *init_subdiv;
+ ExtractIterSubdivBMeshFn *iter_subdiv_bm;
+ ExtractIterSubdivMeshFn *iter_subdiv_mesh;
+ ExtractFinishSubdivFn *finish_subdiv;
/** Used to request common data. */
eMRDataType data_type;
size_t data_size;
@@ -241,31 +276,42 @@ typedef struct MeshExtract {
/** \} */
/* draw_cache_extract_mesh_render_data.c */
-MeshRenderData *mesh_render_data_create(Mesh *me,
- const bool is_editmode,
- const bool is_paint_mode,
- const bool is_mode_active,
+
+/**
+ * \param is_mode_active: When true, use the modifiers from the edit-data,
+ * otherwise don't use modifiers as they are not from this object.
+ */
+MeshRenderData *mesh_render_data_create(Object *object,
+ Mesh *me,
+ bool is_editmode,
+ bool is_paint_mode,
+ bool is_mode_active,
const float obmat[4][4],
- const bool do_final,
- const bool do_uvedit,
+ bool do_final,
+ bool do_uvedit,
const ToolSettings *ts);
void mesh_render_data_free(MeshRenderData *mr);
-void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_flag);
+void mesh_render_data_update_normals(MeshRenderData *mr, eMRDataType data_flag);
void mesh_render_data_update_loose_geom(MeshRenderData *mr,
MeshBufferCache *cache,
- const eMRIterType iter_type,
- const eMRDataType data_flag);
+ eMRIterType iter_type,
+ eMRDataType data_flag);
void mesh_render_data_update_polys_sorted(MeshRenderData *mr,
MeshBufferCache *cache,
- const eMRDataType data_flag);
+ eMRDataType data_flag);
+/**
+ * Part of the creation of the #MeshRenderData that happens in a thread.
+ */
void mesh_render_data_update_looptris(MeshRenderData *mr,
- const eMRIterType iter_type,
- const eMRDataType data_flag);
+ eMRIterType iter_type,
+ eMRDataType data_flag);
/* draw_cache_extract_mesh_extractors.c */
typedef struct EditLoopData {
uchar v_flag;
uchar e_flag;
+ /* This is used for both vertex and edge creases. The edge crease value is stored in the bottom 4
+ * bits, while the vertex crease is stored in the upper 4 bits. */
uchar crease;
uchar bweight;
} EditLoopData;
@@ -273,19 +319,19 @@ typedef struct EditLoopData {
void *mesh_extract_buffer_get(const MeshExtract *extractor, MeshBufferList *mbuflist);
eMRIterType mesh_extract_iter_type(const MeshExtract *ext);
const MeshExtract *mesh_extract_override_get(const MeshExtract *extractor,
- const bool do_hq_normals,
- const bool do_single_mat);
+ bool do_hq_normals,
+ bool do_single_mat);
void mesh_render_data_face_flag(const MeshRenderData *mr,
const BMFace *efa,
- const int cd_ofs,
+ int cd_ofs,
EditLoopData *eattr);
void mesh_render_data_loop_flag(const MeshRenderData *mr,
BMLoop *l,
- const int cd_ofs,
+ int cd_ofs,
EditLoopData *eattr);
void mesh_render_data_loop_edge_flag(const MeshRenderData *mr,
BMLoop *l,
- const int cd_ofs,
+ int cd_ofs,
EditLoopData *eattr);
extern const MeshExtract extract_tris;
@@ -328,6 +374,7 @@ extern const MeshExtract extract_poly_idx;
extern const MeshExtract extract_edge_idx;
extern const MeshExtract extract_vert_idx;
extern const MeshExtract extract_fdot_idx;
+extern const MeshExtract extract_attr[GPU_MAX_ATTR];
#ifdef __cplusplus
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
index d06fb91411e..cd71beb1f02 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_edituv.cc
@@ -27,6 +27,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Edit UV Triangles Indices
@@ -94,6 +96,79 @@ static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr),
GPU_indexbuf_build_in_place(&data->elb, ibo);
}
+static void extract_edituv_tris_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *tls_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
+ GPU_indexbuf_init(&data->elb,
+ GPU_PRIM_TRIS,
+ subdiv_cache->num_subdiv_triangles,
+ subdiv_cache->num_subdiv_loops);
+ data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
+}
+
+static void extract_edituv_tris_iter_subdiv_bm(const DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_quad)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ const uint loop_idx = subdiv_quad_index * 4;
+
+ edituv_tri_add(data,
+ BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN) != 0,
+ BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
+ loop_idx,
+ loop_idx + 1,
+ loop_idx + 2);
+
+ edituv_tri_add(data,
+ BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN) != 0,
+ BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
+ loop_idx,
+ loop_idx + 2,
+ loop_idx + 3);
+}
+
+static void extract_edituv_tris_iter_subdiv_mesh(const DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ const uint loop_idx = subdiv_quad_index * 4;
+
+ edituv_tri_add(data,
+ (coarse_quad->flag & ME_HIDE) != 0,
+ (coarse_quad->flag & ME_FACE_SEL) != 0,
+ loop_idx,
+ loop_idx + 1,
+ loop_idx + 2);
+
+ edituv_tri_add(data,
+ (coarse_quad->flag & ME_HIDE) != 0,
+ (coarse_quad->flag & ME_FACE_SEL) != 0,
+ loop_idx,
+ loop_idx + 2,
+ loop_idx + 3);
+}
+
+static void extract_edituv_tris_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
+ GPU_indexbuf_build_in_place(&data->elb, ibo);
+}
+
constexpr MeshExtract create_extractor_edituv_tris()
{
MeshExtract extractor = {nullptr};
@@ -101,6 +176,10 @@ constexpr MeshExtract create_extractor_edituv_tris()
extractor.iter_looptri_bm = extract_edituv_tris_iter_looptri_bm;
extractor.iter_looptri_mesh = extract_edituv_tris_iter_looptri_mesh;
extractor.finish = extract_edituv_tris_finish;
+ extractor.init_subdiv = extract_edituv_tris_init_subdiv;
+ extractor.iter_subdiv_bm = extract_edituv_tris_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_edituv_tris_iter_subdiv_mesh;
+ extractor.finish_subdiv = extract_edituv_tris_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
@@ -184,6 +263,77 @@ static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr),
GPU_indexbuf_build_in_place(&data->elb, ibo);
}
+static void extract_edituv_lines_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *tls_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
+ GPU_indexbuf_init(
+ &data->elb, GPU_PRIM_LINES, subdiv_cache->num_subdiv_loops, subdiv_cache->num_subdiv_loops);
+ data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
+}
+
+static void extract_edituv_lines_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_poly)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
+ const int edge_origindex = subdiv_loop_edge_index[loop_idx];
+ const bool real_edge = (edge_origindex != -1 &&
+ (mr->e_origindex == nullptr ||
+ mr->e_origindex[edge_origindex] != ORIGINDEX_NONE));
+ edituv_edge_add(data,
+ BM_elem_flag_test_bool(coarse_poly, BM_ELEM_HIDDEN) != 0 || !real_edge,
+ BM_elem_flag_test_bool(coarse_poly, BM_ELEM_SELECT) != 0,
+ loop_idx,
+ (loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1));
+ }
+}
+
+static void extract_edituv_lines_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_poly)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint loop_idx = start_loop_idx; loop_idx < end_loop_idx; loop_idx++) {
+ const int edge_origindex = subdiv_loop_edge_index[loop_idx];
+ const bool real_edge = (edge_origindex != -1 &&
+ (mr->e_origindex == nullptr ||
+ mr->e_origindex[edge_origindex] != ORIGINDEX_NONE));
+ edituv_edge_add(data,
+ (coarse_poly->flag & ME_HIDE) != 0 || !real_edge,
+ (coarse_poly->flag & ME_FACE_SEL) != 0,
+ loop_idx,
+ (loop_idx + 1 == end_loop_idx) ? start_loop_idx : (loop_idx + 1));
+ }
+}
+
+static void extract_edituv_lines_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
+ GPU_indexbuf_build_in_place(&data->elb, ibo);
+}
+
constexpr MeshExtract create_extractor_edituv_lines()
{
MeshExtract extractor = {nullptr};
@@ -191,6 +341,10 @@ constexpr MeshExtract create_extractor_edituv_lines()
extractor.iter_poly_bm = extract_edituv_lines_iter_poly_bm;
extractor.iter_poly_mesh = extract_edituv_lines_iter_poly_mesh;
extractor.finish = extract_edituv_lines_finish;
+ extractor.init_subdiv = extract_edituv_lines_init_subdiv;
+ extractor.iter_subdiv_bm = extract_edituv_lines_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_edituv_lines_iter_subdiv_mesh;
+ extractor.finish_subdiv = extract_edituv_lines_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
@@ -268,6 +422,75 @@ static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr),
GPU_indexbuf_build_in_place(&data->elb, ibo);
}
+static void extract_edituv_points_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *tls_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(tls_data);
+ GPU_indexbuf_init(
+ &data->elb, GPU_PRIM_POINTS, subdiv_cache->num_subdiv_loops, subdiv_cache->num_subdiv_loops);
+ data->sync_selection = (mr->toolsettings->uv_flag & UV_SYNC_SELECTION) != 0;
+}
+
+static void extract_edituv_points_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_quad)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint i = start_loop_idx; i < end_loop_idx; i++) {
+ const int vert_origindex = subdiv_loop_vert_index[i];
+ const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
+ vert_origindex != -1 &&
+ mr->v_origindex[vert_origindex] != ORIGINDEX_NONE);
+ edituv_point_add(data,
+ (BM_elem_flag_test(coarse_quad, BM_ELEM_HIDDEN)) || !real_vert,
+ BM_elem_flag_test(coarse_quad, BM_ELEM_SELECT) != 0,
+ i);
+ }
+}
+
+static void extract_edituv_points_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint i = start_loop_idx; i < end_loop_idx; i++) {
+ const int vert_origindex = subdiv_loop_vert_index[i];
+ const bool real_vert = (mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
+ vert_origindex != -1 &&
+ mr->v_origindex[vert_origindex] != ORIGINDEX_NONE);
+ edituv_point_add(data,
+ ((coarse_quad->flag & ME_HIDE) != 0) || !real_vert,
+ (coarse_quad->flag & ME_FACE_SEL) != 0,
+ i);
+ }
+}
+
+static void extract_edituv_points_finish_subdiv(const struct DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *_data)
+{
+ MeshExtract_EditUvElem_Data *data = static_cast<MeshExtract_EditUvElem_Data *>(_data);
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
+ GPU_indexbuf_build_in_place(&data->elb, ibo);
+}
+
constexpr MeshExtract create_extractor_edituv_points()
{
MeshExtract extractor = {nullptr};
@@ -275,6 +498,10 @@ constexpr MeshExtract create_extractor_edituv_points()
extractor.iter_poly_bm = extract_edituv_points_iter_poly_bm;
extractor.iter_poly_mesh = extract_edituv_points_iter_poly_mesh;
extractor.finish = extract_edituv_points_finish;
+ extractor.init_subdiv = extract_edituv_points_init_subdiv;
+ extractor.iter_subdiv_bm = extract_edituv_points_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_edituv_points_iter_subdiv_mesh;
+ extractor.finish_subdiv = extract_edituv_points_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUvElem_Data);
extractor.use_threading = false;
@@ -388,5 +615,3 @@ const MeshExtract extract_edituv_lines = blender::draw::create_extractor_edituv_
const MeshExtract extract_edituv_points = blender::draw::create_extractor_edituv_points();
const MeshExtract extract_edituv_fdots = blender::draw::create_extractor_edituv_fdots();
}
-
-/** \} */
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
index ea58e1aeed8..2e8b85250f3 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_fdots.cc
@@ -110,10 +110,9 @@ constexpr MeshExtract create_extractor_fdots()
}
/** \} */
+
} // namespace blender::draw
extern "C" {
const MeshExtract extract_fdots = blender::draw::create_extractor_fdots();
}
-
-/** \} */
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
index 54f5611106f..3d9729dea56 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines.cc
@@ -25,6 +25,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -155,6 +157,33 @@ static void extract_lines_finish(const MeshRenderData *UNUSED(mr),
GPU_indexbuf_build_in_place(elb, ibo);
}
+static void extract_lines_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
+ GPU_indexbuf_init_build_on_device(ibo,
+ subdiv_cache->num_subdiv_loops * 2 + mr->edge_loose_len * 2);
+
+ draw_subdiv_build_lines_buffer(subdiv_cache, ibo);
+}
+
+static void extract_lines_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *UNUSED(data))
+{
+ if (loose_geom->edge_len == 0) {
+ return;
+ }
+
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
+ draw_subdiv_build_lines_loose_buffer(subdiv_cache, ibo, static_cast<uint>(loose_geom->edge_len));
+}
+
constexpr MeshExtract create_extractor_lines()
{
MeshExtract extractor = {nullptr};
@@ -163,6 +192,8 @@ constexpr MeshExtract create_extractor_lines()
extractor.iter_poly_mesh = extract_lines_iter_poly_mesh;
extractor.iter_ledge_bm = extract_lines_iter_ledge_bm;
extractor.iter_ledge_mesh = extract_lines_iter_ledge_mesh;
+ extractor.init_subdiv = extract_lines_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_lines_loose_geom_subdiv;
extractor.task_reduce = extract_lines_task_reduce;
extractor.finish = extract_lines_finish;
extractor.data_type = MR_DATA_NONE;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
index 522afcd44a1..2b01b6801c2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_adjacency.cc
@@ -26,6 +26,7 @@
#include "MEM_guardedalloc.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -44,6 +45,18 @@ struct MeshExtract_LineAdjacency_Data {
uint *vert_to_loop;
};
+static void line_adjacency_data_init(MeshExtract_LineAdjacency_Data *data,
+ uint vert_len,
+ uint loop_len,
+ uint tess_edge_len)
+{
+ data->vert_to_loop = static_cast<uint *>(MEM_callocN(sizeof(uint) * vert_len, __func__));
+
+ GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES_ADJ, tess_edge_len, loop_len);
+ data->eh = BLI_edgehash_new_ex(__func__, tess_edge_len);
+ data->is_manifold = true;
+}
+
static void extract_lines_adjacency_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *UNUSED(buf),
@@ -55,11 +68,7 @@ static void extract_lines_adjacency_init(const MeshRenderData *mr,
uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len;
MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(tls_data);
- data->vert_to_loop = static_cast<uint *>(MEM_callocN(sizeof(uint) * mr->vert_len, __func__));
-
- GPU_indexbuf_init(&data->elb, GPU_PRIM_LINES_ADJ, tess_edge_len, mr->loop_len);
- data->eh = BLI_edgehash_new_ex(__func__, tess_edge_len);
- data->is_manifold = true;
+ line_adjacency_data_init(data, mr->vert_len, mr->loop_len, tess_edge_len);
}
BLI_INLINE void lines_adjacency_triangle(
@@ -171,9 +180,72 @@ static void extract_lines_adjacency_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data->vert_to_loop);
}
-#undef NO_EDGE
+static void extract_lines_adjacency_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buf),
+ void *_data)
+{
+ MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(_data);
-/** \} */
+ /* For each polygon there is (loop + triangle - 1) edges. Since we only have quads, and a quad
+ * is split into 2 triangles, we have (loop + 2 - 1) = (loop + 1) edges for each quad, or in
+ * total: (number_of_loops + number_of_quads). */
+ const uint tess_len = subdiv_cache->num_subdiv_loops + subdiv_cache->num_subdiv_quads;
+ line_adjacency_data_init(
+ data, subdiv_cache->num_subdiv_verts, subdiv_cache->num_subdiv_loops, tess_len);
+}
+
+static void extract_lines_adjacency_iter_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ void *_data,
+ uint subdiv_quad_index)
+{
+ MeshExtract_LineAdjacency_Data *data = static_cast<MeshExtract_LineAdjacency_Data *>(_data);
+
+ const uint loop_index = subdiv_quad_index * 4;
+ const uint l0 = loop_index + 0;
+ const uint l1 = loop_index + 1;
+ const uint l2 = loop_index + 2;
+ const uint l3 = loop_index + 3;
+
+ const uint v0 = subdiv_cache->subdiv_loop_subdiv_vert_index[l0];
+ const uint v1 = subdiv_cache->subdiv_loop_subdiv_vert_index[l1];
+ const uint v2 = subdiv_cache->subdiv_loop_subdiv_vert_index[l2];
+ const uint v3 = subdiv_cache->subdiv_loop_subdiv_vert_index[l3];
+
+ lines_adjacency_triangle(v0, v1, v2, l0, l1, l2, data);
+ lines_adjacency_triangle(v0, v2, v3, l0, l2, l3, data);
+}
+
+static void extract_lines_adjacency_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *UNUSED(coarse_quad))
+{
+ extract_lines_adjacency_iter_subdiv(subdiv_cache, mr, _data, subdiv_quad_index);
+}
+
+static void extract_lines_adjacency_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *UNUSED(coarse_quad))
+{
+ extract_lines_adjacency_iter_subdiv(subdiv_cache, mr, _data, subdiv_quad_index);
+}
+
+static void extract_lines_adjacency_finish_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *_data)
+{
+ extract_lines_adjacency_finish(mr, cache, buf, _data);
+}
+
+#undef NO_EDGE
constexpr MeshExtract create_extractor_lines_adjacency()
{
@@ -182,6 +254,10 @@ constexpr MeshExtract create_extractor_lines_adjacency()
extractor.iter_looptri_bm = extract_lines_adjacency_iter_looptri_bm;
extractor.iter_looptri_mesh = extract_lines_adjacency_iter_looptri_mesh;
extractor.finish = extract_lines_adjacency_finish;
+ extractor.init_subdiv = extract_lines_adjacency_init_subdiv;
+ extractor.iter_subdiv_bm = extract_lines_adjacency_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_lines_adjacency_iter_subdiv_mesh;
+ extractor.finish_subdiv = extract_lines_adjacency_finish_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_LineAdjacency_Data);
extractor.use_threading = false;
@@ -189,10 +265,10 @@ constexpr MeshExtract create_extractor_lines_adjacency()
return extractor;
}
+/** \} */
+
} // namespace blender::draw
extern "C" {
const MeshExtract extract_lines_adjacency = blender::draw::create_extractor_lines_adjacency();
}
-
-/** \} */
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
index 494a43e97d1..f7eb5022cdc 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_lines_paint_mask.cc
@@ -103,8 +103,6 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data->select_map);
}
-/** \} */
-
constexpr MeshExtract create_extractor_lines_paint_mask()
{
MeshExtract extractor = {nullptr};
@@ -118,10 +116,10 @@ constexpr MeshExtract create_extractor_lines_paint_mask()
return extractor;
}
+/** \} */
+
} // namespace blender::draw
extern "C" {
const MeshExtract extract_lines_paint_mask = blender::draw::create_extractor_lines_paint_mask();
}
-
-/** \} */
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
index b801ba04162..c3f89ab96ee 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_points.cc
@@ -25,6 +25,7 @@
#include "MEM_guardedalloc.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -32,6 +33,7 @@ namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Point Indices
* \{ */
+
static void extract_points_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *UNUSED(buf),
@@ -154,6 +156,69 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr),
GPU_indexbuf_build_in_place(elb, ibo);
}
+static void extract_points_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *UNUSED(buffer),
+ void *data)
+{
+ GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
+ /* Copy the points as the data upload will free them. */
+ elb->data = (uint *)MEM_dupallocN(subdiv_cache->point_indices);
+ elb->index_len = mr->vert_len;
+ elb->index_min = 0;
+ elb->index_max = subdiv_cache->num_subdiv_loops + mr->loop_loose_len;
+ elb->prim_type = GPU_PRIM_POINTS;
+}
+
+static void extract_points_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ const MeshExtractLooseGeom *loose_geom,
+ void *UNUSED(buffer),
+ void *data)
+{
+ const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
+ if (loop_loose_len == 0) {
+ return;
+ }
+
+ GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(data);
+
+ const Mesh *coarse_mesh = subdiv_cache->mesh;
+ const MEdge *coarse_edges = coarse_mesh->medge;
+
+ uint offset = subdiv_cache->num_subdiv_loops;
+
+ for (int i = 0; i < loose_geom->edge_len; i++) {
+ const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
+ if (elb->data[loose_edge->v1] == -1u) {
+ GPU_indexbuf_set_point_vert(elb, loose_edge->v1, offset);
+ }
+ if (elb->data[loose_edge->v2] == -1u) {
+ GPU_indexbuf_set_point_vert(elb, loose_edge->v2, offset + 1);
+ }
+ offset += 2;
+ }
+
+ for (int i = 0; i < loose_geom->vert_len; i++) {
+ if (elb->data[loose_geom->verts[i]] == -1u) {
+ GPU_indexbuf_set_point_vert(elb, loose_geom->verts[i], offset);
+ }
+ offset += 1;
+ }
+}
+
+static void extract_points_finish_subdiv(const DRWSubdivCache *UNUSED(subdiv_cache),
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *_userdata)
+{
+ GPUIndexBufBuilder *elb = static_cast<GPUIndexBufBuilder *>(_userdata);
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buf);
+ GPU_indexbuf_build_in_place(elb, ibo);
+}
+
constexpr MeshExtract create_extractor_points()
{
MeshExtract extractor = {nullptr};
@@ -166,6 +231,9 @@ constexpr MeshExtract create_extractor_points()
extractor.iter_lvert_mesh = extract_points_iter_lvert_mesh;
extractor.task_reduce = extract_points_task_reduce;
extractor.finish = extract_points_finish;
+ extractor.init_subdiv = extract_points_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_points_loose_geom_subdiv;
+ extractor.finish_subdiv = extract_points_finish_subdiv;
extractor.use_threading = true;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(GPUIndexBufBuilder);
@@ -173,10 +241,10 @@ constexpr MeshExtract create_extractor_points()
return extractor;
}
+/** \} */
+
} // namespace blender::draw
extern "C" {
const MeshExtract extract_points = blender::draw::create_extractor_points();
}
-
-/** \} */
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
index 54e733d3d86..b1ace8bc6c9 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_ibo_tris.cc
@@ -25,6 +25,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
static void extract_tris_mat_task_reduce(void *_userdata_to, void *_userdata_from)
@@ -123,10 +125,37 @@ static void extract_tris_finish(const MeshRenderData *mr,
}
}
+static void extract_tris_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUIndexBuf *ibo = static_cast<GPUIndexBuf *>(buffer);
+ /* Initialize the index buffer, it was already allocated, it will be filled on the device. */
+ GPU_indexbuf_init_build_on_device(ibo, subdiv_cache->num_subdiv_triangles * 3);
+
+ if (cache->tris_per_mat) {
+ for (int i = 0; i < cache->mat_len; i++) {
+ if (cache->tris_per_mat[i] == nullptr) {
+ cache->tris_per_mat[i] = GPU_indexbuf_calloc();
+ }
+
+ /* Multiply by 6 since we have 2 triangles per quad. */
+ const int start = subdiv_cache->mat_start[i] * 6;
+ const int len = (subdiv_cache->mat_end[i] - subdiv_cache->mat_start[i]) * 6;
+ GPU_indexbuf_create_subrange_in_place(cache->tris_per_mat[i], ibo, start, len);
+ }
+ }
+
+ draw_subdiv_build_tris_buffer(subdiv_cache, ibo, cache->mat_len);
+}
+
constexpr MeshExtract create_extractor_tris()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_tris_init;
+ extractor.init_subdiv = extract_tris_init_subdiv;
extractor.iter_poly_bm = extract_tris_iter_poly_bm;
extractor.iter_poly_mesh = extract_tris_iter_poly_mesh;
extractor.task_reduce = extract_tris_mat_task_reduce;
@@ -214,6 +243,7 @@ constexpr MeshExtract create_extractor_tris_single_mat()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_tris_single_mat_init;
+ extractor.init_subdiv = extract_tris_init_subdiv;
extractor.iter_looptri_bm = extract_tris_single_mat_iter_looptri_bm;
extractor.iter_looptri_mesh = extract_tris_single_mat_iter_looptri_mesh;
extractor.task_reduce = extract_tris_mat_task_reduce;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc
new file mode 100644
index 00000000000..b846da3f016
--- /dev/null
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc
@@ -0,0 +1,489 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2021 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup draw
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include <functional>
+
+#include "BLI_math_vec_types.hh"
+#include "BLI_string.h"
+
+#include "BKE_attribute.h"
+
+#include "draw_subdivision.h"
+#include "extract_mesh.h"
+
+namespace blender::draw {
+
+/* ---------------------------------------------------------------------- */
+/** \name Extract Attributes
+ * \{ */
+
+static CustomData *get_custom_data_for_domain(const MeshRenderData *mr, AttributeDomain domain)
+{
+ switch (domain) {
+ default: {
+ return nullptr;
+ }
+ case ATTR_DOMAIN_POINT: {
+ return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
+ }
+ case ATTR_DOMAIN_CORNER: {
+ return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ }
+ case ATTR_DOMAIN_FACE: {
+ return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->pdata : &mr->me->pdata;
+ }
+ case ATTR_DOMAIN_EDGE: {
+ return (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->edata : &mr->me->edata;
+ }
+ }
+}
+
+/* Utility to convert from the type used in the attributes to the types for the VBO.
+ * This is mostly used to promote integers and booleans to floats, as other types (float, float2,
+ * etc.) directly map to available GPU types. Booleans are still converted as attributes are vec4
+ * in the shader.
+ */
+template<typename AttributeType, typename VBOType> struct attribute_type_converter {
+ static VBOType convert_value(AttributeType value)
+ {
+ if constexpr (std::is_same_v<AttributeType, VBOType>) {
+ return value;
+ }
+
+ /* This should only concern bools which are converted to floats. */
+ return static_cast<VBOType>(value);
+ }
+};
+
+/* Similar to the one in #extract_mesh_vcol_vbo.cc */
+struct gpuMeshCol {
+ ushort r, g, b, a;
+};
+
+template<> struct attribute_type_converter<MPropCol, gpuMeshCol> {
+ static gpuMeshCol convert_value(MPropCol value)
+ {
+ gpuMeshCol result;
+ result.r = unit_float_to_ushort_clamp(value.color[0]);
+ result.g = unit_float_to_ushort_clamp(value.color[1]);
+ result.b = unit_float_to_ushort_clamp(value.color[2]);
+ result.a = unit_float_to_ushort_clamp(value.color[3]);
+ return result;
+ }
+};
+
+/* Return the number of component for the attribute's value type, or 0 if is it unsupported. */
+static uint gpu_component_size_for_attribute_type(CustomDataType type)
+{
+ switch (type) {
+ case CD_PROP_BOOL:
+ case CD_PROP_INT32:
+ case CD_PROP_FLOAT: {
+ /* TODO(kevindietrich) : should be 1 when scalar attributes conversion is handled by us. See
+ * comment #extract_attr_init. */
+ return 3;
+ }
+ case CD_PROP_FLOAT2: {
+ return 2;
+ }
+ case CD_PROP_FLOAT3: {
+ return 3;
+ }
+ case CD_PROP_COLOR: {
+ return 4;
+ }
+ default: {
+ return 0;
+ }
+ }
+}
+
+static GPUVertFetchMode get_fetch_mode_for_type(CustomDataType type)
+{
+ switch (type) {
+ case CD_PROP_INT32: {
+ return GPU_FETCH_INT_TO_FLOAT;
+ }
+ case CD_PROP_COLOR: {
+ return GPU_FETCH_INT_TO_FLOAT_UNIT;
+ }
+ default: {
+ return GPU_FETCH_FLOAT;
+ }
+ }
+}
+
+static GPUVertCompType get_comp_type_for_type(CustomDataType type)
+{
+ switch (type) {
+ case CD_PROP_INT32: {
+ return GPU_COMP_I32;
+ }
+ case CD_PROP_COLOR: {
+ return GPU_COMP_U16;
+ }
+ default: {
+ return GPU_COMP_F32;
+ }
+ }
+}
+
+static void init_vbo_for_attribute(const MeshRenderData *mr,
+ GPUVertBuf *vbo,
+ const DRW_AttributeRequest &request,
+ bool build_on_device,
+ uint32_t len)
+{
+ GPUVertCompType comp_type = get_comp_type_for_type(request.cd_type);
+ GPUVertFetchMode fetch_mode = get_fetch_mode_for_type(request.cd_type);
+ const uint comp_size = gpu_component_size_for_attribute_type(request.cd_type);
+ /* We should not be here if the attribute type is not supported. */
+ BLI_assert(comp_size != 0);
+
+ const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain);
+ char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
+ const char *layer_name = CustomData_get_layer_name(
+ custom_data, request.cd_type, request.layer_index);
+ GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+ /* Attributes use auto-name. */
+ BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
+
+ GPUVertFormat format = {0};
+ GPU_vertformat_deinterleave(&format);
+ GPU_vertformat_attr_add(&format, attr_name, comp_type, comp_size, fetch_mode);
+
+ /* Ensure Sculpt Vertex Colors are properly aliased. */
+ if (request.cd_type == CD_PROP_COLOR && request.domain == ATTR_DOMAIN_POINT) {
+ CustomData *cd_vdata = get_custom_data_for_domain(mr, ATTR_DOMAIN_POINT);
+ if (request.layer_index == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "c");
+ }
+ if (request.layer_index == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
+ GPU_vertformat_alias_add(&format, "ac");
+ }
+ }
+
+ if (build_on_device) {
+ GPU_vertbuf_init_build_on_device(vbo, &format, len);
+ }
+ else {
+ GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_data_alloc(vbo, len);
+ }
+}
+
+template<typename AttributeType, typename VBOType>
+static void fill_vertbuf_with_attribute(const MeshRenderData *mr,
+ VBOType *vbo_data,
+ const DRW_AttributeRequest &request)
+{
+ const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain);
+ BLI_assert(custom_data);
+ const int layer_index = request.layer_index;
+
+ const MPoly *mpoly = mr->mpoly;
+ const MLoop *mloop = mr->mloop;
+
+ const AttributeType *attr_data = static_cast<AttributeType *>(
+ CustomData_get_layer_n(custom_data, request.cd_type, layer_index));
+
+ using converter = attribute_type_converter<AttributeType, VBOType>;
+
+ switch (request.domain) {
+ default: {
+ BLI_assert(false);
+ break;
+ }
+ case ATTR_DOMAIN_POINT: {
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) {
+ *vbo_data = converter::convert_value(attr_data[mloop->v]);
+ }
+ break;
+ }
+ case ATTR_DOMAIN_CORNER: {
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++) {
+ *vbo_data = converter::convert_value(attr_data[ml_index]);
+ }
+ break;
+ }
+ case ATTR_DOMAIN_EDGE: {
+ for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vbo_data++, mloop++) {
+ *vbo_data = converter::convert_value(attr_data[mloop->e]);
+ }
+ break;
+ }
+ case ATTR_DOMAIN_FACE: {
+ for (int mp_index = 0; mp_index < mr->poly_len; mp_index++) {
+ const MPoly &poly = mpoly[mp_index];
+ const VBOType value = converter::convert_value(attr_data[mp_index]);
+ for (int l = 0; l < poly.totloop; l++) {
+ *vbo_data++ = value;
+ }
+ }
+ break;
+ }
+ }
+}
+
+template<typename AttributeType, typename VBOType>
+static void fill_vertbuf_with_attribute_bm(const MeshRenderData *mr,
+ VBOType *&vbo_data,
+ const DRW_AttributeRequest &request)
+{
+ const CustomData *custom_data = get_custom_data_for_domain(mr, request.domain);
+ BLI_assert(custom_data);
+ const int layer_index = request.layer_index;
+
+ int cd_ofs = CustomData_get_n_offset(custom_data, request.cd_type, layer_index);
+
+ using converter = attribute_type_converter<AttributeType, VBOType>;
+
+ BMIter f_iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ do {
+ const AttributeType *attr_data = nullptr;
+ if (request.domain == ATTR_DOMAIN_POINT) {
+ attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs));
+ }
+ else if (request.domain == ATTR_DOMAIN_CORNER) {
+ attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter, cd_ofs));
+ }
+ else if (request.domain == ATTR_DOMAIN_FACE) {
+ attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(efa, cd_ofs));
+ }
+ else if (request.domain == ATTR_DOMAIN_EDGE) {
+ attr_data = static_cast<const AttributeType *>(BM_ELEM_CD_GET_VOID_P(l_iter->e, cd_ofs));
+ }
+ else {
+ BLI_assert(false);
+ continue;
+ }
+ *vbo_data = converter::convert_value(*attr_data);
+ vbo_data++;
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+}
+
+template<typename AttributeType, typename VBOType = AttributeType>
+static void extract_attr_generic(const MeshRenderData *mr,
+ GPUVertBuf *vbo,
+ const DRW_AttributeRequest &request)
+{
+ VBOType *vbo_data = static_cast<VBOType *>(GPU_vertbuf_get_data(vbo));
+
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ fill_vertbuf_with_attribute_bm<AttributeType>(mr, vbo_data, request);
+ }
+ else {
+ fill_vertbuf_with_attribute<AttributeType>(mr, vbo_data, request);
+ }
+}
+
+static void extract_attr_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data),
+ int index)
+{
+ const DRW_MeshAttributes *attrs_used = &cache->attr_used;
+ const DRW_AttributeRequest &request = attrs_used->requests[index];
+
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+
+ init_vbo_for_attribute(mr, vbo, request, false, static_cast<uint32_t>(mr->loop_len));
+
+ /* TODO(kevindietrich) : float3 is used for scalar attributes as the implicit conversion done by
+ * OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the
+ * Blender convention, it should be `vec4(s, s, s, 1)`. This could be resolved using a similar
+ * texture as for volume attribute, so we can control the conversion ourselves. */
+ switch (request.cd_type) {
+ case CD_PROP_BOOL: {
+ extract_attr_generic<bool, float3>(mr, vbo, request);
+ break;
+ }
+ case CD_PROP_INT32: {
+ extract_attr_generic<int32_t, float3>(mr, vbo, request);
+ break;
+ }
+ case CD_PROP_FLOAT: {
+ extract_attr_generic<float, float3>(mr, vbo, request);
+ break;
+ }
+ case CD_PROP_FLOAT2: {
+ extract_attr_generic<float2>(mr, vbo, request);
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ extract_attr_generic<float3>(mr, vbo, request);
+ break;
+ }
+ case CD_PROP_COLOR: {
+ extract_attr_generic<MPropCol, gpuMeshCol>(mr, vbo, request);
+ break;
+ }
+ default: {
+ BLI_assert(false);
+ }
+ }
+}
+
+static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(tls_data),
+ int index)
+{
+ const DRW_MeshAttributes *attrs_used = &cache->attr_used;
+ const DRW_AttributeRequest &request = attrs_used->requests[index];
+
+ Mesh *coarse_mesh = subdiv_cache->mesh;
+
+ const uint32_t dimensions = gpu_component_size_for_attribute_type(request.cd_type);
+
+ /* Prepare VBO for coarse data. The compute shader only expects floats. */
+ GPUVertBuf *src_data = GPU_vertbuf_calloc();
+ static GPUVertFormat coarse_format = {0};
+ GPU_vertformat_attr_add(&coarse_format, "data", GPU_COMP_F32, dimensions, GPU_FETCH_FLOAT);
+ GPU_vertbuf_init_with_format_ex(src_data, &coarse_format, GPU_USAGE_STATIC);
+ GPU_vertbuf_data_alloc(src_data, static_cast<uint32_t>(coarse_mesh->totloop));
+
+ switch (request.cd_type) {
+ case CD_PROP_BOOL: {
+ extract_attr_generic<bool, float3>(mr, src_data, request);
+ break;
+ }
+ case CD_PROP_INT32: {
+ extract_attr_generic<int32_t, float3>(mr, src_data, request);
+ break;
+ }
+ case CD_PROP_FLOAT: {
+ extract_attr_generic<float, float3>(mr, src_data, request);
+ break;
+ }
+ case CD_PROP_FLOAT2: {
+ extract_attr_generic<float2>(mr, src_data, request);
+ break;
+ }
+ case CD_PROP_FLOAT3: {
+ extract_attr_generic<float3>(mr, src_data, request);
+ break;
+ }
+ case CD_PROP_COLOR: {
+ extract_attr_generic<MPropCol, gpuMeshCol>(mr, src_data, request);
+ break;
+ }
+ default: {
+ BLI_assert(false);
+ }
+ }
+
+ GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer);
+ init_vbo_for_attribute(mr, dst_buffer, request, true, subdiv_cache->num_subdiv_loops);
+
+ /* Ensure data is uploaded properly. */
+ GPU_vertbuf_tag_dirty(src_data);
+ draw_subdiv_interp_custom_data(
+ subdiv_cache, src_data, dst_buffer, static_cast<int>(dimensions), 0);
+
+ GPU_vertbuf_discard(src_data);
+}
+
+/* Wrappers around extract_attr_init so we can pass the index of the attribute that we want to
+ * extract. The overall API does not allow us to pass this in a convenient way. */
+#define EXTRACT_INIT_WRAPPER(index) \
+ static void extract_attr_init##index( \
+ const MeshRenderData *mr, struct MeshBatchCache *cache, void *buf, void *tls_data) \
+ { \
+ extract_attr_init(mr, cache, buf, tls_data, index); \
+ } \
+ static void extract_attr_init_subdiv##index(const DRWSubdivCache *subdiv_cache, \
+ const MeshRenderData *mr, \
+ struct MeshBatchCache *cache, \
+ void *buf, \
+ void *tls_data) \
+ { \
+ extract_attr_init_subdiv(subdiv_cache, mr, cache, buf, tls_data, index); \
+ }
+
+EXTRACT_INIT_WRAPPER(0)
+EXTRACT_INIT_WRAPPER(1)
+EXTRACT_INIT_WRAPPER(2)
+EXTRACT_INIT_WRAPPER(3)
+EXTRACT_INIT_WRAPPER(4)
+EXTRACT_INIT_WRAPPER(5)
+EXTRACT_INIT_WRAPPER(6)
+EXTRACT_INIT_WRAPPER(7)
+EXTRACT_INIT_WRAPPER(8)
+EXTRACT_INIT_WRAPPER(9)
+EXTRACT_INIT_WRAPPER(10)
+EXTRACT_INIT_WRAPPER(11)
+EXTRACT_INIT_WRAPPER(12)
+EXTRACT_INIT_WRAPPER(13)
+EXTRACT_INIT_WRAPPER(14)
+
+template<int index>
+constexpr MeshExtract create_extractor_attr(ExtractInitFn fn, ExtractInitSubdivFn subdiv_fn)
+{
+ MeshExtract extractor = {nullptr};
+ extractor.init = fn;
+ extractor.init_subdiv = subdiv_fn;
+ extractor.data_type = MR_DATA_NONE;
+ extractor.data_size = 0;
+ extractor.use_threading = false;
+ extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.attr[index]);
+ return extractor;
+}
+
+/** \} */
+
+} // namespace blender::draw
+
+extern "C" {
+#define CREATE_EXTRACTOR_ATTR(index) \
+ blender::draw::create_extractor_attr<index>(blender::draw::extract_attr_init##index, \
+ blender::draw::extract_attr_init_subdiv##index)
+
+const MeshExtract extract_attr[GPU_MAX_ATTR] = {
+ CREATE_EXTRACTOR_ATTR(0),
+ CREATE_EXTRACTOR_ATTR(1),
+ CREATE_EXTRACTOR_ATTR(2),
+ CREATE_EXTRACTOR_ATTR(3),
+ CREATE_EXTRACTOR_ATTR(4),
+ CREATE_EXTRACTOR_ATTR(5),
+ CREATE_EXTRACTOR_ATTR(6),
+ CREATE_EXTRACTOR_ATTR(7),
+ CREATE_EXTRACTOR_ATTR(8),
+ CREATE_EXTRACTOR_ATTR(9),
+ CREATE_EXTRACTOR_ATTR(10),
+ CREATE_EXTRACTOR_ATTR(11),
+ CREATE_EXTRACTOR_ATTR(12),
+ CREATE_EXTRACTOR_ATTR(13),
+ CREATE_EXTRACTOR_ATTR(14),
+};
+}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
index 2e2444a8e3d..8470a71059f 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edge_fac.cc
@@ -25,6 +25,7 @@
#include "GPU_capabilities.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -148,9 +149,8 @@ static void extract_edge_fac_iter_poly_mesh(const MeshRenderData *mr,
const MLoop *ml_next = &mr->mloop[ml_index_other];
const MVert *v1 = &mr->mvert[ml->v];
const MVert *v2 = &mr->mvert[ml_next->v];
- float vnor_f[3];
- normal_short_to_float_v3(vnor_f, v1->no);
- float ratio = loop_edge_factor_get(mr->poly_normals[mp_index], v1->co, vnor_f, v2->co);
+ float ratio = loop_edge_factor_get(
+ mr->poly_normals[mp_index], v1->co, mr->vert_normals[ml->v], v2->co);
data->vbo_data[ml_index] = ratio * 253 + 1;
}
else {
@@ -216,6 +216,86 @@ static void extract_edge_fac_finish(const MeshRenderData *mr,
MEM_SAFE_FREE(data->edge_loop_count);
}
+/* Different function than the one used for the non-subdivision case, as we directly take care of
+ * the buggy AMD driver case. */
+static GPUVertFormat *get_subdiv_edge_fac_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ if (GPU_crappy_amd_driver()) {
+ GPU_vertformat_attr_add(&format, "wd", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ else {
+ GPU_vertformat_attr_add(&format, "wd", GPU_COMP_U8, 1, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ }
+ }
+ return &format;
+}
+
+static void extract_edge_fac_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUVertBuf *edge_idx = cache->final.buff.vbo.edge_idx;
+ GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor;
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ GPU_vertbuf_init_build_on_device(
+ vbo, get_subdiv_edge_fac_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
+
+ /* Create a temporary buffer for the edge original indices if it was not requested. */
+ const bool has_edge_idx = edge_idx != nullptr;
+ GPUVertBuf *loop_edge_idx = nullptr;
+ if (has_edge_idx) {
+ loop_edge_idx = edge_idx;
+ }
+ else {
+ loop_edge_idx = GPU_vertbuf_calloc();
+ draw_subdiv_init_origindex_buffer(
+ loop_edge_idx,
+ static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)),
+ subdiv_cache->num_subdiv_loops,
+ 0);
+ }
+
+ draw_subdiv_build_edge_fac_buffer(subdiv_cache, pos_nor, loop_edge_idx, vbo);
+
+ if (!has_edge_idx) {
+ GPU_vertbuf_discard(loop_edge_idx);
+ }
+}
+
+static void extract_edge_fac_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *UNUSED(data))
+{
+ if (loose_geom->edge_len == 0) {
+ return;
+ }
+
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+
+ /* Make sure buffer is active for sending loose data. */
+ GPU_vertbuf_use(vbo);
+
+ uint offset = subdiv_cache->num_subdiv_loops;
+ for (int i = 0; i < loose_geom->edge_len; i++) {
+ if (GPU_crappy_amd_driver()) {
+ float loose_edge_fac[2] = {1.0f, 1.0f};
+ GPU_vertbuf_update_sub(vbo, offset * sizeof(float), sizeof(loose_edge_fac), loose_edge_fac);
+ }
+ else {
+ char loose_edge_fac[2] = {255, 255};
+ GPU_vertbuf_update_sub(vbo, offset * sizeof(char), sizeof(loose_edge_fac), loose_edge_fac);
+ }
+
+ offset += 2;
+ }
+}
+
constexpr MeshExtract create_extractor_edge_fac()
{
MeshExtract extractor = {nullptr};
@@ -224,6 +304,8 @@ constexpr MeshExtract create_extractor_edge_fac()
extractor.iter_poly_mesh = extract_edge_fac_iter_poly_mesh;
extractor.iter_ledge_bm = extract_edge_fac_iter_ledge_bm;
extractor.iter_ledge_mesh = extract_edge_fac_iter_ledge_mesh;
+ extractor.init_subdiv = extract_edge_fac_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_edge_fac_loose_geom_subdiv;
extractor.finish = extract_edge_fac_finish;
extractor.data_type = MR_DATA_POLY_NOR;
extractor.data_size = sizeof(MeshExtract_EdgeFac_Data);
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
index 5232346e51e..0002b95c867 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edit_data.cc
@@ -25,6 +25,8 @@
#include "draw_cache_impl.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -70,11 +72,11 @@ static void mesh_render_data_edge_flag(const MeshRenderData *mr,
}
}
- /* Use a byte for value range */
- if (mr->crease_ofs != -1) {
- float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->crease_ofs);
+ /* Use half a byte for value range */
+ if (mr->edge_crease_ofs != -1) {
+ float crease = BM_ELEM_CD_GET_FLOAT(eed, mr->edge_crease_ofs);
if (crease > 0) {
- eattr->crease = (uchar)(crease * 255.0f);
+ eattr->crease = (uchar)ceil(crease * 15.0f);
}
}
/* Use a byte for value range */
@@ -105,21 +107,34 @@ static void mesh_render_data_vert_flag(const MeshRenderData *mr,
if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) {
eattr->e_flag |= VFLAG_VERT_SELECTED;
}
+ /* Use half a byte for value range */
+ if (mr->vert_crease_ofs != -1) {
+ float crease = BM_ELEM_CD_GET_FLOAT(eve, mr->vert_crease_ofs);
+ if (crease > 0) {
+ eattr->crease |= (uchar)ceil(crease * 15.0f) << 4;
+ }
+ }
}
-static void extract_edit_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
+static GPUVertFormat *get_edit_data_format()
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING: Adjust #EditLoopData struct accordingly. */
GPU_vertformat_attr_add(&format, "data", GPU_COMP_U8, 4, GPU_FETCH_INT);
GPU_vertformat_alias_add(&format, "flag");
}
- GPU_vertbuf_init_with_format(vbo, &format);
+ return &format;
+}
+
+static void extract_edit_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat *format = get_edit_data_format();
+ GPU_vertbuf_init_with_format(vbo, format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len + mr->loop_loose_len);
EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
*(EditLoopData **)tls_data = vbo_data;
@@ -240,6 +255,92 @@ static void extract_edit_data_iter_lvert_mesh(const MeshRenderData *mr,
}
}
+static void extract_edit_data_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPU_vertbuf_init_with_format(vbo, get_edit_data_format());
+ GPU_vertbuf_data_alloc(vbo, subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
+ EditLoopData *vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
+ *(EditLoopData **)data = vbo_data;
+}
+
+static void extract_edit_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_quad)
+{
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+ int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
+ int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint i = start_loop_idx; i < end_loop_idx; i++) {
+ const int vert_origindex = subdiv_loop_vert_index[i];
+ const int edge_origindex = subdiv_loop_edge_index[i];
+
+ EditLoopData *edit_loop_data = &vbo_data[i];
+ memset(edit_loop_data, 0, sizeof(EditLoopData));
+
+ if (vert_origindex != -1) {
+ const BMVert *eve = bm_original_vert_get(mr, vert_origindex);
+ if (eve) {
+ mesh_render_data_vert_flag(mr, eve, edit_loop_data);
+ }
+ }
+
+ if (edge_origindex != -1) {
+ const BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
+ if (eed) {
+ mesh_render_data_edge_flag(mr, eed, edit_loop_data);
+ }
+ }
+
+ /* The -1 parameter is for edit_uvs, which we don't do here. */
+ mesh_render_data_face_flag(mr, coarse_quad, -1, edit_loop_data);
+ }
+}
+
+static void extract_edit_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad)
+{
+ const int coarse_quad_index = static_cast<int>(coarse_quad - mr->mpoly);
+ BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index);
+ extract_edit_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm);
+}
+
+static void extract_edit_data_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ const MeshExtractLooseGeom *loose_geom,
+ void *UNUSED(buffer),
+ void *_data)
+{
+ if (loose_geom->edge_len == 0) {
+ return;
+ }
+
+ EditLoopData *vbo_data = *(EditLoopData **)_data;
+
+ for (int ledge_index = 0; ledge_index < loose_geom->edge_len; ledge_index++) {
+ const int offset = subdiv_cache->num_subdiv_loops + ledge_index * 2;
+ EditLoopData *data = &vbo_data[offset];
+ memset(data, 0, sizeof(EditLoopData));
+ BMEdge *eed = bm_original_edge_get(mr, loose_geom->edges[ledge_index]);
+ mesh_render_data_edge_flag(mr, eed, &data[0]);
+ data[1] = data[0];
+ mesh_render_data_vert_flag(mr, eed->v1, &data[0]);
+ mesh_render_data_vert_flag(mr, eed->v2, &data[1]);
+ }
+}
+
constexpr MeshExtract create_extractor_edit_data()
{
MeshExtract extractor = {nullptr};
@@ -250,6 +351,10 @@ constexpr MeshExtract create_extractor_edit_data()
extractor.iter_ledge_mesh = extract_edit_data_iter_ledge_mesh;
extractor.iter_lvert_bm = extract_edit_data_iter_lvert_bm;
extractor.iter_lvert_mesh = extract_edit_data_iter_lvert_mesh;
+ extractor.init_subdiv = extract_edit_data_init_subdiv;
+ extractor.iter_subdiv_bm = extract_edit_data_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_edit_data_iter_subdiv_mesh;
+ extractor.iter_loose_geom_subdiv = extract_edit_data_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(EditLoopData *);
extractor.use_threading = true;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
index b8494428eed..b25e40690c9 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_data.cc
@@ -25,6 +25,8 @@
#include "draw_cache_impl.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -36,12 +38,11 @@ struct MeshExtract_EditUVData_Data {
int cd_ofs;
};
-static void extract_edituv_data_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
+static void extract_edituv_data_init_common(const MeshRenderData *mr,
+ GPUVertBuf *vbo,
+ MeshExtract_EditUVData_Data *data,
+ uint loop_len)
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* WARNING: Adjust #EditLoopData struct accordingly. */
@@ -50,15 +51,23 @@ static void extract_edituv_data_init(const MeshRenderData *mr,
}
GPU_vertbuf_init_with_format(vbo, &format);
- GPU_vertbuf_data_alloc(vbo, mr->loop_len);
+ GPU_vertbuf_data_alloc(vbo, loop_len);
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
-
- MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
data->vbo_data = (EditLoopData *)GPU_vertbuf_get_data(vbo);
data->cd_ofs = CustomData_get_offset(cd_ldata, CD_MLOOPUV);
}
+static void extract_edituv_data_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
+ extract_edituv_data_init_common(mr, vbo, data, mr->loop_len);
+}
+
static void extract_edituv_data_iter_poly_bm(const MeshRenderData *mr,
const BMFace *f,
const int UNUSED(f_index),
@@ -119,12 +128,66 @@ static void extract_edituv_data_iter_poly_mesh(const MeshRenderData *mr,
}
}
+static void extract_edituv_data_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(tls_data);
+ extract_edituv_data_init_common(mr, vbo, data, subdiv_cache->num_subdiv_loops);
+}
+
+static void extract_edituv_data_iter_subdiv_bm(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const BMFace *coarse_quad)
+{
+ MeshExtract_EditUVData_Data *data = static_cast<MeshExtract_EditUVData_Data *>(_data);
+ int *subdiv_loop_vert_index = (int *)GPU_vertbuf_get_data(subdiv_cache->verts_orig_index);
+ int *subdiv_loop_edge_index = (int *)GPU_vertbuf_get_data(subdiv_cache->edges_orig_index);
+
+ uint start_loop_idx = subdiv_quad_index * 4;
+ uint end_loop_idx = (subdiv_quad_index + 1) * 4;
+ for (uint i = start_loop_idx; i < end_loop_idx; i++) {
+ const int vert_origindex = subdiv_loop_vert_index[i];
+ const int edge_origindex = subdiv_loop_edge_index[i];
+
+ EditLoopData *edit_loop_data = &data->vbo_data[i];
+ memset(edit_loop_data, 0, sizeof(EditLoopData));
+
+ if (vert_origindex != -1 && edge_origindex != -1) {
+ BMEdge *eed = bm_original_edge_get(mr, edge_origindex);
+ /* Loop on an edge endpoint. */
+ BMLoop *l = BM_face_edge_share_loop(const_cast<BMFace *>(coarse_quad), eed);
+ mesh_render_data_loop_flag(mr, l, data->cd_ofs, edit_loop_data);
+ mesh_render_data_loop_edge_flag(mr, l, data->cd_ofs, edit_loop_data);
+ }
+ }
+}
+
+static void extract_edituv_data_iter_subdiv_mesh(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ void *_data,
+ uint subdiv_quad_index,
+ const MPoly *coarse_quad)
+{
+ const int coarse_quad_index = static_cast<int>(coarse_quad - mr->mpoly);
+ BMFace *coarse_quad_bm = bm_original_face_get(mr, coarse_quad_index);
+ extract_edituv_data_iter_subdiv_bm(subdiv_cache, mr, _data, subdiv_quad_index, coarse_quad_bm);
+}
+
constexpr MeshExtract create_extractor_edituv_data()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_edituv_data_init;
extractor.iter_poly_bm = extract_edituv_data_iter_poly_bm;
extractor.iter_poly_mesh = extract_edituv_data_iter_poly_mesh;
+ extractor.init_subdiv = extract_edituv_data_init_subdiv;
+ extractor.iter_subdiv_bm = extract_edituv_data_iter_subdiv_bm;
+ extractor.iter_subdiv_mesh = extract_edituv_data_iter_subdiv_mesh;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_EditUVData_Data);
extractor.use_threading = true;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
index a947d98f955..49b23ff1efe 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_angle.cc
@@ -27,6 +27,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -213,12 +215,69 @@ static void extract_edituv_stretch_angle_iter_poly_mesh(const MeshRenderData *mr
}
}
+static GPUVertFormat *get_edituv_stretch_angle_format_subdiv()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ /* Waning: adjust #UVStretchAngle struct accordingly. */
+ GPU_vertformat_attr_add(&format, "angle", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "uv_angles", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ }
+ return &format;
+}
+
+static void extract_edituv_stretch_angle_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *refined_vbo = static_cast<GPUVertBuf *>(buffer);
+
+ GPU_vertbuf_init_build_on_device(
+ refined_vbo, get_edituv_stretch_angle_format_subdiv(), subdiv_cache->num_subdiv_loops);
+
+ GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor;
+ GPUVertBuf *uvs = cache->final.buff.vbo.uv;
+
+ /* UVs are stored contiguously so we need to compute the offset in the UVs buffer for the active
+ * UV layer. */
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_MESH) ? &mr->me->ldata : &mr->bm->ldata;
+
+ uint32_t uv_layers = cache->cd_used.uv;
+ /* HACK to fix T68857 */
+ if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
+ int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
+ if (layer != -1) {
+ uv_layers |= (1 << layer);
+ }
+ }
+
+ int uvs_offset = 0;
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (uv_layers & (1 << i)) {
+ if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
+ break;
+ }
+
+ uvs_offset += 1;
+ }
+ }
+
+ /* The data is at `offset * num loops`, and we have 2 values per index. */
+ uvs_offset *= subdiv_cache->num_subdiv_loops * 2;
+
+ draw_subdiv_build_edituv_stretch_angle_buffer(
+ subdiv_cache, pos_nor, uvs, uvs_offset, refined_vbo);
+}
+
constexpr MeshExtract create_extractor_edituv_edituv_stretch_angle()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_edituv_stretch_angle_init;
extractor.iter_poly_bm = extract_edituv_stretch_angle_iter_poly_bm;
extractor.iter_poly_mesh = extract_edituv_stretch_angle_iter_poly_mesh;
+ extractor.init_subdiv = extract_edituv_stretch_angle_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_StretchAngle_Data);
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
index 3db8cd79af5..c116fa5ba07 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_edituv_stretch_area.cc
@@ -27,6 +27,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -63,14 +65,12 @@ BLI_INLINE float area_ratio_to_stretch(float ratio, float tot_ratio, float inv_t
return (ratio > 1.0f) ? (1.0f / ratio) : ratio;
}
-static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(data))
+static void compute_area_ratio(const MeshRenderData *mr,
+ float *r_area_ratio,
+ float &r_tot_area,
+ float &r_tot_uv_area)
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
float tot_area = 0.0f, tot_uv_area = 0.0f;
- float *area_ratio = static_cast<float *>(MEM_mallocN(sizeof(float) * mr->poly_len, __func__));
if (mr->extract_type == MR_EXTRACT_BMESH) {
CustomData *cd_ldata = &mr->bm->ldata;
@@ -84,7 +84,7 @@ static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
float uvarea = BM_face_calc_area_uv(efa, uv_ofs);
tot_area += area;
tot_uv_area += uvarea;
- area_ratio[f] = area_ratio_get(area, uvarea);
+ r_area_ratio[f] = area_ratio_get(area, uvarea);
}
}
else {
@@ -96,12 +96,22 @@ static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
float uvarea = BKE_mesh_calc_poly_uv_area(mp, uv_data);
tot_area += area;
tot_uv_area += uvarea;
- area_ratio[mp_index] = area_ratio_get(area, uvarea);
+ r_area_ratio[mp_index] = area_ratio_get(area, uvarea);
}
}
- cache->tot_area = tot_area;
- cache->tot_uv_area = tot_uv_area;
+ r_tot_area = tot_area;
+ r_tot_uv_area = tot_uv_area;
+}
+
+static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ float *area_ratio = static_cast<float *>(MEM_mallocN(sizeof(float) * mr->poly_len, __func__));
+ compute_area_ratio(mr, area_ratio, cache->tot_area, cache->tot_uv_area);
/* Convert in place to avoid an extra allocation */
uint16_t *poly_stretch = (uint16_t *)area_ratio;
@@ -135,11 +145,46 @@ static void extract_edituv_stretch_area_finish(const MeshRenderData *mr,
MEM_freeN(area_ratio);
}
+static void extract_edituv_stretch_area_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+
+ /* Initialize final buffer. */
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "ratio", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+
+ GPU_vertbuf_init_build_on_device(vbo, &format, subdiv_cache->num_subdiv_loops);
+
+ /* Initialize coarse data buffer. */
+
+ GPUVertBuf *coarse_data = GPU_vertbuf_calloc();
+
+ /* We use the same format as we just copy data around. */
+ GPU_vertbuf_init_with_format(coarse_data, &format);
+ GPU_vertbuf_data_alloc(coarse_data, mr->loop_len);
+
+ compute_area_ratio(mr,
+ static_cast<float *>(GPU_vertbuf_get_data(coarse_data)),
+ cache->tot_area,
+ cache->tot_uv_area);
+
+ draw_subdiv_build_edituv_stretch_area_buffer(subdiv_cache, coarse_data, vbo);
+
+ GPU_vertbuf_discard(coarse_data);
+}
+
constexpr MeshExtract create_extractor_edituv_stretch_area()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_edituv_stretch_area_init;
extractor.finish = extract_edituv_stretch_area_finish;
+ extractor.init_subdiv = extract_edituv_stretch_area_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
index fed66f0057d..b2ebff08abf 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_nor.cc
@@ -28,6 +28,7 @@ namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Face-dots Normal and edit flag
* \{ */
+
#define NOR_AND_FLAG_DEFAULT 0
#define NOR_AND_FLAG_SELECT 1
#define NOR_AND_FLAG_ACTIVE -1
@@ -114,6 +115,7 @@ constexpr MeshExtract create_extractor_fdots_nor()
/* ---------------------------------------------------------------------- */
/** \name Extract Face-dots High Quality Normal and edit flag
* \{ */
+
static void extract_fdots_nor_hq_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf,
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
index 33f9180e122..f65159f9b95 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_fdots_pos.cc
@@ -23,24 +23,40 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
/** \name Extract Face-dots positions
* \{ */
-static void extract_fdots_pos_init(const MeshRenderData *mr,
- struct MeshBatchCache *UNUSED(cache),
- void *buf,
- void *tls_data)
+static GPUVertFormat *get_fdots_pos_format()
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
}
+ return &format;
+}
+
+static GPUVertFormat *get_fdots_nor_format_subdiv()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "norAndFlag", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ }
+ return &format;
+}
- GPU_vertbuf_init_with_format(vbo, &format);
+static void extract_fdots_pos_init(const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *tls_data)
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat *format = get_fdots_pos_format();
+ GPU_vertbuf_init_with_format(vbo, format);
GPU_vertbuf_data_alloc(vbo, mr->poly_len);
void *vbo_data = GPU_vertbuf_get_data(vbo);
*(float(**)[3])tls_data = static_cast<float(*)[3]>(vbo_data);
@@ -97,10 +113,30 @@ static void extract_fdots_pos_iter_poly_mesh(const MeshRenderData *mr,
}
}
+static void extract_fdots_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ /* We "extract" positions, normals, and indices at once. */
+ GPUVertBuf *fdots_pos_vbo = static_cast<GPUVertBuf *>(buffer);
+ GPUVertBuf *fdots_nor_vbo = cache->final.buff.vbo.fdots_nor;
+ GPUIndexBuf *fdots_pos_ibo = cache->final.buff.ibo.fdots;
+
+ GPU_vertbuf_init_build_on_device(
+ fdots_nor_vbo, get_fdots_nor_format_subdiv(), subdiv_cache->num_coarse_poly);
+ GPU_vertbuf_init_build_on_device(
+ fdots_pos_vbo, get_fdots_pos_format(), subdiv_cache->num_coarse_poly);
+ GPU_indexbuf_init_build_on_device(fdots_pos_ibo, subdiv_cache->num_coarse_poly);
+ draw_subdiv_build_fdots_buffers(subdiv_cache, fdots_pos_vbo, fdots_nor_vbo, fdots_pos_ibo);
+}
+
constexpr MeshExtract create_extractor_fdots_pos()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_fdots_pos_init;
+ extractor.init_subdiv = extract_fdots_init_subdiv;
extractor.iter_poly_bm = extract_fdots_pos_iter_poly_bm;
extractor.iter_poly_mesh = extract_fdots_pos_iter_poly_mesh;
extractor.data_type = MR_DATA_NONE;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
index f9f66c27aaa..93b94b210b2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_lnor.cc
@@ -23,6 +23,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -85,7 +87,7 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
*lnor_data = GPU_normal_convert_i10_v3(mr->loop_normals[ml_index]);
}
else if (mp->flag & ME_SMOOTH) {
- *lnor_data = GPU_normal_convert_i10_s3(mr->mvert[ml->v].no);
+ *lnor_data = GPU_normal_convert_i10_v3(mr->vert_normals[ml->v]);
}
else {
*lnor_data = GPU_normal_convert_i10_v3(mr->poly_normals[mp_index]);
@@ -107,10 +109,34 @@ static void extract_lnor_iter_poly_mesh(const MeshRenderData *mr,
}
}
+static GPUVertFormat *get_subdiv_lnor_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "lnor");
+ }
+ return &format;
+}
+
+static void extract_lnor_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ GPUVertBuf *pos_nor = cache->final.buff.vbo.pos_nor;
+ BLI_assert(pos_nor);
+ GPU_vertbuf_init_build_on_device(vbo, get_subdiv_lnor_format(), subdiv_cache->num_subdiv_loops);
+ draw_subdiv_build_lnor_buffer(subdiv_cache, pos_nor, vbo);
+}
+
constexpr MeshExtract create_extractor_lnor()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_lnor_init;
+ extractor.init_subdiv = extract_lnor_init_subdiv;
extractor.iter_poly_bm = extract_lnor_iter_poly_bm;
extractor.iter_poly_mesh = extract_lnor_iter_poly_mesh;
extractor.data_type = MR_DATA_LOOP_NOR;
@@ -121,6 +147,7 @@ constexpr MeshExtract create_extractor_lnor()
}
/** \} */
+
/* ---------------------------------------------------------------------- */
/** \name Extract HQ Loop Normal
* \{ */
@@ -183,7 +210,7 @@ static void extract_lnor_hq_iter_poly_mesh(const MeshRenderData *mr,
normal_float_to_short_v3(&lnor_data->x, mr->loop_normals[ml_index]);
}
else if (mp->flag & ME_SMOOTH) {
- copy_v3_v3_short(&lnor_data->x, mr->mvert[ml->v].no);
+ normal_float_to_short_v3(&lnor_data->x, mr->vert_normals[ml->v]);
}
else {
normal_float_to_short_v3(&lnor_data->x, mr->poly_normals[mp_index]);
@@ -209,6 +236,7 @@ constexpr MeshExtract create_extractor_lnor_hq()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_lnor_hq_init;
+ extractor.init_subdiv = extract_lnor_init_subdiv;
extractor.iter_poly_bm = extract_lnor_hq_iter_poly_bm;
extractor.iter_poly_mesh = extract_lnor_hq_iter_poly_mesh;
extractor.data_type = MR_DATA_LOOP_NOR;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
index 33a33c81bc2..706c6ad5403 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_mesh_analysis.cc
@@ -460,7 +460,7 @@ static void statvis_calc_distort(const MeshRenderData *mr, float *r_distort)
float fac = -1.0f;
if (mp->totloop > 3) {
- float *f_no = mr->poly_normals[mp_index];
+ const float *f_no = mr->poly_normals[mp_index];
fac = 0.0f;
for (int i = 1; i <= mp->totloop; i++) {
@@ -555,7 +555,7 @@ static void statvis_calc_sharp(const MeshRenderData *mr, float *r_sharp)
void **pval;
bool value_is_init = BLI_edgehash_ensure_p(eh, l_curr->v, l_next->v, &pval);
if (!value_is_init) {
- *pval = mr->poly_normals[mp_index];
+ *pval = (void *)mr->poly_normals[mp_index];
/* non-manifold edge, yet... */
continue;
}
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
index eb9a138590c..5d2ea923658 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_pos_nor.cc
@@ -25,6 +25,8 @@
#include "extract_mesh.h"
+#include "draw_subdivision.h"
+
namespace blender::draw {
/* ---------------------------------------------------------------------- */
@@ -72,9 +74,8 @@ static void extract_pos_nor_init(const MeshRenderData *mr,
}
}
else {
- const MVert *mv = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mv++) {
- data->normals[v].low = GPU_normal_convert_i10_s3(mv->no);
+ for (int v = 0; v < mr->vert_len; v++) {
+ data->normals[v].low = GPU_normal_convert_i10_v3(mr->vert_normals[v]);
}
}
}
@@ -194,6 +195,123 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data->normals);
}
+static GPUVertFormat *get_pos_nor_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "vnor");
+ }
+ return &format;
+}
+
+static GPUVertFormat *get_normals_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "lnor");
+ }
+ return &format;
+}
+
+static void extract_pos_nor_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ const bool do_limit_normals = subdiv_cache->do_limit_normals;
+
+ /* Initialize the vertex buffer, it was already allocated. */
+ GPU_vertbuf_init_build_on_device(
+ vbo, get_pos_nor_format(), subdiv_cache->num_subdiv_loops + mr->loop_loose_len);
+
+ draw_subdiv_extract_pos_nor(subdiv_cache, vbo, do_limit_normals);
+
+ if (!do_limit_normals) {
+ /* We cannot evaluate vertex normals using the limit surface, so compute them manually. */
+ GPUVertBuf *subdiv_loop_subdiv_vert_index = draw_subdiv_build_origindex_buffer(
+ subdiv_cache->subdiv_loop_subdiv_vert_index, subdiv_cache->num_subdiv_loops);
+
+ GPUVertBuf *vertex_normals = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_build_on_device(
+ vertex_normals, get_normals_format(), subdiv_cache->num_subdiv_verts);
+
+ draw_subdiv_accumulate_normals(subdiv_cache,
+ vbo,
+ subdiv_cache->subdiv_vertex_face_adjacency_offsets,
+ subdiv_cache->subdiv_vertex_face_adjacency,
+ vertex_normals);
+
+ draw_subdiv_finalize_normals(subdiv_cache, vertex_normals, subdiv_loop_subdiv_vert_index, vbo);
+
+ GPU_vertbuf_discard(vertex_normals);
+ GPU_vertbuf_discard(subdiv_loop_subdiv_vert_index);
+ }
+}
+
+static void extract_pos_nor_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *UNUSED(data))
+{
+ const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
+ if (loop_loose_len == 0) {
+ return;
+ }
+
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ const Mesh *coarse_mesh = subdiv_cache->mesh;
+ const MEdge *coarse_edges = coarse_mesh->medge;
+ const MVert *coarse_verts = coarse_mesh->mvert;
+ uint offset = subdiv_cache->num_subdiv_loops;
+
+ /* TODO(kevindietrich) : replace this when compressed normals are supported. */
+ struct SubdivPosNorLoop {
+ float pos[3];
+ float nor[3];
+ float flag;
+ };
+
+ SubdivPosNorLoop edge_data[2];
+ for (int i = 0; i < loose_geom->edge_len; i++) {
+ const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
+ const MVert *loose_vert1 = &coarse_verts[loose_edge->v1];
+ const MVert *loose_vert2 = &coarse_verts[loose_edge->v2];
+
+ copy_v3_v3(edge_data[0].pos, loose_vert1->co);
+ copy_v3_v3(edge_data[0].nor, mr->vert_normals[loose_edge->v1]);
+ edge_data[0].flag = 0.0f;
+
+ copy_v3_v3(edge_data[1].pos, loose_vert2->co);
+ copy_v3_v3(edge_data[1].nor, mr->vert_normals[loose_edge->v2]);
+ edge_data[1].flag = 0.0f;
+
+ GPU_vertbuf_update_sub(
+ vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop) * 2, &edge_data);
+
+ offset += 2;
+ }
+
+ SubdivPosNorLoop vert_data;
+ vert_data.flag = 0.0f;
+ for (int i = 0; i < loose_geom->vert_len; i++) {
+ const MVert *loose_vertex = &coarse_verts[loose_geom->verts[i]];
+
+ copy_v3_v3(vert_data.pos, loose_vertex->co);
+ copy_v3_v3(vert_data.nor, mr->vert_normals[loose_geom->verts[i]]);
+
+ GPU_vertbuf_update_sub(
+ vbo, offset * sizeof(SubdivPosNorLoop), sizeof(SubdivPosNorLoop), &vert_data);
+
+ offset += 1;
+ }
+}
+
constexpr MeshExtract create_extractor_pos_nor()
{
MeshExtract extractor = {nullptr};
@@ -205,6 +323,8 @@ constexpr MeshExtract create_extractor_pos_nor()
extractor.iter_lvert_bm = extract_pos_nor_iter_lvert_bm;
extractor.iter_lvert_mesh = extract_pos_nor_iter_lvert_mesh;
extractor.finish = extract_pos_nor_finish;
+ extractor.init_subdiv = extract_pos_nor_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_pos_nor_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(MeshExtract_PosNor_Data);
extractor.use_threading = true;
@@ -259,9 +379,8 @@ static void extract_pos_nor_hq_init(const MeshRenderData *mr,
}
}
else {
- const MVert *mv = mr->mvert;
- for (int v = 0; v < mr->vert_len; v++, mv++) {
- copy_v3_v3_short(data->normals[v].high, mv->no);
+ for (int v = 0; v < mr->vert_len; v++) {
+ normal_float_to_short_v3(data->normals[v].high, mr->vert_normals[v]);
}
}
}
@@ -391,6 +510,7 @@ constexpr MeshExtract create_extractor_pos_nor_hq()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_pos_nor_hq_init;
+ extractor.init_subdiv = extract_pos_nor_init_subdiv;
extractor.iter_poly_bm = extract_pos_nor_hq_iter_poly_bm;
extractor.iter_poly_mesh = extract_pos_nor_hq_iter_poly_mesh;
extractor.iter_ledge_bm = extract_pos_nor_hq_iter_ledge_bm;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
index fd91bc5258f..753fbe7e0e2 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_sculpt_data.cc
@@ -27,6 +27,7 @@
#include "BKE_paint.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -35,13 +36,23 @@ namespace blender::draw {
/** \name Extract Sculpt Data
* \{ */
+static GPUVertFormat *get_sculpt_data_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ return &format;
+}
+
static void extract_sculpt_data_init(const MeshRenderData *mr,
struct MeshBatchCache *UNUSED(cache),
void *buf,
void *UNUSED(tls_data))
{
GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
- GPUVertFormat format = {0};
+ GPUVertFormat *format = get_sculpt_data_format();
CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
@@ -50,12 +61,7 @@ static void extract_sculpt_data_init(const MeshRenderData *mr,
float *cd_mask = (float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK);
int *cd_face_set = (int *)CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS);
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "fset", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
- GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
- }
-
- GPU_vertbuf_init_with_format(vbo, &format);
+ GPU_vertbuf_init_with_format(vbo, format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
struct gpuSculptData {
@@ -121,10 +127,99 @@ static void extract_sculpt_data_init(const MeshRenderData *mr,
}
}
+static void extract_sculpt_data_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ struct MeshBatchCache *UNUSED(cache),
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+
+ Mesh *coarse_mesh = mr->me;
+ CustomData *cd_vdata = &coarse_mesh->vdata;
+ CustomData *cd_pdata = &coarse_mesh->pdata;
+
+ /* First, interpolate mask if available. */
+ GPUVertBuf *mask_vbo = nullptr;
+ GPUVertBuf *subdiv_mask_vbo = nullptr;
+ float *cd_mask = (float *)CustomData_get_layer(cd_vdata, CD_PAINT_MASK);
+
+ if (cd_mask) {
+ GPUVertFormat mask_format = {0};
+ GPU_vertformat_attr_add(&mask_format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+
+ mask_vbo = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_with_format(mask_vbo, &mask_format);
+ GPU_vertbuf_data_alloc(mask_vbo, coarse_mesh->totloop);
+ float *v_mask = static_cast<float *>(GPU_vertbuf_get_data(mask_vbo));
+
+ for (int i = 0; i < coarse_mesh->totpoly; i++) {
+ const MPoly *mpoly = &coarse_mesh->mpoly[i];
+
+ for (int loop_index = mpoly->loopstart; loop_index < mpoly->loopstart + mpoly->totloop;
+ loop_index++) {
+ const MLoop *ml = &coarse_mesh->mloop[loop_index];
+ *v_mask++ = cd_mask[ml->v];
+ }
+ }
+
+ subdiv_mask_vbo = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_build_on_device(
+ subdiv_mask_vbo, &mask_format, subdiv_cache->num_subdiv_loops);
+
+ draw_subdiv_interp_custom_data(subdiv_cache, mask_vbo, subdiv_mask_vbo, 1, 0);
+ }
+
+ /* Then, gather face sets. */
+ GPUVertFormat face_set_format = {0};
+ GPU_vertformat_attr_add(&face_set_format, "msk", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+
+ GPUVertBuf *face_set_vbo = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_with_format(face_set_vbo, &face_set_format);
+ GPU_vertbuf_data_alloc(face_set_vbo, subdiv_cache->num_subdiv_loops);
+
+ struct gpuFaceSet {
+ uint8_t color[4];
+ };
+
+ gpuFaceSet *face_sets = (gpuFaceSet *)GPU_vertbuf_get_data(face_set_vbo);
+ int *cd_face_set = (int *)CustomData_get_layer(cd_pdata, CD_SCULPT_FACE_SETS);
+
+ GPUVertFormat *format = get_sculpt_data_format();
+ GPU_vertbuf_init_build_on_device(vbo, format, subdiv_cache->num_subdiv_loops);
+ int *subdiv_loop_poly_index = subdiv_cache->subdiv_loop_poly_index;
+
+ for (uint i = 0; i < subdiv_cache->num_subdiv_loops; i++) {
+ const int mp_index = subdiv_loop_poly_index[i];
+
+ uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
+ if (cd_face_set) {
+ const int face_set_id = cd_face_set[mp_index];
+ /* Skip for the default color Face Set to render it white. */
+ if (face_set_id != coarse_mesh->face_sets_color_default) {
+ BKE_paint_face_set_overlay_color_get(
+ face_set_id, coarse_mesh->face_sets_color_seed, face_set_color);
+ }
+ }
+ copy_v3_v3_uchar(face_sets->color, face_set_color);
+ face_sets++;
+ }
+
+ /* Finally, interleave mask and face sets. */
+ draw_subdiv_build_sculpt_data_buffer(subdiv_cache, subdiv_mask_vbo, face_set_vbo, vbo);
+
+ if (mask_vbo) {
+ GPU_vertbuf_discard(mask_vbo);
+ GPU_vertbuf_discard(subdiv_mask_vbo);
+ }
+ GPU_vertbuf_discard(face_set_vbo);
+}
+
constexpr MeshExtract create_extractor_sculpt_data()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_sculpt_data_init;
+ extractor.init_subdiv = extract_sculpt_data_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
index 5ac30dd3be9..33c27b45627 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_select_idx.cc
@@ -21,6 +21,7 @@
* \ingroup draw
*/
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -196,12 +197,104 @@ static void extract_vert_idx_iter_lvert_mesh(const MeshRenderData *mr,
(*(uint32_t **)data)[offset + lvert_index] = v_orig;
}
+static void extract_vert_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ /* Each element points to an element in the ibo.points. */
+ draw_subdiv_init_origindex_buffer(vbo,
+ subdiv_cache->subdiv_loop_subdiv_vert_index,
+ subdiv_cache->num_subdiv_loops,
+ mr->loop_loose_len);
+}
+
+static void extract_vert_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *UNUSED(data))
+{
+ const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
+ if (loop_loose_len == 0) {
+ return;
+ }
+
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
+ const Mesh *coarse_mesh = subdiv_cache->mesh;
+ const MEdge *coarse_edges = coarse_mesh->medge;
+ uint offset = subdiv_cache->num_subdiv_loops;
+
+ for (int i = 0; i < loose_geom->edge_len; i++) {
+ const MEdge *loose_edge = &coarse_edges[loose_geom->edges[i]];
+ vert_idx_data[offset] = loose_edge->v1;
+ vert_idx_data[offset + 1] = loose_edge->v2;
+ offset += 2;
+ }
+
+ for (int i = 0; i < loose_geom->vert_len; i++) {
+ vert_idx_data[offset] = loose_geom->verts[i];
+ offset += 1;
+ }
+}
+
+static void extract_edge_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *mr,
+ MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ draw_subdiv_init_origindex_buffer(
+ vbo,
+ static_cast<int *>(GPU_vertbuf_get_data(subdiv_cache->edges_orig_index)),
+ subdiv_cache->num_subdiv_loops,
+ mr->edge_loose_len * 2);
+}
+
+static void extract_edge_idx_loose_geom_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ const MeshExtractLooseGeom *loose_geom,
+ void *buffer,
+ void *UNUSED(data))
+{
+ const int loop_loose_len = loose_geom->edge_len + loose_geom->vert_len;
+ if (loop_loose_len == 0) {
+ return;
+ }
+
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ uint *vert_idx_data = (uint *)GPU_vertbuf_get_data(vbo);
+ uint offset = subdiv_cache->num_subdiv_loops;
+
+ for (int i = 0; i < loose_geom->edge_len; i++) {
+ vert_idx_data[offset] = loose_geom->edges[i];
+ vert_idx_data[offset + 1] = loose_geom->edges[i];
+ offset += 2;
+ }
+}
+
+static void extract_poly_idx_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ MeshBatchCache *UNUSED(cache),
+ void *buf,
+ void *UNUSED(data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ draw_subdiv_init_origindex_buffer(
+ vbo, subdiv_cache->subdiv_loop_poly_index, subdiv_cache->num_subdiv_loops, 0);
+}
+
constexpr MeshExtract create_extractor_poly_idx()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_select_idx_init;
extractor.iter_poly_bm = extract_poly_idx_iter_poly_bm;
extractor.iter_poly_mesh = extract_poly_idx_iter_poly_mesh;
+ extractor.init_subdiv = extract_poly_idx_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
@@ -217,6 +310,8 @@ constexpr MeshExtract create_extractor_edge_idx()
extractor.iter_poly_mesh = extract_edge_idx_iter_poly_mesh;
extractor.iter_ledge_bm = extract_edge_idx_iter_ledge_bm;
extractor.iter_ledge_mesh = extract_edge_idx_iter_ledge_mesh;
+ extractor.init_subdiv = extract_edge_idx_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_edge_idx_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
@@ -234,6 +329,8 @@ constexpr MeshExtract create_extractor_vert_idx()
extractor.iter_ledge_mesh = extract_vert_idx_iter_ledge_mesh;
extractor.iter_lvert_bm = extract_vert_idx_iter_lvert_bm;
extractor.iter_lvert_mesh = extract_vert_idx_iter_lvert_mesh;
+ extractor.init_subdiv = extract_vert_idx_init_subdiv;
+ extractor.iter_loose_geom_subdiv = extract_vert_idx_loose_geom_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = sizeof(uint32_t *);
extractor.use_threading = true;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
index 1f8776fc98e..03d1b327689 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_tan.cc
@@ -54,11 +54,18 @@ static void extract_tan_ex_init(const MeshRenderData *mr,
uint32_t tan_layers = cache->cd_used.tan;
float(*orco)[3] = (float(*)[3])CustomData_get_layer(cd_vdata, CD_ORCO);
bool orco_allocated = false;
- const bool use_orco_tan = cache->cd_used.tan_orco != 0;
+ bool use_orco_tan = cache->cd_used.tan_orco != 0;
int tan_len = 0;
char tangent_names[MAX_MTFACE][MAX_CUSTOMDATA_LAYER_NAME];
+ /* FIXME(T91838): This is to avoid a crash when orco tangent was requested but there are valid
+ * uv layers. It would be better to fix the root cause. */
+ if (tan_layers == 0 && use_orco_tan && CustomData_get_layer_index(cd_ldata, CD_MLOOPUV) != -1) {
+ tan_layers = 1;
+ use_orco_tan = false;
+ }
+
for (int i = 0; i < MAX_MTFACE; i++) {
if (tan_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
@@ -131,6 +138,7 @@ static void extract_tan_ex_init(const MeshRenderData *mr,
calc_active_tangent,
tangent_names,
tan_len,
+ mr->vert_normals,
mr->poly_normals,
mr->loop_normals,
orco,
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
index af279b08a59..6e9d8ef6926 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_uv.cc
@@ -23,6 +23,7 @@
#include "BLI_string.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -31,25 +32,27 @@ namespace blender::draw {
/** \name Extract UV layers
* \{ */
-static void extract_uv_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
+/* Initialize the vertex format to be used for UVs. Return true if any UV layer is
+ * found, false otherwise. */
+static bool mesh_extract_uv_format_init(GPUVertFormat *format,
+ struct MeshBatchCache *cache,
+ CustomData *cd_ldata,
+ eMRExtractType extract_type,
+ uint32_t &r_uv_layers)
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
- GPUVertFormat format = {0};
- GPU_vertformat_deinterleave(&format);
+ GPU_vertformat_deinterleave(format);
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t uv_layers = cache->cd_used.uv;
/* HACK to fix T68857 */
- if (mr->extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
+ if (extract_type == MR_EXTRACT_BMESH && cache->cd_used.edit_uv == 1) {
int layer = CustomData_get_active_layer(cd_ldata, CD_MLOOPUV);
if (layer != -1) {
uv_layers |= (1 << layer);
}
}
+ r_uv_layers = uv_layers;
+
for (int i = 0; i < MAX_MTFACE; i++) {
if (uv_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
@@ -58,30 +61,47 @@ static void extract_uv_init(const MeshRenderData *mr,
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
/* UV layer name. */
BLI_snprintf(attr_name, sizeof(attr_name), "u%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_vertformat_attr_add(format, attr_name, GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
/* Auto layer name. */
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
+ GPU_vertformat_alias_add(format, attr_name);
/* Active render layer name. */
if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "u");
+ GPU_vertformat_alias_add(format, "u");
}
/* Active display layer name. */
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "au");
+ GPU_vertformat_alias_add(format, "au");
/* Alias to `pos` for edit uvs. */
- GPU_vertformat_alias_add(&format, "pos");
+ GPU_vertformat_alias_add(format, "pos");
}
/* Stencil mask uv layer name. */
if (i == CustomData_get_stencil_layer(cd_ldata, CD_MLOOPUV)) {
- GPU_vertformat_alias_add(&format, "mu");
+ GPU_vertformat_alias_add(format, "mu");
}
}
}
+ if (format->attr_len == 0) {
+ GPU_vertformat_attr_add(format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ return false;
+ }
+
+ return true;
+}
+
+static void extract_uv_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat format = {0};
+
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
int v_len = mr->loop_len;
- if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint32_t uv_layers = cache->cd_used.uv;
+ if (!mesh_extract_uv_format_init(&format, cache, cd_ldata, mr->extract_type, uv_layers)) {
/* VBO will not be used, only allocate minimum of memory. */
v_len = 1;
}
@@ -116,10 +136,45 @@ static void extract_uv_init(const MeshRenderData *mr,
}
}
+static void extract_uv_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ Mesh *coarse_mesh = subdiv_cache->mesh;
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+ GPUVertFormat format = {0};
+
+ uint v_len = subdiv_cache->num_subdiv_loops;
+ uint uv_layers;
+ if (!mesh_extract_uv_format_init(
+ &format, cache, &coarse_mesh->ldata, MR_EXTRACT_MESH, uv_layers)) {
+ // TODO(kevindietrich): handle this more gracefully.
+ v_len = 1;
+ }
+
+ GPU_vertbuf_init_build_on_device(vbo, &format, v_len);
+
+ if (uv_layers == 0) {
+ return;
+ }
+
+ /* Index of the UV layer in the compact buffer. Used UV layers are stored in a single buffer. */
+ int pack_layer_index = 0;
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (uv_layers & (1 << i)) {
+ const int offset = (int)subdiv_cache->num_subdiv_loops * pack_layer_index++;
+ draw_subdiv_extract_uvs(subdiv_cache, vbo, i, offset);
+ }
+ }
+}
+
constexpr MeshExtract create_extractor_uv()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_uv_init;
+ extractor.init_subdiv = extract_uv_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
index 2c7770c8e72..a0307b9b2cd 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc
@@ -25,6 +25,7 @@
#include "BLI_string.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -33,19 +34,14 @@ namespace blender::draw {
/** \name Extract VCol
* \{ */
-static void extract_vcol_init(const MeshRenderData *mr,
- struct MeshBatchCache *cache,
- void *buf,
- void *UNUSED(tls_data))
+/* Initialize the common vertex format for vcol for coarse and subdivided meshes. */
+static void init_vcol_format(GPUVertFormat *format,
+ const MeshBatchCache *cache,
+ CustomData *cd_ldata)
{
- GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
- GPUVertFormat format = {0};
- GPU_vertformat_deinterleave(&format);
+ GPU_vertformat_deinterleave(format);
- CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
- CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : &mr->me->vdata;
- uint32_t vcol_layers = cache->cd_used.vcol;
- uint32_t svcol_layers = cache->cd_used.sculpt_vcol;
+ const uint32_t vcol_layers = cache->cd_used.vcol;
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
@@ -54,61 +50,57 @@ static void extract_vcol_init(const MeshRenderData *mr,
GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
if (i == CustomData_get_render_layer(cd_ldata, CD_MLOOPCOL)) {
- GPU_vertformat_alias_add(&format, "c");
+ GPU_vertformat_alias_add(format, "c");
}
if (i == CustomData_get_active_layer(cd_ldata, CD_MLOOPCOL)) {
- GPU_vertformat_alias_add(&format, "ac");
+ GPU_vertformat_alias_add(format, "ac");
}
/* Gather number of auto layers. */
- /* We only do `vcols` that are not overridden by `uvs` and sculpt vertex colors. */
- if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1 &&
- CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, layer_name) == -1) {
+ /* We only do `vcols` that are not overridden by `uvs`. */
+ if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
+ GPU_vertformat_alias_add(format, attr_name);
}
}
}
+}
- /* Sculpt Vertex Colors */
- if (U.experimental.use_sculpt_vertex_colors) {
- for (int i = 0; i < 8; i++) {
- if (svcol_layers & (1 << i)) {
- char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
- const char *layer_name = CustomData_get_layer_name(cd_vdata, CD_PROP_COLOR, i);
- GPU_vertformat_safe_attr_name(layer_name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME);
+/* Vertex format for vertex colors, only used during the coarse data upload for the subdivision
+ * case. */
+static GPUVertFormat *get_coarse_vcol_format()
+{
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "cCol", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ GPU_vertformat_alias_add(&format, "c");
+ GPU_vertformat_alias_add(&format, "ac");
+ }
+ return &format;
+}
- BLI_snprintf(attr_name, sizeof(attr_name), "c%s", attr_safe_name);
- GPU_vertformat_attr_add(&format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+using gpuMeshVcol = struct gpuMeshVcol {
+ ushort r, g, b, a;
+};
- if (i == CustomData_get_render_layer(cd_vdata, CD_PROP_COLOR)) {
- GPU_vertformat_alias_add(&format, "c");
- }
- if (i == CustomData_get_active_layer(cd_vdata, CD_PROP_COLOR)) {
- GPU_vertformat_alias_add(&format, "ac");
- }
- /* Gather number of auto layers. */
- /* We only do `vcols` that are not overridden by `uvs`. */
- if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, layer_name) == -1) {
- BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name);
- GPU_vertformat_alias_add(&format, attr_name);
- }
- }
- }
- }
+static void extract_vcol_init(const MeshRenderData *mr,
+ struct MeshBatchCache *cache,
+ void *buf,
+ void *UNUSED(tls_data))
+{
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf);
+ GPUVertFormat format = {0};
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
+ const uint32_t vcol_layers = cache->cd_used.vcol;
+ init_vcol_format(&format, cache, cd_ldata);
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
- using gpuMeshVcol = struct gpuMeshVcol {
- ushort r, g, b, a;
- };
-
gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo);
- MLoop *loops = (MLoop *)CustomData_get_layer(cd_ldata, CD_MLOOP);
for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
@@ -139,42 +131,67 @@ static void extract_vcol_init(const MeshRenderData *mr,
}
}
}
+ }
+}
- if (svcol_layers & (1 << i) && U.experimental.use_sculpt_vertex_colors) {
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- int cd_ofs = CustomData_get_n_offset(cd_vdata, CD_PROP_COLOR, i);
- BMIter f_iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- do {
- const MPropCol *prop_col = (const MPropCol *)BM_ELEM_CD_GET_VOID_P(l_iter->v, cd_ofs);
- vcol_data->r = unit_float_to_ushort_clamp(prop_col->color[0]);
- vcol_data->g = unit_float_to_ushort_clamp(prop_col->color[1]);
- vcol_data->b = unit_float_to_ushort_clamp(prop_col->color[2]);
- vcol_data->a = unit_float_to_ushort_clamp(prop_col->color[3]);
- vcol_data++;
- } while ((l_iter = l_iter->next) != l_first);
- }
- }
- else {
- MPropCol *vcol = (MPropCol *)CustomData_get_layer_n(cd_vdata, CD_PROP_COLOR, i);
- for (int ml_index = 0; ml_index < mr->loop_len; ml_index++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[0]);
- vcol_data->g = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[1]);
- vcol_data->b = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[2]);
- vcol_data->a = unit_float_to_ushort_clamp(vcol[loops[ml_index].v].color[3]);
- }
+static void extract_vcol_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer);
+ Mesh *coarse_mesh = subdiv_cache->mesh;
+
+ GPUVertFormat format = {0};
+ init_vcol_format(&format, cache, &coarse_mesh->ldata);
+
+ GPU_vertbuf_init_build_on_device(dst_buffer, &format, subdiv_cache->num_subdiv_loops);
+
+ GPUVertBuf *src_data = GPU_vertbuf_calloc();
+ /* Dynamic as we upload and interpolate layers one at a time. */
+ GPU_vertbuf_init_with_format_ex(src_data, get_coarse_vcol_format(), GPU_USAGE_DYNAMIC);
+
+ GPU_vertbuf_data_alloc(src_data, coarse_mesh->totloop);
+
+ gpuMeshVcol *mesh_vcol = (gpuMeshVcol *)GPU_vertbuf_get_data(src_data);
+
+ const CustomData *cd_ldata = &coarse_mesh->ldata;
+
+ const uint vcol_layers = cache->cd_used.vcol;
+
+ /* Index of the vertex color layer in the compact buffer. Used vertex color layers are stored in
+ * a single buffer. */
+ int pack_layer_index = 0;
+ for (int i = 0; i < MAX_MTFACE; i++) {
+ if (vcol_layers & (1 << i)) {
+ /* Include stride in offset, we use a stride of 2 since colors are packed into 2 uints. */
+ const int dst_offset = (int)subdiv_cache->num_subdiv_loops * 2 * pack_layer_index++;
+ const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
+
+ gpuMeshVcol *vcol = mesh_vcol;
+
+ for (int ml_index = 0; ml_index < coarse_mesh->totloop; ml_index++, vcol++, mloopcol++) {
+ vcol->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
}
+
+ /* Ensure data is uploaded properly. */
+ GPU_vertbuf_tag_dirty(src_data);
+ draw_subdiv_interp_custom_data(subdiv_cache, src_data, dst_buffer, 4, dst_offset);
}
}
+
+ GPU_vertbuf_discard(src_data);
}
constexpr MeshExtract create_extractor_vcol()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_vcol_init;
+ extractor.init_subdiv = extract_vcol_init_subdiv;
extractor.data_type = MR_DATA_NONE;
extractor.data_size = 0;
extractor.use_threading = false;
diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
index bdb1410a755..bb8853b8154 100644
--- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
+++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_weights.cc
@@ -25,6 +25,7 @@
#include "BKE_deform.h"
+#include "draw_subdivision.h"
#include "extract_mesh.h"
namespace blender::draw {
@@ -167,10 +168,57 @@ static void extract_weights_iter_poly_mesh(const MeshRenderData *mr,
}
}
+static void extract_weights_init_subdiv(const DRWSubdivCache *subdiv_cache,
+ const MeshRenderData *UNUSED(mr),
+ struct MeshBatchCache *cache,
+ void *buffer,
+ void *UNUSED(data))
+{
+ Mesh *coarse_mesh = subdiv_cache->mesh;
+ GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buffer);
+
+ static GPUVertFormat format = {0};
+ if (format.attr_len == 0) {
+ GPU_vertformat_attr_add(&format, "weight", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ }
+ GPU_vertbuf_init_build_on_device(vbo, &format, subdiv_cache->num_subdiv_loops);
+
+ GPUVertBuf *coarse_weights = GPU_vertbuf_calloc();
+ GPU_vertbuf_init_with_format(coarse_weights, &format);
+ GPU_vertbuf_data_alloc(coarse_weights, coarse_mesh->totloop);
+ float *coarse_weights_data = static_cast<float *>(GPU_vertbuf_get_data(coarse_weights));
+
+ const DRW_MeshWeightState *wstate = &cache->weight_state;
+ const MDeformVert *dverts = static_cast<const MDeformVert *>(
+ CustomData_get_layer(&coarse_mesh->vdata, CD_MDEFORMVERT));
+
+ for (int i = 0; i < coarse_mesh->totpoly; i++) {
+ const MPoly *mpoly = &coarse_mesh->mpoly[i];
+
+ for (int loop_index = mpoly->loopstart; loop_index < mpoly->loopstart + mpoly->totloop;
+ loop_index++) {
+ const MLoop *ml = &coarse_mesh->mloop[loop_index];
+
+ if (dverts != nullptr) {
+ const MDeformVert *dvert = &dverts[ml->v];
+ coarse_weights_data[loop_index] = evaluate_vertex_weight(dvert, wstate);
+ }
+ else {
+ coarse_weights_data[loop_index] = evaluate_vertex_weight(nullptr, wstate);
+ }
+ }
+ }
+
+ draw_subdiv_interp_custom_data(subdiv_cache, coarse_weights, vbo, 1, 0);
+
+ GPU_vertbuf_discard(coarse_weights);
+}
+
constexpr MeshExtract create_extractor_weights()
{
MeshExtract extractor = {nullptr};
extractor.init = extract_weights_init;
+ extractor.init_subdiv = extract_weights_init_subdiv;
extractor.iter_poly_bm = extract_weights_iter_poly_bm;
extractor.iter_poly_mesh = extract_weights_iter_poly_mesh;
extractor.data_type = MR_DATA_NONE;