Workbench: Support Active Vertex Color
authorJeroen Bakker <j.bakker@atmind.nl>
Tue, 16 Apr 2019 12:00:16 +0000 (14:00 +0200)
committerJeroen Bakker <j.bakker@atmind.nl>
Tue, 23 Apr 2019 10:05:33 +0000 (12:05 +0200)
Currently it is not possible to view the vertex colors of an object. To
optimize the workflow, workbench will need to support Vertex Colors.

The Vertex Colors is a new option in `shading->color_type`. When objects
do not have vertex color, the objects will be rendered with the
`V3D_SHADING_OBJECT_COLOR`.

In order to support vertex colors in workbench the current texture/solid
shading structure is migrated to a primary shaders and fallback shaders.

Fix: T57000

Reviewers: brecht, fclem

Differential Revision: https://developer.blender.org/D4694

19 files changed:
source/blender/blenkernel/BKE_pbvh.h
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/pbvh.c
source/blender/blenkernel/intern/pbvh_intern.h
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl
source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl
source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl
source/blender/draw/engines/workbench/workbench_deferred.c
source/blender/draw/engines/workbench/workbench_forward.c
source/blender/draw/engines/workbench/workbench_materials.c
source/blender/draw/engines/workbench/workbench_private.h
source/blender/draw/intern/draw_manager_data.c
source/blender/draw/modes/sculpt_mode.c
source/blender/gpu/GPU_buffers.h
source/blender/gpu/intern/gpu_buffers.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index 049fc58..6df6d36 100644 (file)
@@ -67,6 +67,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
                          struct MVert *verts,
                          int totvert,
                          struct CustomData *vdata,
+                         struct CustomData *ldata,
                          const struct MLoopTri *looptri,
                          int looptri_num);
 void BKE_pbvh_build_grids(PBVH *bvh,
@@ -153,6 +154,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
                       bool fast,
                       bool wires,
                       bool only_mask,
+                      bool show_vcol,
                       void (*draw_fn)(void *user_data, struct GPUBatch *batch),
                       void *user_data);
 
index e41f733..ea3834b 100644 (file)
@@ -296,6 +296,7 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
                         me->mvert,
                         me->totvert,
                         &me->vdata,
+                        &me->ldata,
                         looptri,
                         looptris_num);
 
index 00b3c86..7e8e724 100644 (file)
@@ -1379,8 +1379,15 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
 
   BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
 
-  BKE_pbvh_build_mesh(
-      pbvh, me->mpoly, me->mloop, me->mvert, me->totvert, &me->vdata, looptri, looptris_num);
+  BKE_pbvh_build_mesh(pbvh,
+                      me->mpoly,
+                      me->mloop,
+                      me->mvert,
+                      me->totvert,
+                      &me->vdata,
+                      &me->ldata,
+                      looptri,
+                      looptris_num);
 
   pbvh_show_diffuse_color_set(pbvh, ob->sculpt->show_diffuse_color);
   pbvh_show_mask_set(pbvh, ob->sculpt->show_mask);
index d0591b3..0a82d08 100644 (file)
@@ -542,6 +542,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
                          MVert *verts,
                          int totvert,
                          struct CustomData *vdata,
+                         struct CustomData *ldata,
                          const MLoopTri *looptri,
                          int looptri_num)
 {
@@ -557,6 +558,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
   bvh->totvert = totvert;
   bvh->leaf_limit = LEAF_LIMIT;
   bvh->vdata = vdata;
+  bvh->ldata = ldata;
 
   BB_reset(&cb);
 
@@ -1162,14 +1164,15 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
   BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
 }
 
-static int pbvh_get_buffers_update_flags(PBVH *bvh)
+static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol)
 {
   int update_flags = 0;
   update_flags |= bvh->show_mask ? GPU_PBVH_BUFFERS_SHOW_MASK : 0;
+  update_flags |= show_vcol ? GPU_PBVH_BUFFERS_SHOW_VCOL : 0;
   return update_flags;
 }
 
