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:
authorClément Foucault <foucault.clem@gmail.com>2019-05-04 02:39:35 +0300
committerClément Foucault <foucault.clem@gmail.com>2019-05-04 15:11:04 +0300
commitb2f1a6587410d00ad3bbd22e045979f80048afe2 (patch)
tree8312daea35aed37a1cdba6d6e6e97958b7f21d47 /source/blender
parent1d8ed6dcd7cd2b3ccfaaacb59387dca481262eb6 (diff)
Sculpt: Refactor draw manager sculpt drawing mechanism
Workbench/Eevee now displays multiple multi-materials correctly. Iterate over pbvh nodes when doing object iteration. This makes the rendering process more streamlined and allow for using different materials. This change will make possible to: - Add culling pass of each pbvh leaf node. (speedup if zoomed on a small area) - Reduce number of lead node iteration. - Reduce code complexity
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h41
-rw-r--r--source/blender/blenkernel/intern/pbvh.c52
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c106
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c30
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c128
-rw-r--r--source/blender/draw/intern/DRW_render.h19
-rw-r--r--source/blender/draw/intern/draw_manager_data.c200
-rw-r--r--source/blender/draw/modes/overlay_mode.c2
-rw-r--r--source/blender/draw/modes/sculpt_mode.c6
9 files changed, 310 insertions, 274 deletions
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f59288f54bd..9b15462de6b 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -40,6 +40,7 @@ struct MPoly;
struct MVert;
struct PBVH;
struct PBVHNode;
+struct GPU_PBVH_Buffers;
typedef struct PBVH PBVH;
typedef struct PBVHNode PBVHNode;
@@ -48,6 +49,21 @@ typedef struct {
float (*co)[3];
} PBVHProxyNode;
+typedef enum {
+ PBVH_Leaf = 1,
+
+ PBVH_UpdateNormals = 2,
+ PBVH_UpdateBB = 4,
+ PBVH_UpdateOriginalBB = 8,
+ PBVH_UpdateDrawBuffers = 16,
+ PBVH_UpdateRedraw = 32,
+
+ PBVH_RebuildDrawBuffers = 64,
+ PBVH_FullyHidden = 128,
+
+ PBVH_UpdateTopology = 256,
+} PBVHNodeFlags;
+
/* Callbacks */
/* returns 1 if the search should continue from this node, 0 otherwise */
@@ -151,13 +167,15 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
void BKE_pbvh_draw_cb(PBVH *bvh,
float (*planes)[4],
float (*fnors)[3],
- bool fast,
- bool wires,
- bool only_mask,
bool show_vcol,
- void (*draw_fn)(void *user_data, struct GPUBatch *batch),
+ void (*draw_fn)(void *user_data, struct GPU_PBVH_Buffers *buffers),
void *user_data);
+void BKE_pbvh_draw_debug_cb(
+ PBVH *bvh,
+ void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
+ void *user_data);
+
/* PBVH Access */
typedef enum {
PBVH_FACES,
@@ -202,21 +220,6 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
/* Node Access */
-typedef enum {
- PBVH_Leaf = 1,
-
- PBVH_UpdateNormals = 2,
- PBVH_UpdateBB = 4,
- PBVH_UpdateOriginalBB = 8,
- PBVH_UpdateDrawBuffers = 16,
- PBVH_UpdateRedraw = 32,
-
- PBVH_RebuildDrawBuffers = 64,
- PBVH_FullyHidden = 128,
-
- PBVH_UpdateTopology = 256,
-} PBVHNodeFlags;
-
void BKE_pbvh_node_mark_update(PBVHNode *node);
void BKE_pbvh_node_mark_rebuild_draw(PBVHNode *node);
void BKE_pbvh_node_mark_redraw(PBVHNode *node);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index cb4ac0ea01b..f1d5347c48b 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -2202,26 +2202,17 @@ bool BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data)
return test_planes_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
-struct PBVHNodeDrawCallbackData {
- void (*draw_fn)(void *user_data, GPUBatch *batch);
+typedef struct PBVHNodeDrawCallbackData {
+ void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers);
void *user_data;
- bool fast;
- bool only_mask; /* Only draw nodes that have mask data. */
- bool wires;
-};
+} PBVHNodeDrawCallbackData;
static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
{
- struct PBVHNodeDrawCallbackData *data = data_v;
+ PBVHNodeDrawCallbackData *data = data_v;
if (!(node->flag & PBVH_FullyHidden)) {
- GPUBatch *batch = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast, data->wires);
- bool show_mask = GPU_pbvh_buffers_has_mask(node->draw_buffers);
- if (!data->only_mask || show_mask) {
- if (batch != NULL) {
- data->draw_fn(data->user_data, batch);
- }
- }
+ data->draw_fn(data->user_data, node->draw_buffers);
}
}
@@ -2231,20 +2222,10 @@ static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
void BKE_pbvh_draw_cb(PBVH *bvh,
float (*planes)[4],
float (*fnors)[3],
- bool fast,
- bool wires,
- bool only_mask,
bool show_vcol,
- void (*draw_fn)(void *user_data, GPUBatch *batch),
+ void (*draw_fn)(void *user_data, GPU_PBVH_Buffers *buffers),
void *user_data)
{
- struct PBVHNodeDrawCallbackData draw_data = {
- .only_mask = only_mask,
- .fast = fast,
- .wires = wires,
- .draw_fn = draw_fn,
- .user_data = user_data,
- };
PBVHNode **nodes;
int totnode;
@@ -2261,6 +2242,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
MEM_freeN(nodes);
}
+ PBVHNodeDrawCallbackData draw_data = {
+ .draw_fn = draw_fn,
+ .user_data = user_data,
+ };
+
if (planes) {
BKE_pbvh_search_callback(
bvh, BKE_pbvh_node_planes_contain_AABB, planes, pbvh_node_draw_cb, &draw_data);
@@ -2268,10 +2254,18 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
else {
BKE_pbvh_search_callback(bvh, NULL, NULL, pbvh_node_draw_cb, &draw_data);
}
-#if 0
- if (G.debug_value == 14)
- pbvh_draw_BB(bvh);
-#endif
+}
+
+void BKE_pbvh_draw_debug_cb(
+ PBVH *bvh,
+ void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
+ void *user_data)
+{
+ for (int a = 0; a < bvh->totnode; a++) {
+ PBVHNode *node = &bvh->nodes[a];
+
+ draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag);
+ }
}
void BKE_pbvh_grids_update(
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index c6a523e4822..8ee5b51d825 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -1190,17 +1190,12 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
#define ADD_SHGROUP_CALL(shgrp, ob, ma, geom, oedata) \
do { \
- if (is_sculpt_mode_draw) { \
- DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \
+ if (oedata) { \
+ DRW_shgroup_call_object_add_with_callback( \
+ shgrp, geom, ob, ma, EEVEE_lightprobes_obj_visibility_cb, oedata); \
} \
else { \
- if (oedata) { \
- DRW_shgroup_call_object_add_with_callback( \
- shgrp, geom, ob, ma, EEVEE_lightprobes_obj_visibility_cb, oedata); \
- } \
- else { \
- DRW_shgroup_call_object_add_ex(shgrp, geom, ob, ma, false); \
- } \
+ DRW_shgroup_call_object_add_ex(shgrp, geom, ob, ma, false); \
} \
} while (0)
@@ -1604,6 +1599,16 @@ static void material_transparent(Material *ma,
}
}
+/* Return correct material or &defmaterial if slot is empty. */
+BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot)
+{
+ Material *ma = give_current_material(ob, slot + 1);
+ if (ma == NULL) {
+ ma = &defmaterial;
+ }
+ return ma;
+}
+
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1617,15 +1622,14 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
const bool do_cull = (draw_ctx->v3d &&
(draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
- const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
+ bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
/* For now just force fully shaded with eevee when supported. */
- const bool is_sculpt_mode_draw = ob->sculpt && ob->sculpt->pbvh &&
- BKE_pbvh_type(ob->sculpt->pbvh) != PBVH_FACES;
- const bool is_default_mode_shader = is_sculpt_mode;
+ is_sculpt_mode = is_sculpt_mode &&
+ !(ob->sculpt->pbvh && BKE_pbvh_type(ob->sculpt->pbvh) == PBVH_FACES);
/* First get materials for this mesh. */
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
- const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol));
+ const int materials_len = MAX2(1, ob->totcol);
struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len);
struct DRWShadingGroup **shgrp_depth_array = BLI_array_alloca(shgrp_depth_array,
@@ -1635,40 +1639,22 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
+ struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
bool use_flat_nor = false;
-
- if (is_default_mode_shader) {
- if (is_sculpt_mode_draw) {
- use_flat_nor = DRW_object_is_flat_normal(ob);
- }
- }
-
for (int i = 0; i < materials_len; ++i) {
- Material *ma;
-
- if (is_sculpt_mode_draw) {
- ma = NULL;
- }
- else {
- ma = give_current_material(ob, i + 1);
- }
-
+ ma_array[i] = eevee_object_material_get(ob, i);
gpumat_array[i] = NULL;
gpumat_depth_array[i] = NULL;
shgrp_array[i] = NULL;
shgrp_depth_array[i] = NULL;
shgrp_depth_clip_array[i] = NULL;
- if (ma == NULL) {
- ma = &defmaterial;
- }
-
- switch (ma->blend_method) {
+ switch (ma_array[i]->blend_method) {
case MA_BM_SOLID:
case MA_BM_CLIP:
case MA_BM_HASHED:
- material_opaque(ma,
+ material_opaque(ma_array[i],
material_hash,
sldata,
vedata,
@@ -1683,7 +1669,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
case MA_BM_ADD:
case MA_BM_MULTIPLY:
case MA_BM_BLEND:
- material_transparent(ma,
+ material_transparent(ma_array[i],
sldata,
vedata,
do_cull,
@@ -1725,17 +1711,18 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
&auto_layer_count);
}
- if (is_sculpt_mode_draw || mat_geom) {
+ if (is_sculpt_mode) {
+ /* TODO(fclem): Support Vcol. */
+ DRW_shgroup_call_sculpt_with_materials_add(shgrp_array, ma_array, ob, false);
+ DRW_shgroup_call_sculpt_with_materials_add(shgrp_depth_array, ma_array, ob, false);
+ DRW_shgroup_call_sculpt_with_materials_add(shgrp_depth_clip_array, ma_array, ob, false);
+ /* TODO(fclem): Support shadows in sculpt mode. */
+ }
+ else if (mat_geom) {
for (int i = 0; i < materials_len; ++i) {
- if (!is_sculpt_mode_draw && mat_geom[i] == NULL) {
+ if (mat_geom[i] == NULL) {
continue;
}
- EEVEE_ObjectEngineData *oedata = NULL;
- Material *ma = give_current_material(ob, i + 1);
-
- if (ma == NULL) {
- ma = &defmaterial;
- }
/* Do not render surface if we are rendering a volume object
* and do not have a surface closure. */
@@ -1746,23 +1733,16 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* XXX TODO rewrite this to include the dupli objects.
* This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
oedata = EEVEE_object_data_ensure(ob);
oedata->ob = ob;
oedata->test_data = &sldata->probes->vis_data;
}
- /* Shading pass */
- ADD_SHGROUP_CALL(shgrp_array[i], ob, ma, mat_geom[i], oedata);
-
- /* Depth Prepass */
- ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, ma, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, ma, mat_geom[i], oedata);
-
- /* TODO(fclem): Don't support shadows in sculpt mode. */
- if (is_sculpt_mode_draw) {
- break;
- }
+ ADD_SHGROUP_CALL(shgrp_array[i], ob, ma_array[i], mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_array[i], ob, ma_array[i], mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(shgrp_depth_clip_array[i], ob, ma_array[i], mat_geom[i], oedata);
char *name = auto_layer_names;
for (int j = 0; j < auto_layer_count; ++j) {
@@ -1785,19 +1765,19 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
/* Shadow Pass */
struct GPUMaterial *gpumat;
- switch (ma->blend_shadow) {
+ switch (ma_array[i]->blend_shadow) {
case MA_BS_SOLID:
EEVEE_lights_cache_shcaster_add(sldata, stl, mat_geom[i], ob);
*cast_shadow = true;
break;
case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma, false, true);
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
EEVEE_lights_cache_shcaster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma->alpha_threshold);
+ sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
*cast_shadow = true;
break;
case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma, true, true);
+ gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
EEVEE_lights_cache_shcaster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
*cast_shadow = true;
break;
@@ -1845,11 +1825,7 @@ void EEVEE_hair_cache_populate(EEVEE_Data *vedata,
}
DRWShadingGroup *shgrp = NULL;
- Material *ma = give_current_material(ob, part->omat);
-
- if (ma == NULL) {
- ma = &defmaterial;
- }
+ Material *ma = eevee_object_material_get(ob, part->omat - 1);
float *color_p = &ma->r;
float *metal_p = &ma->metallic;
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index 9dcd53a8158..343ad26b802 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -937,7 +937,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
const bool is_active = (ob == draw_ctx->obact);
const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
const bool use_hide = is_active && DRW_object_use_hide_faces(ob);
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
+ const int materials_len = MAX2(1, ob->totcol);
const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
bool has_transp_mat = false;
@@ -983,8 +983,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
/* Draw solid color */
material = get_or_create_material_data(vedata, ob, NULL, NULL, NULL, color_type, 0);
}
+
if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
+ bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR);
+ DRW_shgroup_call_sculpt_add(material->shgrp, ob, false, false, use_vcol);
}
else {
struct GPUBatch *geom;
@@ -1003,11 +1005,25 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
else {
/* Draw material color */
if (is_sculpt_mode) {
- /* Multiple materials are not supported in sculpt mode yet. */
- Material *mat = give_current_material(ob, 1);
- material = get_or_create_material_data(
- vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
+ struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len);
+ struct Material **mats = BLI_array_alloca(mats, materials_len);
+
+ for (int i = 0; i < materials_len; ++i) {
+ mats[i] = give_current_material(ob, i + 1);
+ if (mats[i] != NULL && mats[i]->a < 1.0f) {
+ /* Hack */
+ wpd->shading.xray_alpha = mats[i]->a;
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
+ has_transp_mat = true;
+ }
+ else {
+ material = get_or_create_material_data(
+ vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
+ }
+ shgrps[i] = material->shgrp;
+ }
+ DRW_shgroup_call_sculpt_with_materials_add(shgrps, mats, ob, false);
}
else {
struct GPUBatch **geoms;
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 1d55a54df8d..fe3e0579c8e 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -566,69 +566,78 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
WORKBENCH_MaterialData *material;
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const bool is_sculpt_mode = DRW_object_use_pbvh_drawing(ob);
- bool is_drawn = false;
-
- if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && ELEM(ob->type, OB_MESH)) {
- const Mesh *me = ob->data;
- if (me->mloopuv) {
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
- struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
- for (int i = 0; i < materials_len; i++) {
- Material *mat;
- Image *image;
- ImageUser *iuser;
- int interp;
- workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
- int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode);
- material = workbench_forward_get_or_create_material_data(
- vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode);
- DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
- DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
- }
- is_drawn = true;
+ const int materials_len = MAX2(1, ob->totcol);
+ const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+
+ if (!is_sculpt_mode && TEXTURE_DRAWING_ENABLED(wpd) && me && me->mloopuv) {
+ struct GPUBatch **geom_array = DRW_cache_mesh_surface_texpaint_get(ob);
+ for (int i = 0; i < materials_len; i++) {
+ Material *mat;
+ Image *image;
+ ImageUser *iuser;
+ int interp;
+ workbench_material_get_image_and_mat(ob, i + 1, &image, &iuser, &interp, &mat);
+ int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mat, image, iuser, color_type, interp, is_sculpt_mode);
+ DRW_shgroup_call_object_add(material->shgrp_object_outline, geom_array[i], ob);
+ DRW_shgroup_call_object_add(material->shgrp, geom_array[i], ob);
}
}
-
- /* Fallback from not drawn OB_TEXTURE mode or just OB_SOLID mode */
- if (!is_drawn) {
- if (ELEM(wpd->shading.color_type,
- V3D_SHADING_SINGLE_COLOR,
- V3D_SHADING_OBJECT_COLOR,
- V3D_SHADING_RANDOM_COLOR,
- V3D_SHADING_VERTEX_COLOR)) {
- /* No material split needed */
- int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode);
-
- struct GPUBatch *geom;
- if (color_type == V3D_SHADING_VERTEX_COLOR) {
- geom = DRW_cache_mesh_surface_vertpaint_get(ob);
- }
- else {
- geom = DRW_cache_object_surface_get(ob);
+ else if (ELEM(wpd->shading.color_type,
+ V3D_SHADING_SINGLE_COLOR,
+ V3D_SHADING_OBJECT_COLOR,
+ V3D_SHADING_RANDOM_COLOR,
+ V3D_SHADING_VERTEX_COLOR)) {
+ /* No material split needed */
+ int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode);
+
+ if (is_sculpt_mode) {
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode);
+ bool use_vcol = (color_type == V3D_SHADING_VERTEX_COLOR);
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, false, false, false);
+ if (!is_wire) {
+ DRW_shgroup_call_sculpt_add(material->shgrp, ob, false, false, use_vcol);
}
+ }
+ else {
+ struct GPUBatch *geom = (color_type == V3D_SHADING_VERTEX_COLOR) ?
+ DRW_cache_mesh_surface_vertpaint_get(ob) :
+ DRW_cache_object_surface_get(ob);
if (geom) {
material = workbench_forward_get_or_create_material_data(
vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode);
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
- if (!is_wire) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
- }
- }
- else {
- DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob);
- if (!is_wire) {
- DRW_shgroup_call_object_add(material->shgrp, geom, ob);
- }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_object_add(material->shgrp_object_outline, geom, ob);
+ if (!is_wire) {
+ DRW_shgroup_call_object_add(material->shgrp, geom, ob);
}
}
}
+ }
+ else {
+ /* Draw material color */
+ if (is_sculpt_mode) {
+ struct DRWShadingGroup **shgrps = BLI_array_alloca(shgrps, materials_len);
+ struct Material **mats = BLI_array_alloca(mats, materials_len);
+
+ for (int i = 0; i < materials_len; ++i) {
+ mats[i] = give_current_material(ob, i + 1);
+ material = workbench_forward_get_or_create_material_data(
+ vedata, ob, mats[i], NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
+ shgrps[i] = material->shgrp;
+ }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, false, false, false);
+ if (!is_wire) {
+ DRW_shgroup_call_sculpt_with_materials_add(shgrps, mats, ob, false);
+ }
+ }
else {
- const int materials_len = MAX2(1, (is_sculpt_mode ? 1 : ob->totcol));
struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- gpumat_array[i] = NULL;
- }
+ memset(gpumat_array, 0, sizeof(*gpumat_array) * materials_len);
struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
ob, gpumat_array, materials_len, NULL, NULL, NULL);
@@ -641,17 +650,10 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
Material *mat = give_current_material(ob, i + 1);
material = workbench_forward_get_or_create_material_data(
vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
- if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_add(material->shgrp_object_outline, ob, ob->obmat);
- if (!is_wire) {
- DRW_shgroup_call_sculpt_add(material->shgrp, ob, ob->obmat);
- }
- }
- else {
- DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob);
- if (!is_wire) {
- DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob);
- }
+ /* TODO(fclem) make this call optional */
+ DRW_shgroup_call_object_add(material->shgrp_object_outline, mat_geom[i], ob);
+ if (!is_wire) {
+ DRW_shgroup_call_object_add(material->shgrp, mat_geom[i], ob);
}
}
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 134fb5d99f8..363cf67623a 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -440,6 +440,17 @@ void DRW_shgroup_call_object_add_with_callback(DRWShadingGroup *shgroup,
struct Material *ma,
DRWCallVisibilityFn *callback,
void *user_data);
+
+void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shading_group,
+ Object *object,
+ bool use_wire,
+ bool use_mask,
+ bool use_vert_color);
+void DRW_shgroup_call_sculpt_with_materials_add(DRWShadingGroup **shgroups,
+ Material **materials,
+ Object *ob,
+ bool use_vcol);
+
/* Used for drawing a batch with instancing without instance attributes. */
void DRW_shgroup_call_instances_add(DRWShadingGroup *shgroup,
struct GPUBatch *geom,
@@ -449,14 +460,6 @@ void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup,
struct GPUBatch *geom,
struct Object *ob,
uint *count);
-void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
-void DRW_shgroup_call_sculpt_wires_add(DRWShadingGroup *shgroup,
- struct Object *ob,
- float (*obmat)[4]);
-void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup,
- DRWCallGenerateFn *geometry_fn,
- void *user_data,
- float (*obmat)[4]);
void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup,
const void *attr[],
uint attr_len);
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 65ef2fa66fa..c63e30e65d7 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -38,6 +38,8 @@
#include "BLI_link_utils.h"
#include "BLI_mempool.h"
+#include "GPU_buffers.h"
+
#include "intern/gpu_codegen.h"
struct GPUVertFormat *g_pos_format = NULL;
@@ -616,110 +618,150 @@ void DRW_shgroup_call_object_instances_add(DRWShadingGroup *shgroup,
BLI_LINKS_APPEND(&shgroup->calls, call);
}
-void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup,
- DRWCallGenerateFn *geometry_fn,
- void *user_data,
- float (*obmat)[4])
-{
- BLI_assert(geometry_fn != NULL);
- BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
+// #define SCULPT_DEBUG_BUFFERS
- DRWCall *call = BLI_mempool_alloc(DST.vmempool->calls);
- call->state = drw_call_state_create(shgroup, obmat, NULL);
- call->type = DRW_CALL_GENERATE;
- call->generate.geometry_fn = geometry_fn;
- call->generate.user_data = user_data;
-#ifdef USE_GPU_SELECT
- call->select_id = DST.select_id;
+typedef struct DRWSculptCallbackData {
+ Object *ob;
+ DRWShadingGroup **shading_groups;
+ Material **materials;
+ bool use_wire;
+ bool use_mats;
+ bool use_mask;
+ bool fast_mode; /* Set by draw manager. Do not init. */
+#ifdef SCULPT_DEBUG_BUFFERS
+ int node_nr;
+#endif
+} DRWSculptCallbackData;
+
+#ifdef SCULPT_DEBUG_BUFFERS
+# define SCULPT_DEBUG_COLOR(id) (sculpt_debug_colors[id % 9])
+static float sculpt_debug_colors[9][4] = {
+ {1.0f, 0.2f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 0.2f, 1.0f},
+ {0.2f, 0.2f, 1.0f, 1.0f},
+ {1.0f, 1.0f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 1.0f, 1.0f},
+ {1.0f, 0.2f, 1.0f, 1.0f},
+ {1.0f, 0.7f, 0.2f, 1.0f},
+ {0.2f, 1.0f, 0.7f, 1.0f},
+ {0.7f, 0.2f, 1.0f, 1.0f},
+};
#endif
- BLI_LINKS_APPEND(&shgroup->calls, call);
-}
-
-/* This function tests if the current draw engine draws the vertex colors
- * It is used when drawing sculpts
- *
- * XXX: should we use a callback to a the draw engine to retrieve this
- * setting, this makes the draw manager more clean? */
-static bool DRW_draw_vertex_color_active(const DRWContextState *draw_ctx)
-{
- View3D *v3d = draw_ctx->v3d;
- return v3d->shading.type == OB_SOLID && v3d->shading.color_type == V3D_SHADING_VERTEX_COLOR;
-}
-
-static void sculpt_draw_cb(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom),
- void *user_data)
+static void sculpt_draw_cb(DRWSculptCallbackData *scd, GPU_PBVH_Buffers *buffers)
{
- Object *ob = user_data;
-
- /* XXX should be ensured before but sometime it's not... go figure (see T57040). */
- PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, ob);
+ GPUBatch *geom = GPU_pbvh_buffers_batch_get(buffers, scd->fast_mode, scd->use_wire);
+ Material *ma = NULL;
+ short index = 0;
- const DRWContextState *drwctx = DRW_context_state_get();
- int fast_mode = 0;
+ /* Meh... use_mask is a bit misleading here. */
+ if (scd->use_mask && !GPU_pbvh_buffers_has_mask(buffers)) {
+ return;
+ }
- if (drwctx->evil_C != NULL) {
- Paint *p = BKE_paint_get_active_from_context(drwctx->evil_C);
- if (p && (p->flags & PAINT_FAST_NAVIGATE)) {
- fast_mode = drwctx->rv3d->rflag & RV3D_NAVIGATING;
- }
+ if (scd->use_mats) {
+ index = GPU_pbvh_buffers_material_index_get(buffers);
+ ma = scd->materials[index];
}
- if (pbvh) {
- const bool show_vcol = DRW_draw_vertex_color_active(drwctx);
- BKE_pbvh_draw_cb(pbvh,
- NULL,
- NULL,
- fast_mode,
- false,
- false,
- show_vcol,
- (void (*)(void *, GPUBatch *))draw_fn,
- shgroup);
+ DRWShadingGroup *shgrp = scd->shading_groups[index];
+ if (geom != NULL && shgrp != NULL) {
+#ifdef SCULPT_DEBUG_BUFFERS
+ /* Color each buffers in different colors. Only work in solid/Xray mode. */
+ shgrp = DRW_shgroup_create_sub(shgrp);
+ DRW_shgroup_uniform_vec3(shgrp, "materialDiffuseColor", SCULPT_DEBUG_COLOR(scd->node_nr++), 1);
+#endif
+ /* DRW_shgroup_call_object_add_ex reuses matrices calculations for all the drawcalls of this
+ * object. */
+ DRW_shgroup_call_object_add_ex(shgrp, geom, scd->ob, ma, true);
}
}
-static void sculpt_draw_wires_cb(DRWShadingGroup *shgroup,
- void (*draw_fn)(DRWShadingGroup *shgroup, GPUBatch *geom),
- void *user_data)
+#ifdef SCULPT_DEBUG_BUFFERS
+static void sculpt_debug_cb(void *user_data,
+ const float bmin[3],
+ const float bmax[3],
+ PBVHNodeFlags flag)
{
- Object *ob = user_data;
+ int *node_nr = (int *)user_data;
+ BoundBox bb;
+ BKE_boundbox_init_from_minmax(&bb, bmin, bmax);
+
+# if 0 /* Nodes hierarchy. */
+ if (flag & PBVH_Leaf) {
+ DRW_debug_bbox(&bb, (float[4]){0.0f, 1.0f, 0.0f, 1.0f});
+ }
+ else {
+ DRW_debug_bbox(&bb, (float[4]){0.5f, 0.5f, 0.5f, 0.6f});
+ }
+# else /* Color coded leaf bounds. */
+ if (flag & PBVH_Leaf) {
+ DRW_debug_bbox(&bb, SCULPT_DEBUG_COLOR((*node_nr)++));
+ }
+# endif
+}
+#endif
+static void drw_sculpt_generate_calls(DRWSculptCallbackData *scd, bool use_vcol)
+{
/* XXX should be ensured before but sometime it's not... go figure (see T57040). */
- PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, ob);
+ PBVH *pbvh = BKE_sculpt_object_pbvh_ensure(DST.draw_ctx.depsgraph, scd->ob);
+ if (!pbvh) {
+ return;
+ }
- const DRWContextState *drwctx = DRW_context_state_get();
- int fast_mode = 0;
+ float(*planes)[4] = NULL; /* TODO proper culling. */
+ scd->fast_mode = false;
+ const DRWContextState *drwctx = DRW_context_state_get();
if (drwctx->evil_C != NULL) {
Paint *p = BKE_paint_get_active_from_context(drwctx->evil_C);
if (p && (p->flags & PAINT_FAST_NAVIGATE)) {
- fast_mode = drwctx->rv3d->rflag & RV3D_NAVIGATING;
+ scd->fast_mode = (drwctx->rv3d->rflag & RV3D_NAVIGATING) != 0;
}
}
- if (pbvh) {
- BKE_pbvh_draw_cb(pbvh,
- NULL,
- NULL,
- fast_mode,
- true,
- false,
- false,
- (void (*)(void *, GPUBatch *))draw_fn,
- shgroup);
- }
-}
+ BKE_pbvh_draw_cb(
+ pbvh, planes, NULL, use_vcol, (void (*)(void *, GPU_PBVH_Buffers *))sculpt_draw_cb, scd);
-void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
-{
- DRW_shgroup_call_generate_add(shgroup, sculpt_draw_cb, ob, obmat);
+#ifdef SCULPT_DEBUG_BUFFERS
+ int node_nr = 0;
+ DRW_debug_modelmat(scd->ob->obmat);
+ BKE_pbvh_draw_debug_cb(
+ pbvh,
+ (void (*)(void *d, const float min[3], const float max[3], PBVHNodeFlags f))sculpt_debug_cb,
+ &node_nr);
+#endif
}
-void DRW_shgroup_call_sculpt_wires_add(DRWShadingGroup *shgroup, Object *ob, float (*obmat)[4])
-{
- DRW_shgroup_call_generate_add(shgroup, sculpt_draw_wires_cb, ob, obmat);
+void DRW_shgroup_call_sculpt_add(
+ DRWShadingGroup *shgroup, Object *ob, bool use_wire, bool use_mask, bool use_vcol)
+{
+ DRWSculptCallbackData scd = {
+ .ob = ob,
+ .shading_groups = &shgroup,
+ .materials = NULL,
+ .use_wire = use_wire,
+ .use_mats = false,
+ .use_mask = use_mask,
+ };
+ drw_sculpt_generate_calls(&scd, use_vcol);
+}
+
+void DRW_shgroup_call_sculpt_with_materials_add(DRWShadingGroup **shgroups,
+ Material **materials,
+ Object *ob,
+ bool use_vcol)
+{
+ DRWSculptCallbackData scd = {
+ .ob = ob,
+ .shading_groups = shgroups,
+ .materials = materials,
+ .use_wire = false,
+ .use_mats = true,
+ .use_mask = false,
+ };
+ drw_sculpt_generate_calls(&scd, use_vcol);
}
void DRW_shgroup_call_dynamic_add_array(DRWShadingGroup *shgroup,
diff --git a/source/blender/draw/modes/overlay_mode.c b/source/blender/draw/modes/overlay_mode.c
index 68d9a7d3bed..90fac136f73 100644
--- a/source/blender/draw/modes/overlay_mode.c
+++ b/source/blender/draw/modes/overlay_mode.c
@@ -389,7 +389,7 @@ static void overlay_cache_populate(void *vedata, Object *ob)
}
if (is_sculpt_mode) {
- DRW_shgroup_call_sculpt_wires_add(shgrp, ob, ob->obmat);
+ DRW_shgroup_call_sculpt_add(shgrp, ob, true, false, false);
}
else {
DRW_shgroup_call_add(shgrp, geom, ob->obmat);
diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c
index 8adae0a4238..fb2619ce768 100644
--- a/source/blender/draw/modes/sculpt_mode.c
+++ b/source/blender/draw/modes/sculpt_mode.c
@@ -98,6 +98,7 @@ static struct {
} e_data = {NULL}; /* Engine data */
typedef struct SCULPT_PrivateData {
+ DRWShadingGroup *mask_overlay_grp;
/* This keeps the references of the shading groups for
* easy access in SCULPT_cache_populate() */
DRWShadingGroup *group_flat;
@@ -143,7 +144,7 @@ static void SCULPT_cache_init(void *vedata)
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.shader_smooth, psl->pass);
DRW_shgroup_uniform_float(shgrp, "maskOpacity", &v3d->overlay.sculpt_mode_mask_opacity, 1);
- stl->g_data->group_smooth = shgrp;
+ stl->g_data->mask_overlay_grp = shgrp;
}
}
@@ -213,8 +214,7 @@ static void SCULPT_cache_populate(void *vedata, Object *ob)
PBVH *pbvh = ob->sculpt->pbvh;
if (pbvh && pbvh_has_mask(pbvh)) {
- DRW_shgroup_call_generate_add(
- stl->g_data->group_smooth, sculpt_draw_mask_cb, ob, ob->obmat);
+ DRW_shgroup_call_sculpt_add(stl->g_data->mask_overlay_grp, ob, false, true, false);
}
}
}