diff options
author | Jeroen Bakker <j.bakker@atmind.nl> | 2019-04-16 15:00:16 +0300 |
---|---|---|
committer | Jeroen Bakker <j.bakker@atmind.nl> | 2019-04-23 13:05:33 +0300 |
commit | ee701baff8caf6d184fa245e170c1e67981e2608 (patch) | |
tree | 0e84a0829141682cedfdf9770e755a3e9f833282 /source/blender/draw | |
parent | c9ed39925a51fc421a734027c2ef386157392f3b (diff) |
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
Diffstat (limited to 'source/blender/draw')
9 files changed, 181 insertions, 71 deletions
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl index e654141df5c..5eff0b41e20 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl @@ -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 */ diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl index 6b2962a66da..2596fc4cf88 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_frag.glsl @@ -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 diff --git a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl index dd737063f61..f2c684cdb6a 100644 --- a/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl +++ b/source/blender/draw/engines/workbench/shaders/workbench_prepass_vert.glsl @@ -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 diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c index 91f4f351c7b..efbe33b45da 100644 --- a/source/blender/draw/engines/workbench/workbench_deferred.c +++ b/source/blender/draw/engines/workbench/workbench_deferred.c @@ -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 { diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c index 782e85597d7..1117ee0126b 100644 --- a/source/blender/draw/engines/workbench/workbench_forward.c +++ b/source/blender/draw/engines/workbench/workbench_forward.c @@ -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) { diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c index d73eee37a98..6151c1f54dd 100644 --- a/source/blender/draw/engines/workbench/workbench_materials.c +++ b/source/blender/draw/engines/workbench/workbench_materials.c @@ -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 && diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h index 0e2ef2f94d2..3cfb1283416 100644 --- a/source/blender/draw/engines/workbench/workbench_private.h +++ b/source/blender/draw/engines/workbench/workbench_private.h @@ -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, diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c index 4a9f4fe910b..77f84976165 100644 --- a/source/blender/draw/intern/draw_manager_data.c +++ b/source/blender/draw/intern/draw_manager_data.c @@ -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); } } diff --git a/source/blender/draw/modes/sculpt_mode.c b/source/blender/draw/modes/sculpt_mode.c index e2b73a0fac7..e5d10a5d6e1 100644 --- a/source/blender/draw/modes/sculpt_mode.c +++ b/source/blender/draw/modes/sculpt_mode.c @@ -161,6 +161,7 @@ static void sculpt_draw_mask_cb(DRWShadingGroup *shgroup, false, false, true, + false, (void (*)(void *, struct GPUBatch *))draw_fn, shgroup); } |