-static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
+static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, bool show_vcol)
 {
   /* can't be done in parallel with OpenGL */
   for (int n = 0; n < totnode; n++) {
@@ -1200,7 +1203,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
     }
 
     if (node->flag & PBVH_UpdateDrawBuffers) {
-      const int update_flags = pbvh_get_buffers_update_flags(bvh);
+      const int update_flags = pbvh_get_buffers_update_flags(bvh, show_vcol);
       switch (bvh->type) {
         case PBVH_GRIDS:
           GPU_pbvh_grid_buffers_update(node->draw_buffers,
@@ -1217,6 +1220,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
                                        node->vert_indices,
                                        node->uniq_verts + node->face_verts,
                                        CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
+                                       CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
                                        node->face_vert_indices,
                                        update_flags);
           break;
@@ -2229,6 +2233,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
                       bool fast,
                       bool wires,
                       bool only_mask,
+                      bool show_vcol,
                       void (*draw_fn)(void *user_data, GPUBatch *batch),
                       void *user_data)
 {
@@ -2249,7 +2254,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
                          &totnode);
 
   pbvh_update_normals(bvh, nodes, totnode, fnors);
-  pbvh_update_draw_buffers(bvh, nodes, totnode);
+  pbvh_update_draw_buffers(bvh, nodes, totnode, show_vcol);
 
   if (nodes) {
     MEM_freeN(nodes);
index 5fc41c5..74d7312 100644 (file)
@@ -132,6 +132,7 @@ struct PBVH {
   const MLoop *mloop;
   const MLoopTri *looptri;
   CustomData *vdata;
+  CustomData *ldata;
 
   /* Grid Data */
   CCGKey gridkey;
index 35acbbf..a58d1ea 100644 (file)
@@ -2361,6 +2361,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
                         me->mvert,
                         me->totvert,
                         &me->vdata,
+                        &me->ldata,
                         looptri,
                         looptris_num);
 
index e654141..5eff0b4 100644 (file)
@@ -25,6 +25,9 @@ in vec3 normal_viewport;
 #ifdef V3D_SHADING_TEXTURE_COLOR
 in vec2 uv_interp;
 #endif
+#ifdef V3D_SHADING_VERTEX_COLOR
+in vec3 vertexColor;
+#endif
 #ifdef V3D_LIGHTING_MATCAP
 uniform sampler2D matcapImage;
 #endif
@@ -42,11 +45,13 @@ void main()
 {
   vec4 diffuse_color;
 
-#ifdef V3D_SHADING_TEXTURE_COLOR
+#if defined(V3D_SHADING_TEXTURE_COLOR)
   diffuse_color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest);
   if (diffuse_color.a < ImageTransparencyCutoff) {
     discard;
   }
+#elif defined(V3D_SHADING_VERTEX_COLOR)
+  diffuse_color = vec4(vertexColor, 1.0);
 #else
   diffuse_color = vec4(materialDiffuseColor, 1.0);
 #endif /* V3D_SHADING_TEXTURE_COLOR */
index 6b2962a..2596fc4 100644 (file)
@@ -16,6 +16,9 @@ in vec3 normal_viewport;
 #ifdef V3D_SHADING_TEXTURE_COLOR
 in vec2 uv_interp;
 #endif
+#ifdef V3D_SHADING_VERTEX_COLOR
+in vec3 vertexColor;
+#endif
 
 #ifdef HAIR_SHADER
 flat in float hair_rand;
@@ -37,11 +40,13 @@ void main()
   float metallic, roughness;
   vec4 color;
 
-#  ifdef V3D_SHADING_TEXTURE_COLOR
+#  if defined(V3D_SHADING_TEXTURE_COLOR)
   color = workbench_sample_texture(image, uv_interp, imageSrgb, imageNearest);
   if (color.a < ImageTransparencyCutoff) {
     discard;
   }
+#  elif defined(V3D_SHADING_VERTEX_COLOR)
+  color.rgb = vertexColor;
 #  else
   color.rgb = materialDiffuseColor;
 #  endif
index dd73706..f2c684c 100644 (file)
@@ -10,6 +10,9 @@ uniform mat3 NormalMatrix;
 in vec3 pos;
 in vec3 nor;
 in vec2 u; /* active texture layer */
+#  ifdef V3D_SHADING_VERTEX_COLOR
+in vec3 c; /* active color */
+#  endif
 #  define uv u
 #else /* HAIR_SHADER */
 #  ifdef V3D_SHADING_TEXTURE_COLOR
@@ -25,6 +28,9 @@ out vec3 normal_viewport;
 #ifdef V3D_SHADING_TEXTURE_COLOR
 out vec2 uv_interp;
 #endif
+#ifdef V3D_SHADING_VERTEX_COLOR
+out vec3 vertexColor;
+#endif
 
 /* From http://libnoise.sourceforge.net/noisegen/index.html */
 float integer_noise(int n)
@@ -34,6 +40,16 @@ float integer_noise(int n)
   return (float(nn) / 1073741824.0);
 }
 
+#ifdef V3D_SHADING_VERTEX_COLOR
+vec3 srgb_to_linear_attr(vec3 c)
+{
+  c = max(c, vec3(0.0));
+  vec3 c1 = c * (1.0 / 12.92);
+  vec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));
+  return mix(c1, c2, step(vec3(0.04045), c));
+}
+#endif
+
 void main()
 {
 #ifdef HAIR_SHADER
@@ -68,6 +84,12 @@ void main()
   uv_interp = uv;
 #endif
 
+#ifdef V3D_SHADING_VERTEX_COLOR
+#  ifndef HAIR_SHADER
+  vertexColor = srgb_to_linear_attr(c);
+#  endif
+#endif
+
 #ifdef NORMAL_VIEWPORT_PASS_ENABLED
   normal_viewport = NormalMatrix * nor;
 #  ifndef HAIR_SHADER
index 91f4f35..efbe33b 100644 (file)
@@ -209,15 +209,15 @@ static GPUShader *workbench_cavity_shader_get(bool cavity, bool curvature)
 }
 
 static GPUShader *ensure_deferred_prepass_shader(WORKBENCH_PrivateData *wpd,
-                                                 bool use_textures,
+                                                 bool is_uniform_color,
                                                  bool is_hair,
                                                  eGPUShaderConfig sh_cfg)
 {
   WORKBENCH_DEFERRED_Shaders *sh_data = &e_data.sh_data[sh_cfg];
-  int index = workbench_material_get_prepass_shader_index(wpd, use_textures, is_hair);
+  int index = workbench_material_get_prepass_shader_index(wpd, is_uniform_color, is_hair);
   if (sh_data->prepass_sh_cache[index] == NULL) {
     const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
-    char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
+    char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
     char *prepass_vert = workbench_build_prepass_vert(is_hair);
     char *prepass_frag = workbench_build_prepass_frag();
     sh_data->prepass_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -263,10 +263,10 @@ static GPUShader *ensure_background_shader(WORKBENCH_PrivateData *wpd)
 
 static void select_deferred_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
 {
-  wpd->prepass_solid_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg);
-  wpd->prepass_solid_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg);
-  wpd->prepass_texture_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg);
-  wpd->prepass_texture_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg);
+  wpd->prepass_sh = ensure_deferred_prepass_shader(wpd, false, false, sh_cfg);
+  wpd->prepass_hair_sh = ensure_deferred_prepass_shader(wpd, false, true, sh_cfg);
+  wpd->prepass_uniform_sh = ensure_deferred_prepass_shader(wpd, true, false, sh_cfg);
+  wpd->prepass_uniform_hair_sh = ensure_deferred_prepass_shader(wpd, true, true, sh_cfg);
   wpd->composite_sh = ensure_deferred_composite_shader(wpd);
   wpd->background_sh = ensure_background_shader(wpd);
 }
