Workbench: Support Active Vertex Color

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
This commit is contained in:
Jeroen Bakker 2019-04-16 14:00:16 +02:00
parent c9ed39925a
commit ee701baff8
Notes: blender-bot 2023-03-24 17:05:22 +01:00
Referenced by issue #68855, Texture on active object is not visible in solid view with sculpt mode activated
19 changed files with 257 additions and 78 deletions

View 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);

View File

@ -296,6 +296,7 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
me->mvert,
me->totvert,
&me->vdata,
&me->ldata,
looptri,
looptris_num);

View 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);

View 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);

View File

@ -132,6 +132,7 @@ struct PBVH {
const MLoop *mloop;
const MLoopTri *looptri;
CustomData *vdata;
CustomData *ldata;
/* Grid Data */
CCGKey gridkey;

View 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);

View 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 */

View 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

View 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

View 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 {

View 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) {

View 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 &&

View File

@ -37,11 +37,12 @@
#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,

View 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);
}
}

View File

@ -161,6 +161,7 @@ static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup,
false,
false,
true,
false,
(void (*)(void *, struct GPUBatch *))draw_fn,
shgroup);
}

View 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);

View 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);
}
}

View 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 */

View 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);