@@ -846,8 +846,7 @@ static WORKBENCH_MaterialData *get_or_create_material_data(WORKBENCH_Data *vedat
   if (material == NULL) {
     material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
     material->shgrp = DRW_shgroup_create(
-        (color_type == V3D_SHADING_TEXTURE_COLOR) ? wpd->prepass_texture_sh :
-                                                    wpd->prepass_solid_sh,
+        (wpd->shading.color_type == color_type) ? wpd->prepass_sh : wpd->prepass_uniform_sh,
         (ob->dtx & OB_DRAWXRAY) ? psl->ghost_prepass_pass : psl->prepass_pass);
     workbench_material_copy(material, &material_template);
     DRW_shgroup_stencil_mask(material->shgrp, (ob->dtx & OB_DRAWXRAY) ? 0x00 : 0xFF);
@@ -881,13 +880,13 @@ static void workbench_cache_populate_particles(WORKBENCH_Data *vedata, Object *o
       ImageUser *iuser;
       int interp;
       workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat);
-      int color_type = workbench_material_determine_color_type(wpd, image, ob);
+      int color_type = workbench_material_determine_color_type(wpd, image, ob, false);
       WORKBENCH_MaterialData *material = get_or_create_material_data(
           vedata, ob, mat, image, iuser, color_type, interp);
 
-      struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ?
-                                     wpd->prepass_solid_hair_sh :
-                                     wpd->prepass_texture_hair_sh;
+      struct GPUShader *shader = (wpd->shading.color_type == color_type) ?
+                                     wpd->prepass_hair_sh :
+                                     wpd->prepass_uniform_hair_sh;
       DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
           ob,
           psys,
@@ -952,10 +951,10 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
           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);
+          int color_type = workbench_material_determine_color_type(wpd, image, ob, is_sculpt_mode);
           if (color_type == V3D_SHADING_MATERIAL_COLOR && mat && mat->a < 1.0) {
             material = workbench_forward_get_or_create_material_data(
-                vedata, ob, mat, image, iuser, color_type, 0);
+                vedata, ob, mat, image, iuser, color_type, 0, is_sculpt_mode);
             has_transp_mat = true;
           }
           else {
@@ -969,24 +968,33 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
     else if (ELEM(wpd->shading.color_type,
                   V3D_SHADING_SINGLE_COLOR,
                   V3D_SHADING_OBJECT_COLOR,
-                  V3D_SHADING_RANDOM_COLOR)) {
-      if ((ob->color[3] < 1.0f) && (wpd->shading.color_type == V3D_SHADING_OBJECT_COLOR)) {
+                  V3D_SHADING_RANDOM_COLOR,
+                  V3D_SHADING_VERTEX_COLOR)) {
+      int color_type = workbench_material_determine_color_type(wpd, NULL, ob, is_sculpt_mode);
+
+      if ((ob->color[3] < 1.0f) && (color_type == V3D_SHADING_OBJECT_COLOR)) {
         /* Hack */
         wpd->shading.xray_alpha = ob->color[3];
         material = workbench_forward_get_or_create_material_data(
-            vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0);
+            vedata, ob, NULL, NULL, NULL, color_type, 0, is_sculpt_mode);
         has_transp_mat = true;
       }
       else {
         /* Draw solid color */
-        material = get_or_create_material_data(
-            vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0);
+        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);
       }
       else {
-        struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+        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);
+        }
+
         if (geom) {
           DRW_shgroup_call_object_add(material->shgrp, geom, ob);
         }
@@ -1015,7 +1023,7 @@ void workbench_deferred_solid_cache_populate(WORKBENCH_Data *vedata, Object *ob)
               /* Hack */
               wpd->shading.xray_alpha = mat->a;
               material = workbench_forward_get_or_create_material_data(
-                  vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0);
+                  vedata, ob, mat, NULL, NULL, V3D_SHADING_MATERIAL_COLOR, 0, is_sculpt_mode);
               has_transp_mat = true;
             }
             else {
index 782e855..1117ee0 100644 (file)
@@ -137,7 +137,8 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
                                                                       Image *ima,
                                                                       ImageUser *iuser,
                                                                       int color_type,
-                                                                      int interp)
+                                                                      int interp,
+                                                                      bool is_sculpt_mode)
 {
   const DRWContextState *draw_ctx = DRW_context_state_get();
   WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
@@ -168,9 +169,9 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
     material = MEM_mallocN(sizeof(WORKBENCH_MaterialData), __func__);
 
     /* transparent accum */
-    grp = DRW_shgroup_create(color_type == V3D_SHADING_TEXTURE_COLOR ?
-                                 wpd->transparent_accum_texture_sh :
-                                 wpd->transparent_accum_sh,
+    grp = DRW_shgroup_create(wpd->shading.color_type == color_type ?
+                                 wpd->transparent_accum_sh :
+                                 wpd->transparent_accum_uniform_sh,
                              psl->transparent_accum_pass);
     DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
     DRW_shgroup_uniform_float_copy(grp, "alpha", wpd->shading.xray_alpha);
@@ -194,7 +195,7 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
     material->shgrp = grp;
 
     /* Depth */
-    if (workbench_material_determine_color_type(wpd, material->ima, ob) ==
+    if (workbench_material_determine_color_type(wpd, material->ima, ob, is_sculpt_mode) ==
         V3D_SHADING_TEXTURE_COLOR) {
       material->shgrp_object_outline = DRW_shgroup_create(sh_data->object_outline_texture_sh,
                                                           psl->object_outline_pass);
@@ -217,15 +218,15 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
 }
 
 static GPUShader *ensure_forward_accum_shaders(WORKBENCH_PrivateData *wpd,
-                                               bool use_textures,
+                                               bool is_uniform_color,
                                                bool is_hair,
                                                eGPUShaderConfig sh_cfg)
 {
   WORKBENCH_FORWARD_Shaders *sh_data = &e_data.sh_data[sh_cfg];
-  int index = workbench_material_get_accum_shader_index(wpd, use_textures, is_hair);
+  int index = workbench_material_get_accum_shader_index(wpd, is_uniform_color, is_hair);
   if (sh_data->transparent_accum_sh_cache[index] == NULL) {
     const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
-    char *defines = workbench_material_build_defines(wpd, use_textures, is_hair);
+    char *defines = workbench_material_build_defines(wpd, is_uniform_color, is_hair);
     char *transparent_accum_vert = workbench_build_forward_vert(is_hair);
     char *transparent_accum_frag = workbench_build_forward_transparent_accum_frag();
     sh_data->transparent_accum_sh_cache[index] = GPU_shader_create_from_arrays({
@@ -258,8 +259,8 @@ void workbench_forward_choose_shaders(WORKBENCH_PrivateData *wpd, eGPUShaderConf
   wpd->composite_sh = ensure_forward_composite_shaders(wpd);
   wpd->transparent_accum_sh = ensure_forward_accum_shaders(wpd, false, false, sh_cfg);
   wpd->transparent_accum_hair_sh = ensure_forward_accum_shaders(wpd, false, true, sh_cfg);
-  wpd->transparent_accum_texture_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg);
-  wpd->transparent_accum_texture_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg);
+  wpd->transparent_accum_uniform_sh = ensure_forward_accum_shaders(wpd, true, false, sh_cfg);
+  wpd->transparent_accum_uniform_hair_sh = ensure_forward_accum_shaders(wpd, true, true, sh_cfg);
 }
 
 void workbench_forward_outline_shaders_ensure(WORKBENCH_PrivateData *wpd, eGPUShaderConfig sh_cfg)
@@ -497,13 +498,13 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
       ImageUser *iuser;
       int interp;
       workbench_material_get_image_and_mat(ob, part->omat, &image, &iuser, &interp, &mat);
-      int color_type = workbench_material_determine_color_type(wpd, image, ob);
+      int color_type = workbench_material_determine_color_type(wpd, image, ob, false);
       WORKBENCH_MaterialData *material = workbench_forward_get_or_create_material_data(
-          vedata, ob, mat, image, iuser, color_type, interp);
+          vedata, ob, mat, image, iuser, color_type, interp, false);
 
-      struct GPUShader *shader = (color_type != V3D_SHADING_TEXTURE_COLOR) ?
+      struct GPUShader *shader = (wpd->shading.color_type == color_type) ?
                                      wpd->transparent_accum_hair_sh :
-                                     wpd->transparent_accum_texture_hair_sh;
+                                     wpd->transparent_accum_uniform_hair_sh;
       DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
           ob, psys, md, psl->transparent_accum_pass, shader);
       DRW_shgroup_uniform_block(shgrp, "world_block", wpd->world_ubo);
@@ -579,9 +580,9 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
           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);
+          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);
+              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);
         }
@@ -594,12 +595,21 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
       if (ELEM(wpd->shading.color_type,
                V3D_SHADING_SINGLE_COLOR,
                V3D_SHADING_OBJECT_COLOR,
-               V3D_SHADING_RANDOM_COLOR)) {
+               V3D_SHADING_RANDOM_COLOR,
+               V3D_SHADING_VERTEX_COLOR)) {
         /* No material split needed */
-        struct GPUBatch *geom = DRW_cache_object_surface_get(ob);
+        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);
+        }
         if (geom) {
           material = workbench_forward_get_or_create_material_data(
-              vedata, ob, NULL, NULL, NULL, wpd->shading.color_type, 0);
+              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) {
@@ -631,7 +641,7 @@ 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);
+                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) {
index d73eee3..6151c1f 100644 (file)
@@ -31,6 +31,7 @@
 #include "BLI_hash.h"
 
 #include "DNA_node_types.h"
+#include "DNA_mesh_types.h"
 
 #include "ED_uvedit.h"
 
@@ -67,7 +68,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
     hsv_to_rgb_v(hsv, data->diffuse_color);
     copy_v3_v3(data->base_color, data->diffuse_color);
   }
-  else if (color_type == V3D_SHADING_OBJECT_COLOR) {
+  else if (ELEM(color_type, V3D_SHADING_OBJECT_COLOR, V3D_SHADING_VERTEX_COLOR)) {
     copy_v3_v3(data->diffuse_color, ob->color);
     copy_v3_v3(data->base_color, data->diffuse_color);
   }
@@ -90,9 +91,14 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
   }
 }
 
-char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_textures, bool is_hair)
+char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
+                                       bool is_uniform_color,
+                                       bool is_hair)
 {
   char *str = NULL;
+  bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
+  bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
+                           !is_uniform_color;
 
   DynStr *ds = BLI_dynstr_new();
 
@@ -126,6 +132,9 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd, bool use_text
   if (NORMAL_VIEWPORT_PASS_ENABLED(wpd)) {
     BLI_dynstr_append(ds, "#define NORMAL_VIEWPORT_PASS_ENABLED\n");
   }
+  if (use_vertex_colors) {
+    BLI_dynstr_append(ds, "#define V3D_SHADING_VERTEX_COLOR\n");
+  }
   if (use_textures) {
     BLI_dynstr_append(ds, "#define V3D_SHADING_TEXTURE_COLOR\n");
   }
@@ -160,6 +169,7 @@ uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool
   result += BLI_ghashutil_uinthash_v4_murmur(input);
 
   result += BLI_ghashutil_uinthash((uint)is_ghost);
+  result += BLI_ghashutil_uinthash(material_template->color_type);
 
   /* add texture reference */
   if (material_template->ima) {
@@ -184,9 +194,12 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
 }
 
 int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
-                                                bool use_textures,
+                                                bool is_uniform_color,
                                                 bool is_hair)
 {
+  bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
+  bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
+                           !is_uniform_color;
   /* NOTE: change MAX_PREPASS_SHADERS accordingly when modifying this function. */
   int index = 0;
   SET_FLAG_FROM_TEST(index, is_hair, 1 << 0);
@@ -195,32 +208,46 @@ int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
   SET_FLAG_FROM_TEST(index, NORMAL_VIEWPORT_PASS_ENABLED(wpd), 1 << 3);
   SET_FLAG_FROM_TEST(index, MATCAP_ENABLED(wpd), 1 << 4);
   SET_FLAG_FROM_TEST(index, use_textures, 1 << 5);
+  SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 6);
   BLI_assert(index < MAX_PREPASS_SHADERS);
   return index;
 }
 
 int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
-                                              bool use_textures,
+                                              bool is_uniform_color,
                                               bool is_hair)
 {
+  bool use_textures = (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR) && !is_uniform_color;
+  bool use_vertex_colors = (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR) &&
+                           !is_uniform_color;
   /* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
   int index = 0;
   /* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
   index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
   SET_FLAG_FROM_TEST(index, use_textures, 1 << 2);
-  SET_FLAG_FROM_TEST(index, is_hair, 1 << 3);
+  SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 3);
+  SET_FLAG_FROM_TEST(index, is_hair, 1 << 4);
   /* 1 bits SHADOWS (only facing factor) */
-  SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 4);
+  SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5);
   BLI_assert(index < MAX_ACCUM_SHADERS);
   return index;
 }
 
-int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob)
+int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd,
+                                            Image *ima,
+                                            Object *ob,
+                                            bool is_sculpt_mode)
 {
   int color_type = wpd->shading.color_type;
-  if ((color_type == V3D_SHADING_TEXTURE_COLOR && ima == NULL) || (ob->dt < OB_TEXTURE)) {
+  const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
+
+  if ((color_type == V3D_SHADING_TEXTURE_COLOR && (ima == NULL || is_sculpt_mode)) ||
+      (ob->dt < OB_TEXTURE)) {
     color_type = V3D_SHADING_MATERIAL_COLOR;
   }
+  if (color_type == V3D_SHADING_VERTEX_COLOR && (me == NULL || me->mloopcol == NULL)) {
+    color_type = V3D_SHADING_OBJECT_COLOR;
+  }
   return color_type;
 }
 
@@ -264,7 +291,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
     return;
   }
 
-  if (workbench_material_determine_color_type(wpd, material->ima, ob) ==
+  if (workbench_material_determine_color_type(wpd, material->ima, ob, false) ==
       V3D_SHADING_TEXTURE_COLOR) {
     ImBuf *ibuf = BKE_image_acquire_ibuf(material->ima, material->iuser, NULL);
     const bool do_color_correction = wpd->use_color_management &&
index 0e2ef2f..3cfb128 100644 (file)
 #define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
 #define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
 #define MAX_COMPOSITE_SHADERS (1 << 6)
-#define MAX_PREPASS_SHADERS (1 << 6)
-#define MAX_ACCUM_SHADERS (1 << 5)
+#define MAX_PREPASS_SHADERS (1 << 7)
+#define MAX_ACCUM_SHADERS (1 << 6)
 #define MAX_CAVITY_SHADERS (1 << 3)
 
 #define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
+#define VERTEX_COLORS_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_VERTEX_COLOR)
 #define FLAT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_FLAT)
 #define STUDIOLIGHT_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_STUDIO)
 #define MATCAP_ENABLED(wpd) (wpd->shading.light == V3D_LIGHTING_MATCAP)
@@ -69,7 +70,8 @@
   (ELEM(wpd->shading.color_type, \
         V3D_SHADING_MATERIAL_COLOR, \
         V3D_SHADING_OBJECT_COLOR, \
-        V3D_SHADING_TEXTURE_COLOR))
+        V3D_SHADING_TEXTURE_COLOR, \
+        V3D_SHADING_VERTEX_COLOR))
 
 #define IS_NAVIGATING(wpd) \
   ((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING))
@@ -213,16 +215,16 @@ BLI_STATIC_ASSERT_ALIGN(WORKBENCH_UBO_World, 16)
 typedef struct WORKBENCH_PrivateData {
   struct GHash *material_hash;
   struct GHash *material_transp_hash;
-  struct GPUShader *prepass_solid_sh;
-  struct GPUShader *prepass_solid_hair_sh;
-  struct GPUShader *prepass_texture_sh;
-  struct GPUShader *prepass_texture_hair_sh;
+  struct GPUShader *prepass_sh;
+  struct GPUShader *prepass_hair_sh;
+  struct GPUShader *prepass_uniform_sh;
+  struct GPUShader *prepass_uniform_hair_sh;
   struct GPUShader *composite_sh;
   struct GPUShader *background_sh;
   struct GPUShader *transparent_accum_sh;
   struct GPUShader *transparent_accum_hair_sh;
-  struct GPUShader *transparent_accum_texture_sh;
-  struct GPUShader *transparent_accum_texture_hair_sh;
+  struct GPUShader *transparent_accum_uniform_sh;
+  struct GPUShader *transparent_accum_uniform_hair_sh;
   View3DShading shading;
   StudioLight *studio_light;
   const UserDef *preferences;
@@ -353,7 +355,8 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
                                                                       Image *ima,
                                                                       ImageUser *iuser,
                                                                       int color_type,
-                                                                      int interp);
+                                                                      int interp,
+                                                                      bool is_sculpt_mode);
 
 /* workbench_effect_aa.c */
 void workbench_aa_create_pass(WORKBENCH_Data *vedata, GPUTexture **tx);
@@ -382,11 +385,14 @@ void workbench_dof_create_pass(WORKBENCH_Data *vedata,
 void workbench_dof_draw_pass(WORKBENCH_Data *vedata);
 
 /* workbench_materials.c */
-int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd, Image *ima, Object *ob);
+int workbench_material_determine_color_type(WORKBENCH_PrivateData *wpd,
+                                            Image *ima,
+                                            Object *ob,
+                                            bool is_sculpt_mode);
 void workbench_material_get_image_and_mat(
     Object *ob, int mat_nr, Image **r_image, ImageUser **r_iuser, int *r_interp, Material **r_mat);
 char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
-                                       bool use_textures,
+                                       bool is_uniform_color,
                                        bool is_hair);
 void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
                                     Object *ob,
@@ -395,10 +401,10 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
 uint workbench_material_get_hash(WORKBENCH_MaterialData *material_template, bool is_ghost);
 int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd);
 int workbench_material_get_prepass_shader_index(WORKBENCH_PrivateData *wpd,
-                                                bool use_textures,
+                                                bool is_uniform_color,
                                                 bool is_hair);
 int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
-                                              bool use_textures,
+                                              bool is_uniform_color,
                                               bool is_hair);
 void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
                                         DRWShadingGroup *grp,
index 4a9f4fe..77f8497 100644 (file)
@@ -634,6 +634,17 @@ void DRW_shgroup_call_generate_add(DRWShadingGroup *shgroup,
   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)
@@ -654,8 +665,16 @@ static void sculpt_draw_cb(DRWShadingGroup *shgroup,
   }
 
   if (pbvh) {
-    BKE_pbvh_draw_cb(
-        pbvh, NULL, NULL, fast_mode, false, false, (void (*)(void *, GPUBatch *))draw_fn, shgroup);
+    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);
   }
 }
 
@@ -679,8 +698,15 @@ static void sculpt_draw_wires_cb(DRWShadingGroup *shgroup,
   }
 
   if (pbvh) {
-    BKE_pbvh_draw_cb(
-        pbvh, NULL, NULL, fast_mode, true, false, (void (*)(void *, GPUBatch *))draw_fn, shgroup);
+    BKE_pbvh_draw_cb(pbvh,
+                     NULL,
+                     NULL,
+                     fast_mode,
+                     true,
+                     false,
+                     false,
+                     (void (*)(void *, GPUBatch *))draw_fn,
+                     shgroup);
   }
 }
 
index e2b73a0..e5d10a5 100644 (file)
@@ -161,6 +161,7 @@ static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup,
                      false,
                      false,
                      true,
+                     false,
                      (void (*)(void *, struct GPUBatch *))draw_fn,
                      shgroup);
   }
index 895887c..2004717 100644 (file)
@@ -35,6 +35,7 @@ struct MLoop;
 struct MLoopTri;
 struct MPoly;
 struct MVert;
+struct MLoopCol;
 struct PBVH;
 
 /* Buffers for drawing from PBVH grids. */
@@ -57,6 +58,7 @@ GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading);
 
 enum {
   GPU_PBVH_BUFFERS_SHOW_MASK = (1 << 1),
+  GPU_PBVH_BUFFERS_SHOW_VCOL = (1 << 1),
 };
 
 void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
@@ -64,6 +66,7 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                   const int *vert_indices,
                                   int totvert,
                                   const float *vmask,
+                                  const struct MLoopCol *vcol,
                                   const int (*face_vert_indices)[3],
                                   const int update_flags);
 
index 9b89fc3..ebe5fcf 100644 (file)
@@ -91,7 +91,7 @@ struct GPU_PBVH_Buffers {
 };
 
 static struct {
-  uint pos, nor, msk;
+  uint pos, nor, msk, col;
 } g_vbo_id = {0};
 
 /** \} */
@@ -131,7 +131,10 @@ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len)
       g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
       g_vbo_id.nor = GPU_vertformat_attr_add(
           &format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+      /* TODO: Do not allocate these `.msk` and `.col` when they are not used. */
       g_vbo_id.msk = GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+      g_vbo_id.col = GPU_vertformat_attr_add(
+          &format, "c", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
     }
     buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC);
   }
@@ -183,10 +186,12 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                   const int *vert_indices,
                                   int totvert,
                                   const float *vmask,
+                                  const MLoopCol *vcol,
                                   const int (*face_vert_indices)[3],
                                   const int update_flags)
 {
   const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+  const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
   bool empty_mask = true;
 
   {
@@ -216,6 +221,18 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
             }
           }
         }
+
+        if (vcol && show_vcol) {
+          for (uint i = 0; i < buffers->face_indices_len; i++) {
+            const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+            for (int j = 0; j < 3; j++) {
+              const int loop_index = lt->tri[j];
+              const int vidx = face_vert_indices[i][j];
+              const uchar *elem = &vcol[loop_index].r;
+              GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vidx, elem);
+            }
+          }
+        }
       }
       else {
         /* calculate normal for each polygon only once */
@@ -256,6 +273,12 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
             GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no);
             GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask);
 
+            if (vcol && show_vcol) {
+              const uint loop_index = lt->tri[j];
+              const uchar *elem = &vcol[loop_index].r;
+              GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, elem);
+            }
+
             vbo_index++;
           }
 
@@ -511,10 +534,12 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
                                   const int update_flags)
 {
   const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+  const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
   bool empty_mask = true;
   int i, j, k, x, y;
 
   const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
+  static char vcol[4] = {255, 255, 255, 255};
 
   /* Build VBO */
   const int has_mask = key->has_mask;
@@ -577,6 +602,11 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
               GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask);
               empty_mask = empty_mask && (fmask == 0.0f);
             }
+
+            if (show_vcol) {
+              GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index, &vcol);
+            }
+
             vbo_index += 1;
           }
         }
@@ -623,6 +653,10 @@ void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers,
               GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fmask);
               empty_mask = empty_mask && (fmask == 0.0f);
             }
+            GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 0, &vcol);
+            GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 1, &vcol);
+            GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 2, &vcol);
+            GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.col, vbo_index + 3, &vcol);
             vbo_index += 4;
           }
         }
@@ -677,6 +711,7 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert *v,
                                                const float *fmask,
                                                const int cd_vert_mask_offset,
                                                const bool show_mask,
+                                               const bool show_vcol,
                                                bool *empty_mask)
 {
   if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
@@ -694,6 +729,11 @@ static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert *v,
       *empty_mask = *empty_mask && (effective_mask == 0.0f);
     }
 
+    if (show_vcol) {
+      static char vcol[4] = {255, 255, 255, 255};
+      GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, &vcol);
+    }
+
     /* Assign index for use in the triangle index buffer */
     /* note: caller must set:  bm->elem_index_dirty |= BM_VERT; */
     BM_elem_index_set(v, (*v_index)); /* set_dirty! */
@@ -751,6 +791,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                    const int update_flags)
 {
   const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
+  const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
   int tottri, totvert, maxvert = 0;
   bool empty_mask = true;
 
@@ -799,6 +840,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                            NULL,
                                            cd_vert_mask_offset,
                                            show_mask,
+                                           show_vcol,
                                            &empty_mask);
       }
 
@@ -810,6 +852,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                            NULL,
                                            cd_vert_mask_offset,
                                            show_mask,
+                                           show_vcol,
                                            &empty_mask);
       }
 
@@ -851,6 +894,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
                                                &fmask,
                                                cd_vert_mask_offset,
                                                show_mask,
+                                               show_vcol,
                                                &empty_mask);
           }
         }
index 60a7752..0667ab3 100644 (file)
@@ -432,6 +432,7 @@ enum {
   V3D_SHADING_SINGLE_COLOR = 2,
   V3D_SHADING_TEXTURE_COLOR = 3,
   V3D_SHADING_OBJECT_COLOR = 4,
+  V3D_SHADING_VERTEX_COLOR = 5,
 };
 
 /** #View3DShading.background_type */
index 5ddb1d7..ca00ce9 100644 (file)
@@ -362,6 +362,7 @@ static const EnumPropertyItem rna_enum_shading_color_type_items[] = {
     {V3D_SHADING_MATERIAL_COLOR, "MATERIAL", 0, "Material", "Show material color"},
     {V3D_SHADING_OBJECT_COLOR, "OBJECT", 0, "Object", "Show object color"},
     {V3D_SHADING_RANDOM_COLOR, "RANDOM", 0, "Random", "Show random object color"},
+    {V3D_SHADING_VERTEX_COLOR, "VERTEX", 0, "Vertex", "Show active vertex color"},
     {V3D_SHADING_TEXTURE_COLOR, "TEXTURE", 0, "Texture", "Show texture"},
     {0, NULL, 0, NULL, NULL},
 };
@@ -1080,6 +1081,8 @@ static const EnumPropertyItem *rna_View3DShading_color_type_itemf(bContext *UNUS
         &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_OBJECT_COLOR);
     RNA_enum_items_add_value(
         &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_RANDOM_COLOR);
+    RNA_enum_items_add_value(
+        &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_VERTEX_COLOR);
     if (shading->light != V3D_LIGHTING_MATCAP) {
       RNA_enum_items_add_value(
           &item, &totitem, rna_enum_shading_color_type_items, V3D_SHADING_TEXTURE_COLOR);
@@ -3001,6 +3004,7 @@ static void rna_def_space_view3d_shading(BlenderRNA *brna)
   RNA_def_property_enum_items(prop, rna_enum_shading_color_type_items);
   RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_View3DShading_color_type_itemf");
   RNA_def_property_ui_text(prop, "Color", "Color Type");
+  RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
   RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
 
   prop = RNA_def_property(srna, "wireframe_color_type", PROP_ENUM, PROP_NONE);