diff options
Diffstat (limited to 'source')
12 files changed, 252 insertions, 664 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index d20745f28c0..9744f2e3cee 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -67,7 +67,6 @@ set(SRC intern/mesh_extractors/extract_mesh_vbo_skin_roots.cc intern/mesh_extractors/extract_mesh_vbo_tan.cc intern/mesh_extractors/extract_mesh_vbo_uv.cc - intern/mesh_extractors/extract_mesh_vbo_vcol.cc intern/mesh_extractors/extract_mesh_vbo_weights.cc intern/draw_attributes.cc intern/draw_cache_impl_curve.cc diff --git a/source/blender/draw/intern/draw_attributes.cc b/source/blender/draw/intern/draw_attributes.cc index 3f187aef8e6..011d72e9e8f 100644 --- a/source/blender/draw/intern/draw_attributes.cc +++ b/source/blender/draw/intern/draw_attributes.cc @@ -88,7 +88,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data, int *r_layer_index, eCustomDataType *r_type) { - const eCustomDataType possible_attribute_types[7] = { + const eCustomDataType possible_attribute_types[8] = { CD_PROP_BOOL, CD_PROP_INT8, CD_PROP_INT32, @@ -96,6 +96,7 @@ bool drw_custom_data_match_attribute(const CustomData *custom_data, CD_PROP_FLOAT2, CD_PROP_FLOAT3, CD_PROP_COLOR, + CD_PROP_BYTE_COLOR, }; for (int i = 0; i < ARRAY_SIZE(possible_attribute_types); i++) { diff --git a/source/blender/draw/intern/draw_cache_extract.hh b/source/blender/draw/intern/draw_cache_extract.hh index c7127d169e1..203da22406c 100644 --- a/source/blender/draw/intern/draw_cache_extract.hh +++ b/source/blender/draw/intern/draw_cache_extract.hh @@ -55,7 +55,6 @@ enum { struct DRW_MeshCDMask { uint32_t uv : 8; uint32_t tan : 8; - uint32_t vcol : 8; uint32_t orco : 1; uint32_t tan_orco : 1; uint32_t sculpt_overlays : 1; @@ -111,7 +110,6 @@ struct MeshBufferList { GPUVertBuf *weights; /* extend */ GPUVertBuf *uv; GPUVertBuf *tan; - GPUVertBuf *vcol; GPUVertBuf *sculpt_data; GPUVertBuf *orco; /* Only for edit mode. */ diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.cc b/source/blender/draw/intern/draw_cache_extract_mesh.cc index 380736ef656..b1d1631cb6d 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh.cc @@ -619,7 +619,6 @@ void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph, EXTRACT_ADD_REQUESTED(vbo, lnor); EXTRACT_ADD_REQUESTED(vbo, uv); EXTRACT_ADD_REQUESTED(vbo, tan); - EXTRACT_ADD_REQUESTED(vbo, vcol); EXTRACT_ADD_REQUESTED(vbo, sculpt_data); EXTRACT_ADD_REQUESTED(vbo, orco); EXTRACT_ADD_REQUESTED(vbo, edge_fac); @@ -848,7 +847,6 @@ void mesh_buffer_cache_create_requested_subdiv(MeshBatchCache *cache, EXTRACT_ADD_REQUESTED(vbo, edituv_stretch_angle); EXTRACT_ADD_REQUESTED(ibo, lines_paint_mask); EXTRACT_ADD_REQUESTED(ibo, lines_adjacency); - EXTRACT_ADD_REQUESTED(vbo, vcol); EXTRACT_ADD_REQUESTED(vbo, weights); EXTRACT_ADD_REQUESTED(vbo, sculpt_data); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc index 77cbb5efa12..fc09606f9f3 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc +++ b/source/blender/draw/intern/draw_cache_extract_mesh_render_data.cc @@ -431,6 +431,30 @@ void mesh_render_data_update_normals(MeshRenderData *mr, const eMRDataType data_ } } +static void retrieve_active_attribute_names(MeshRenderData &mr, + const Object &object, + const Mesh &mesh) +{ + const Mesh *mesh_final = editmesh_final_or_this(&object, &mesh); + const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(mesh_final); + const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(mesh_final); + + /* Necessary because which attributes are active/default is stored in #CustomData. */ + Mesh me_query = blender::dna::shallow_zero_initialize(); + BKE_id_attribute_copy_domains_temp( + ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); + + mr.active_color_name = nullptr; + mr.default_color_name = nullptr; + + if (const CustomDataLayer *active = BKE_id_attributes_active_color_get(&me_query.id)) { + mr.active_color_name = active->name; + } + if (const CustomDataLayer *render = BKE_id_attributes_render_color_get(&me_query.id)) { + mr.default_color_name = render->name; + } +} + MeshRenderData *mesh_render_data_create(Object *object, Mesh *me, const bool is_editmode, @@ -566,6 +590,8 @@ MeshRenderData *mesh_render_data_create(Object *object, mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len); } + retrieve_active_attribute_names(*mr, *object, *me); + return mr; } diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.cc b/source/blender/draw/intern/draw_cache_impl_mesh.cc index e93b1a66b66..d3d9db13005 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.cc +++ b/source/blender/draw/intern/draw_cache_impl_mesh.cc @@ -21,6 +21,7 @@ #include "BLI_math_vector.h" #include "BLI_span.hh" #include "BLI_string.h" +#include "BLI_string_ref.hh" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -67,6 +68,7 @@ using blender::IndexRange; using blender::Map; using blender::Span; +using blender::StringRefNull; /* ---------------------------------------------------------------------- */ /** \name Dependencies between buffer and batch @@ -115,8 +117,6 @@ static constexpr DRWBatchFlag batches_that_use_buffer(const int buffer_index) MBC_SURFACE_PER_MAT; case BUFFER_INDEX(vbo.tan): return MBC_SURFACE_PER_MAT; - case BUFFER_INDEX(vbo.vcol): - return MBC_SURFACE | MBC_SURFACE_PER_MAT; case BUFFER_INDEX(vbo.sculpt_data): return MBC_SCULPT_OVERLAYS; case BUFFER_INDEX(vbo.orco): @@ -236,87 +236,11 @@ BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a) *((uint32_t *)a) = 0; } -BLI_INLINE const Mesh *editmesh_final_or_this(const Object *object, const Mesh *me) -{ - if (me->edit_mesh != nullptr) { - Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); - if (editmesh_eval_final != nullptr) { - return editmesh_eval_final; - } - } - - return me; -} - static void mesh_cd_calc_edit_uv_layer(const Mesh *UNUSED(me), DRW_MeshCDMask *cd_used) { cd_used->edit_uv = 1; } -BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - case ME_WRAPPER_TYPE_MDATA: - return &me->ldata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->ldata; - break; - } - - BLI_assert(0); - return &me->ldata; -} - -BLI_INLINE const CustomData *mesh_cd_pdata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - case ME_WRAPPER_TYPE_MDATA: - return &me->pdata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->pdata; - break; - } - - BLI_assert(0); - return &me->pdata; -} - -BLI_INLINE const CustomData *mesh_cd_edata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - case ME_WRAPPER_TYPE_MDATA: - return &me->edata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->edata; - break; - } - - BLI_assert(0); - return &me->edata; -} - -BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) -{ - switch ((eMeshWrapperType)me->runtime.wrapper_type) { - case ME_WRAPPER_TYPE_SUBD: - case ME_WRAPPER_TYPE_MDATA: - return &me->vdata; - break; - case ME_WRAPPER_TYPE_BMESH: - return &me->edit_mesh->bm->vdata; - break; - } - - BLI_assert(0); - return &me->vdata; -} - static void mesh_cd_calc_active_uv_layer(const Object *object, const Mesh *me, DRW_MeshCDMask *cd_used) @@ -341,75 +265,6 @@ static void mesh_cd_calc_active_mask_uv_layer(const Object *object, } } -static void mesh_cd_calc_active_mloopcol_layer(const Object *object, - const Mesh *me, - DRW_MeshCDMask *cd_used) -{ - const Mesh *me_final = editmesh_final_or_this(object, me); - Mesh me_query = blender::dna::shallow_zero_initialize(); - - const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); - const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); - - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - - const CustomDataLayer *layer = BKE_id_attributes_active_color_get(&me_query.id); - int layer_i = BKE_id_attribute_to_index( - &me_query.id, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - - if (layer_i != -1) { - cd_used->vcol |= (1UL << (uint)layer_i); - } -} - -static uint mesh_cd_calc_gpu_layers_vcol_used(const Mesh *me_query, - const CustomData *cd_vdata, - const CustomData *cd_ldata, - const char name[]) -{ - const CustomDataLayer *layer = nullptr; - eAttrDomain domain; - - if (name[0]) { - int layer_i = 0; - - domain = ATTR_DOMAIN_POINT; - layer_i = CustomData_get_named_layer_index(cd_vdata, CD_PROP_COLOR, name); - layer_i = layer_i == -1 ? - CustomData_get_named_layer_index(cd_vdata, CD_PROP_BYTE_COLOR, name) : - layer_i; - - if (layer_i == -1) { - domain = ATTR_DOMAIN_CORNER; - layer_i = layer_i == -1 ? CustomData_get_named_layer_index(cd_ldata, CD_PROP_COLOR, name) : - layer_i; - layer_i = layer_i == -1 ? - CustomData_get_named_layer_index(cd_ldata, CD_PROP_BYTE_COLOR, name) : - layer_i; - } - - /* NOTE: this is not the same as the layer_i below. */ - if (layer_i != -1) { - layer = (domain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata)->layers + layer_i; - } - } - else { - layer = BKE_id_attributes_render_color_get(&me_query->id); - } - - if (!layer) { - return -1; - } - - /* NOTE: this is the logical index into the color attribute list, - * not the customdata index. */ - int vcol_i = BKE_id_attribute_to_index( - (ID *)me_query, layer, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - - return vcol_i; -} - static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, const Mesh *me, struct GPUMaterial **gpumat_array, @@ -433,6 +288,9 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, DRW_MeshCDMask cd_used; mesh_cd_layers_type_clear(&cd_used); + const CustomDataLayer *default_color = BKE_id_attributes_render_color_get(&me_query.id); + const StringRefNull default_color_name = default_color ? default_color->name : ""; + for (int i = 0; i < gpumat_array_len; i++) { GPUMaterial *gpumat = gpumat_array[i]; if (gpumat) { @@ -443,6 +301,10 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, int layer = -1; std::optional<eAttrDomain> domain; + if (gpu_attr->is_default_color) { + name = default_color_name.c_str(); + } + if (type == CD_AUTO_FROM_NAME) { /* We need to deduce what exact layer is used. * @@ -452,38 +314,6 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, layer = CustomData_get_named_layer(cd_ldata, CD_MLOOPUV, name); type = CD_MTFACE; - if (layer == -1) { - layer = CustomData_get_named_layer(cd_vdata, CD_PROP_COLOR, name); - if (layer != -1) { - type = CD_PROP_COLOR; - domain = ATTR_DOMAIN_POINT; - } - } - - if (layer == -1) { - layer = CustomData_get_named_layer(cd_ldata, CD_PROP_COLOR, name); - if (layer != -1) { - type = CD_PROP_COLOR; - domain = ATTR_DOMAIN_CORNER; - } - } - - if (layer == -1) { - layer = CustomData_get_named_layer(cd_vdata, CD_PROP_BYTE_COLOR, name); - if (layer != -1) { - type = CD_PROP_BYTE_COLOR; - domain = ATTR_DOMAIN_POINT; - } - } - - if (layer == -1) { - layer = CustomData_get_named_layer(cd_ldata, CD_PROP_BYTE_COLOR, name); - if (layer != -1) { - type = CD_PROP_BYTE_COLOR; - domain = ATTR_DOMAIN_CORNER; - } - } - #if 0 /* Tangents are always from UV's - this will never happen. */ if (layer == -1) { layer = CustomData_get_named_layer(cd_ldata, CD_TANGENT, name); @@ -556,28 +386,8 @@ static DRW_MeshCDMask mesh_cd_calc_used_gpu_layers(const Object *object, cd_used.orco = 1; break; } - - /* NOTE: attr->type will always be CD_PROP_COLOR even for - * CD_PROP_BYTE_COLOR layers, see node_shader_gpu_vertex_color in - * node_shader_vertex_color.cc. - */ - case CD_MCOL: case CD_PROP_BYTE_COLOR: - case CD_PROP_COLOR: { - /* First check Color attributes, when not found check mesh attributes. Geometry nodes - * can generate those layers. */ - int vcol_bit = mesh_cd_calc_gpu_layers_vcol_used(&me_query, cd_vdata, cd_ldata, name); - - if (vcol_bit != -1) { - cd_used.vcol |= 1UL << (uint)vcol_bit; - break; - } - - if (layer != -1 && domain.has_value()) { - drw_attributes_add_request(attributes, name, type, layer, *domain); - } - break; - } + case CD_PROP_COLOR: case CD_PROP_FLOAT3: case CD_PROP_BOOL: case CD_PROP_INT8: @@ -863,10 +673,9 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) FOREACH_MESH_BUFFER_CACHE (cache, mbc) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.uv); GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.tan); - GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.vcol); GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.orco); } - DRWBatchFlag batch_map = BATCH_MAP(vbo.uv, vbo.tan, vbo.vcol, vbo.orco); + DRWBatchFlag batch_map = BATCH_MAP(vbo.uv, vbo.tan, vbo.orco); mesh_batch_cache_discard_batch(cache, batch_map); mesh_cd_layers_type_clear(&cache->cd_used); } @@ -1070,42 +879,35 @@ static void texpaint_request_active_uv(MeshBatchCache *cache, Object *object, Me mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); } -static void texpaint_request_active_vcol(MeshBatchCache *cache, Object *object, Mesh *me) -{ - DRW_MeshCDMask cd_needed; - mesh_cd_layers_type_clear(&cd_needed); - mesh_cd_calc_active_mloopcol_layer(object, me, &cd_needed); - - BLI_assert(cd_needed.vcol != 0 && - "No MLOOPCOL layer available in vertpaint, but batches requested anyway!"); - - mesh_cd_layers_type_merge(&cache->cd_needed, cd_needed); -} - -static void sculpt_request_active_vcol(MeshBatchCache *cache, Object *object, Mesh *me) +static void request_active_and_default_color_attributes(const Object &object, + const Mesh &mesh, + DRW_Attributes &attributes) { - const Mesh *me_final = editmesh_final_or_this(object, me); + const Mesh *me_final = editmesh_final_or_this(&object, &mesh); const CustomData *cd_vdata = mesh_cd_vdata_get_from_mesh(me_final); const CustomData *cd_ldata = mesh_cd_ldata_get_from_mesh(me_final); + /* Necessary because which attributes are active/default is stored in #CustomData. */ Mesh me_query = blender::dna::shallow_zero_initialize(); BKE_id_attribute_copy_domains_temp( ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - const CustomDataLayer *active = BKE_id_attributes_active_color_get(&me_query.id); - const CustomDataLayer *render = BKE_id_attributes_render_color_get(&me_query.id); - - int active_i = BKE_id_attribute_to_index( - &me_query.id, active, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); - int render_i = BKE_id_attribute_to_index( - &me_query.id, render, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL); + auto request_color_attribute = [&](const char *name) { + int layer_index; + eCustomDataType type; + if (drw_custom_data_match_attribute(cd_vdata, name, &layer_index, &type)) { + drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_POINT); + } + else if (drw_custom_data_match_attribute(cd_ldata, name, &layer_index, &type)) { + drw_attributes_add_request(&attributes, name, type, layer_index, ATTR_DOMAIN_CORNER); + } + }; - if (active_i >= 0) { - cache->cd_needed.vcol |= 1UL << (uint)active_i; + if (const CustomDataLayer *active = BKE_id_attributes_active_color_get(&me_query.id)) { + request_color_attribute(active->name); } - - if (render_i >= 0) { - cache->cd_needed.vcol |= 1UL << (uint)render_i; + if (const CustomDataLayer *render = BKE_id_attributes_render_color_get(&me_query.id)) { + request_color_attribute(render->name); } } @@ -1214,7 +1016,13 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_texpaint_single(Object *object, Mesh GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - texpaint_request_active_vcol(cache, object, me); + + DRW_Attributes attrs_needed{}; + request_active_and_default_color_attributes(*object, *me, attrs_needed); + + ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex; + drw_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex); + mesh_batch_cache_request_surface_batches(cache); return cache->batch.surface; } @@ -1222,7 +1030,13 @@ GPUBatch *DRW_mesh_batch_cache_get_surface_vertpaint(Object *object, Mesh *me) GPUBatch *DRW_mesh_batch_cache_get_surface_sculpt(Object *object, Mesh *me) { MeshBatchCache *cache = mesh_batch_cache_get(me); - sculpt_request_active_vcol(cache, object, me); + + DRW_Attributes attrs_needed{}; + request_active_and_default_color_attributes(*object, *me, attrs_needed); + + ThreadMutex *mesh_render_mutex = (ThreadMutex *)me->runtime.render_mutex; + drw_attributes_merge(&cache->attr_needed, &attrs_needed, mesh_render_mutex); + mesh_batch_cache_request_surface_batches(cache); return cache->batch.surface; } @@ -1621,9 +1435,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.sculpt_overlays != cache->cd_needed.sculpt_overlays) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.sculpt_data); } - if ((cache->cd_used.vcol & cache->cd_needed.vcol) != cache->cd_needed.vcol) { - GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.vcol); - } if (!drw_attributes_overlap(&cache->attr_used, &cache->attr_needed)) { for (int i = 0; i < GPU_MAX_ATTR; i++) { GPU_VERTBUF_DISCARD_SAFE(mbc->buff.vbo.attr[i]); @@ -1710,15 +1521,26 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, MeshBufferList *mbuflist = &cache->final.buff; /* Initialize batches and request VBO's & IBO's. */ - assert_deps_valid( - MBC_SURFACE, - {BUFFER_INDEX(ibo.tris), BUFFER_INDEX(vbo.lnor), BUFFER_INDEX(vbo.pos_nor), - BUFFER_INDEX(vbo.uv), BUFFER_INDEX(vbo.vcol), BUFFER_INDEX(vbo.attr[0]), - BUFFER_INDEX(vbo.attr[1]), BUFFER_INDEX(vbo.attr[2]), BUFFER_INDEX(vbo.attr[3]), - BUFFER_INDEX(vbo.attr[4]), BUFFER_INDEX(vbo.attr[5]), BUFFER_INDEX(vbo.attr[6]), - BUFFER_INDEX(vbo.attr[7]), BUFFER_INDEX(vbo.attr[8]), BUFFER_INDEX(vbo.attr[9]), - BUFFER_INDEX(vbo.attr[10]), BUFFER_INDEX(vbo.attr[11]), BUFFER_INDEX(vbo.attr[12]), - BUFFER_INDEX(vbo.attr[13]), BUFFER_INDEX(vbo.attr[14])}); + assert_deps_valid(MBC_SURFACE, + {BUFFER_INDEX(ibo.tris), + BUFFER_INDEX(vbo.lnor), + BUFFER_INDEX(vbo.pos_nor), + BUFFER_INDEX(vbo.uv), + BUFFER_INDEX(vbo.attr[0]), + BUFFER_INDEX(vbo.attr[1]), + BUFFER_INDEX(vbo.attr[2]), + BUFFER_INDEX(vbo.attr[3]), + BUFFER_INDEX(vbo.attr[4]), + BUFFER_INDEX(vbo.attr[5]), + BUFFER_INDEX(vbo.attr[6]), + BUFFER_INDEX(vbo.attr[7]), + BUFFER_INDEX(vbo.attr[8]), + BUFFER_INDEX(vbo.attr[9]), + BUFFER_INDEX(vbo.attr[10]), + BUFFER_INDEX(vbo.attr[11]), + BUFFER_INDEX(vbo.attr[12]), + BUFFER_INDEX(vbo.attr[13]), + BUFFER_INDEX(vbo.attr[14])}); if (DRW_batch_requested(cache->batch.surface, GPU_PRIM_TRIS)) { DRW_ibo_request(cache->batch.surface, &mbuflist->ibo.tris); /* Order matters. First ones override latest VBO's attributes. */ @@ -1727,9 +1549,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if (cache->cd_used.uv != 0) { DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.uv); } - if (cache->cd_used.vcol != 0) { - DRW_vbo_request(cache->batch.surface, &mbuflist->vbo.vcol); - } drw_add_attributes_vbo(cache->batch.surface, mbuflist, &cache->attr_used); } assert_deps_valid(MBC_ALL_VERTS, {BUFFER_INDEX(vbo.pos_nor)}); @@ -1807,12 +1626,12 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, assert_deps_valid( MBC_SURFACE_PER_MAT, {BUFFER_INDEX(vbo.lnor), BUFFER_INDEX(vbo.pos_nor), BUFFER_INDEX(vbo.uv), - BUFFER_INDEX(vbo.tan), BUFFER_INDEX(vbo.vcol), BUFFER_INDEX(vbo.orco), - BUFFER_INDEX(vbo.attr[0]), BUFFER_INDEX(vbo.attr[1]), BUFFER_INDEX(vbo.attr[2]), - BUFFER_INDEX(vbo.attr[3]), BUFFER_INDEX(vbo.attr[4]), BUFFER_INDEX(vbo.attr[5]), - BUFFER_INDEX(vbo.attr[6]), BUFFER_INDEX(vbo.attr[7]), BUFFER_INDEX(vbo.attr[8]), - BUFFER_INDEX(vbo.attr[9]), BUFFER_INDEX(vbo.attr[10]), BUFFER_INDEX(vbo.attr[11]), - BUFFER_INDEX(vbo.attr[12]), BUFFER_INDEX(vbo.attr[13]), BUFFER_INDEX(vbo.attr[14])}); + BUFFER_INDEX(vbo.tan), BUFFER_INDEX(vbo.orco), BUFFER_INDEX(vbo.attr[0]), + BUFFER_INDEX(vbo.attr[1]), BUFFER_INDEX(vbo.attr[2]), BUFFER_INDEX(vbo.attr[3]), + BUFFER_INDEX(vbo.attr[4]), BUFFER_INDEX(vbo.attr[5]), BUFFER_INDEX(vbo.attr[6]), + BUFFER_INDEX(vbo.attr[7]), BUFFER_INDEX(vbo.attr[8]), BUFFER_INDEX(vbo.attr[9]), + BUFFER_INDEX(vbo.attr[10]), BUFFER_INDEX(vbo.attr[11]), BUFFER_INDEX(vbo.attr[12]), + BUFFER_INDEX(vbo.attr[13]), BUFFER_INDEX(vbo.attr[14])}); assert_deps_valid(MBC_SURFACE_PER_MAT, {TRIS_PER_MAT_INDEX}); for (int i = 0; i < cache->mat_len; i++) { if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) { @@ -1826,9 +1645,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, if ((cache->cd_used.tan != 0) || (cache->cd_used.tan_orco != 0)) { DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.tan); } - if (cache->cd_used.vcol != 0) { - DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.vcol); - } if (cache->cd_used.orco != 0) { DRW_vbo_request(cache->surface_per_mat[i], &mbuflist->vbo.orco); } @@ -1994,7 +1810,6 @@ void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, assert_final_deps_valid(BUFFER_INDEX(vbo.lnor)); assert_final_deps_valid(BUFFER_INDEX(vbo.pos_nor)); assert_final_deps_valid(BUFFER_INDEX(vbo.uv)); - assert_final_deps_valid(BUFFER_INDEX(vbo.vcol)); assert_final_deps_valid(BUFFER_INDEX(vbo.sculpt_data)); assert_final_deps_valid(BUFFER_INDEX(vbo.weights)); assert_final_deps_valid(BUFFER_INDEX(vbo.edge_fac)); diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh index 8052b277d45..a4773736f0c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh.hh +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh.hh @@ -86,6 +86,9 @@ struct MeshRenderData { float (*loop_normals)[3]; int *lverts, *ledges; + const char *active_color_name; + const char *default_color_name; + struct { int *tri_first_index; int *mat_tri_len; @@ -93,6 +96,82 @@ struct MeshRenderData { } poly_sorted; }; +BLI_INLINE const Mesh *editmesh_final_or_this(const Object *object, const Mesh *me) +{ + if (me->edit_mesh != nullptr) { + Mesh *editmesh_eval_final = BKE_object_get_editmesh_eval_final(object); + if (editmesh_eval_final != nullptr) { + return editmesh_eval_final; + } + } + + return me; +} + +BLI_INLINE const CustomData *mesh_cd_ldata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + case ME_WRAPPER_TYPE_MDATA: + return &me->ldata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->ldata; + break; + } + + BLI_assert(0); + return &me->ldata; +} + +BLI_INLINE const CustomData *mesh_cd_pdata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + case ME_WRAPPER_TYPE_MDATA: + return &me->pdata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->pdata; + break; + } + + BLI_assert(0); + return &me->pdata; +} + +BLI_INLINE const CustomData *mesh_cd_edata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + case ME_WRAPPER_TYPE_MDATA: + return &me->edata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->edata; + break; + } + + BLI_assert(0); + return &me->edata; +} + +BLI_INLINE const CustomData *mesh_cd_vdata_get_from_mesh(const Mesh *me) +{ + switch ((eMeshWrapperType)me->runtime.wrapper_type) { + case ME_WRAPPER_TYPE_SUBD: + case ME_WRAPPER_TYPE_MDATA: + return &me->vdata; + break; + case ME_WRAPPER_TYPE_BMESH: + return &me->edit_mesh->bm->vdata; + break; + } + + BLI_assert(0); + return &me->vdata; +} + BLI_INLINE BMFace *bm_original_face_get(const MeshRenderData *mr, int idx) { return ((mr->p_origindex != NULL) && (mr->p_origindex[idx] != ORIGINDEX_NONE) && mr->bm) ? diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc index b98af3be17f..7f16837022c 100644 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc +++ b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_attributes.cc @@ -9,6 +9,7 @@ #include <functional> +#include "BLI_color.hh" #include "BLI_math_vec_types.hh" #include "BLI_string.h" @@ -74,6 +75,18 @@ template<> struct AttributeTypeConverter<MPropCol, gpuMeshCol> { } }; +template<> struct AttributeTypeConverter<ColorGeometry4b, gpuMeshCol> { + static gpuMeshCol convert_value(ColorGeometry4b value) + { + gpuMeshCol result; + result.r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.r]); + result.g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.g]); + result.b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[value.b]); + result.a = unit_float_to_ushort_clamp(value.a * (1.0f / 255.0f)); + return result; + } +}; + /* Return the number of component for the attribute's value type, or 0 if is it unsupported. */ static uint gpu_component_size_for_attribute_type(eCustomDataType type) { @@ -90,6 +103,7 @@ static uint gpu_component_size_for_attribute_type(eCustomDataType type) case CD_PROP_FLOAT3: return 3; case CD_PROP_COLOR: + case CD_PROP_BYTE_COLOR: return 4; default: return 0; @@ -102,6 +116,7 @@ static GPUVertFetchMode get_fetch_mode_for_type(eCustomDataType type) case CD_PROP_INT32: return GPU_FETCH_INT_TO_FLOAT; case CD_PROP_COLOR: + case CD_PROP_BYTE_COLOR: return GPU_FETCH_INT_TO_FLOAT_UNIT; default: return GPU_FETCH_FLOAT; @@ -114,13 +129,15 @@ static GPUVertCompType get_comp_type_for_type(eCustomDataType type) case CD_PROP_INT32: return GPU_COMP_I32; case CD_PROP_COLOR: + case CD_PROP_BYTE_COLOR: return GPU_COMP_U16; default: return GPU_COMP_F32; } } -static void init_vbo_for_attribute(GPUVertBuf *vbo, +static void init_vbo_for_attribute(const MeshRenderData &mr, + GPUVertBuf *vbo, const DRW_AttributeRequest &request, bool build_on_device, uint32_t len) @@ -140,6 +157,13 @@ static void init_vbo_for_attribute(GPUVertBuf *vbo, GPU_vertformat_deinterleave(&format); GPU_vertformat_attr_add(&format, attr_name, comp_type, comp_size, fetch_mode); + if (mr.active_color_name && STREQ(request.attribute_name, mr.active_color_name)) { + GPU_vertformat_alias_add(&format, "ac"); + } + if (mr.default_color_name && STREQ(request.attribute_name, mr.default_color_name)) { + GPU_vertformat_alias_add(&format, "c"); + } + if (build_on_device) { GPU_vertbuf_init_build_on_device(vbo, &format, len); } @@ -262,7 +286,7 @@ static void extract_attr_init( GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); - init_vbo_for_attribute(vbo, request, false, static_cast<uint32_t>(mr->loop_len)); + init_vbo_for_attribute(*mr, vbo, request, false, static_cast<uint32_t>(mr->loop_len)); /* TODO(@kevindietrich): float3 is used for scalar attributes as the implicit conversion done by * OpenGL to vec4 for a scalar `s` will produce a `vec4(s, 0, 0, 1)`. However, following the @@ -290,6 +314,9 @@ static void extract_attr_init( case CD_PROP_COLOR: extract_attr_generic<MPropCol, gpuMeshCol>(mr, vbo, request); break; + case CD_PROP_BYTE_COLOR: + extract_attr_generic<ColorGeometry4b, gpuMeshCol>(mr, vbo, request); + break; default: BLI_assert_unreachable(); } @@ -338,12 +365,15 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache, case CD_PROP_COLOR: extract_attr_generic<MPropCol, gpuMeshCol>(mr, src_data, request); break; + case CD_PROP_BYTE_COLOR: + extract_attr_generic<ColorGeometry4b, gpuMeshCol>(mr, src_data, request); + break; default: BLI_assert_unreachable(); } GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer); - init_vbo_for_attribute(dst_buffer, request, true, subdiv_cache->num_subdiv_loops); + init_vbo_for_attribute(*mr, dst_buffer, request, true, subdiv_cache->num_subdiv_loops); /* Ensure data is uploaded properly. */ GPU_vertbuf_tag_dirty(src_data); @@ -352,7 +382,7 @@ static void extract_attr_init_subdiv(const DRWSubdivCache *subdiv_cache, dst_buffer, static_cast<int>(dimensions), 0, - request.cd_type == CD_PROP_COLOR); + ELEM(request.cd_type, CD_PROP_COLOR, CD_PROP_BYTE_COLOR)); GPU_vertbuf_discard(src_data); } diff --git a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc b/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc deleted file mode 100644 index 419cbb0267f..00000000000 --- a/source/blender/draw/intern/mesh_extractors/extract_mesh_vbo_vcol.cc +++ /dev/null @@ -1,387 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later - * Copyright 2021 Blender Foundation. All rights reserved. */ - -/** \file - * \ingroup draw - */ - -#include "MEM_guardedalloc.h" - -#include "BKE_attribute.h" -#include "BLI_string.h" -#include "BLI_vector.hh" - -#include "draw_subdivision.h" -#include "extract_mesh.hh" - -namespace blender::draw { - -struct VColRef { - const CustomDataLayer *layer; - eAttrDomain domain; -}; - -/** Get all vcol layers as AttributeRefs. - * - * \param vcol_layers: bitmask to filter vcol layers by, each bit - * corresponds to the integer position of the attribute - * within the global color attribute list. - */ -static Vector<VColRef> get_vcol_refs(const CustomData *cd_vdata, - const CustomData *cd_ldata, - const uint vcol_layers) -{ - Vector<VColRef> refs; - uint layeri = 0; - - auto buildList = [&](const CustomData *cdata, eAttrDomain domain) { - for (int i = 0; i < cdata->totlayer; i++) { - const CustomDataLayer *layer = cdata->layers + i; - - if (!(CD_TYPE_AS_MASK(layer->type) & CD_MASK_COLOR_ALL)) { - continue; - } - - if (layer->flag & CD_FLAG_TEMPORARY) { - continue; - } - - if (!(vcol_layers & (1UL << layeri))) { - layeri++; - continue; - } - - VColRef ref = {}; - ref.domain = domain; - ref.layer = layer; - - refs.append(ref); - layeri++; - } - }; - - buildList(cd_vdata, ATTR_DOMAIN_POINT); - buildList(cd_ldata, ATTR_DOMAIN_CORNER); - - return refs; -} - -/* ---------------------------------------------------------------------- */ -/** \name Extract VCol - * \{ */ - -/* Initialize the common vertex format for vcol for coarse and subdivided meshes. */ -static void init_vcol_format(GPUVertFormat *format, - const MeshBatchCache *cache, - const CustomData *cd_vdata, - const CustomData *cd_ldata, - const CustomDataLayer *active, - const CustomDataLayer *render) -{ - GPU_vertformat_deinterleave(format); - - const uint32_t vcol_layers = cache->cd_used.vcol; - - Vector<VColRef> refs = get_vcol_refs(cd_vdata, cd_ldata, vcol_layers); - - for (const VColRef &ref : refs) { - char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME]; - - GPU_vertformat_safe_attr_name(ref.layer->name, attr_safe_name, GPU_MAX_SAFE_ATTR_NAME); - - /* VCol layer name. */ - BLI_snprintf(attr_name, sizeof(attr_name), "a%s", attr_safe_name); - GPU_vertformat_attr_add(format, attr_name, GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - - /* Active layer name. */ - if (ref.layer == active) { - GPU_vertformat_alias_add(format, "ac"); - } - - /* Active render layer name. */ - if (ref.layer == render) { - GPU_vertformat_alias_add(format, "c"); - } - } -} - -/* Vertex format for vertex colors, only used during the coarse data upload for the subdivision - * case. */ -static GPUVertFormat *get_coarse_vcol_format() -{ - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - GPU_vertformat_attr_add(&format, "cCol", GPU_COMP_U16, 4, GPU_FETCH_INT_TO_FLOAT_UNIT); - GPU_vertformat_alias_add(&format, "c"); - GPU_vertformat_alias_add(&format, "ac"); - } - return &format; -} - -struct gpuMeshVcol { - ushort r, g, b, a; -}; - -static void extract_vcol_init(const MeshRenderData *mr, - MeshBatchCache *cache, - void *buf, - void *UNUSED(tls_data)) -{ - GPUVertBuf *vbo = static_cast<GPUVertBuf *>(buf); - GPUVertFormat format = {0}; - - const CustomData *cd_vdata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->vdata : - &mr->me->vdata; - const CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : - &mr->me->ldata; - - Mesh me_query = blender::dna::shallow_zero_initialize(); - - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - - const CustomDataLayer *active_color = BKE_id_attributes_active_color_get(&me_query.id); - const CustomDataLayer *render_color = BKE_id_attributes_render_color_get(&me_query.id); - - const uint32_t vcol_layers = cache->cd_used.vcol; - init_vcol_format(&format, cache, cd_vdata, cd_ldata, active_color, render_color); - - GPU_vertbuf_init_with_format(vbo, &format); - GPU_vertbuf_data_alloc(vbo, mr->loop_len); - - gpuMeshVcol *vcol_data = (gpuMeshVcol *)GPU_vertbuf_get_data(vbo); - - Vector<VColRef> refs = get_vcol_refs(cd_vdata, cd_ldata, vcol_layers); - - for (const VColRef &ref : refs) { - const CustomData *cdata = ref.domain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata; - - if (mr->extract_type == MR_EXTRACT_BMESH) { - int cd_ofs = ref.layer->offset; - - if (cd_ofs == -1) { - vcol_data += ref.domain == ATTR_DOMAIN_POINT ? mr->bm->totvert : mr->bm->totloop; - continue; - } - - BMIter iter; - const bool is_byte = ref.layer->type == CD_PROP_BYTE_COLOR; - const bool is_point = ref.domain == ATTR_DOMAIN_POINT; - - BMFace *f; - BM_ITER_MESH (f, &iter, mr->bm, BM_FACES_OF_MESH) { - const BMLoop *l_iter = f->l_first; - do { - const BMElem *elem = is_point ? reinterpret_cast<const BMElem *>(l_iter->v) : - reinterpret_cast<const BMElem *>(l_iter); - if (is_byte) { - const MLoopCol *mloopcol = (const MLoopCol *)BM_ELEM_CD_GET_VOID_P(elem, cd_ofs); - vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]); - vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]); - vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]); - vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f)); - vcol_data++; - } - else { - const MPropCol *mpcol = (const MPropCol *)BM_ELEM_CD_GET_VOID_P(elem, cd_ofs); - vcol_data->r = unit_float_to_ushort_clamp(mpcol->color[0]); - vcol_data->g = unit_float_to_ushort_clamp(mpcol->color[1]); - vcol_data->b = unit_float_to_ushort_clamp(mpcol->color[2]); - vcol_data->a = unit_float_to_ushort_clamp(mpcol->color[3]); - vcol_data++; - } - } while ((l_iter = l_iter->next) != f->l_first); - } - } - else { - int totloop = mr->loop_len; - const int idx = CustomData_get_named_layer_index(cdata, ref.layer->type, ref.layer->name); - - const MLoopCol *mcol = nullptr; - const MPropCol *pcol = nullptr; - const MLoop *mloop = mr->mloop; - - if (ref.layer->type == CD_PROP_COLOR) { - pcol = static_cast<const MPropCol *>(cdata->layers[idx].data); - } - else { - mcol = static_cast<const MLoopCol *>(cdata->layers[idx].data); - } - - const bool is_corner = ref.domain == ATTR_DOMAIN_CORNER; - - for (int i = 0; i < totloop; i++, mloop++) { - const int v_i = is_corner ? i : mloop->v; - - if (mcol) { - vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[v_i].r]); - vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[v_i].g]); - vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[v_i].b]); - vcol_data->a = unit_float_to_ushort_clamp(mcol[v_i].a * (1.0f / 255.0f)); - vcol_data++; - } - else if (pcol) { - vcol_data->r = unit_float_to_ushort_clamp(pcol[v_i].color[0]); - vcol_data->g = unit_float_to_ushort_clamp(pcol[v_i].color[1]); - vcol_data->b = unit_float_to_ushort_clamp(pcol[v_i].color[2]); - vcol_data->a = unit_float_to_ushort_clamp(pcol[v_i].color[3]); - vcol_data++; - } - } - } - } -} - -static void extract_vcol_init_subdiv(const DRWSubdivCache *subdiv_cache, - const MeshRenderData *mr, - MeshBatchCache *cache, - void *buffer, - void *UNUSED(data)) -{ - GPUVertBuf *dst_buffer = static_cast<GPUVertBuf *>(buffer); - const Mesh *coarse_mesh = subdiv_cache->mesh; - - bool extract_bmesh = mr->extract_type == MR_EXTRACT_BMESH; - - const CustomData *cd_vdata = extract_bmesh ? &coarse_mesh->edit_mesh->bm->vdata : - &coarse_mesh->vdata; - const CustomData *cd_ldata = extract_bmesh ? &coarse_mesh->edit_mesh->bm->ldata : - &coarse_mesh->ldata; - const int totloop = extract_bmesh ? coarse_mesh->edit_mesh->bm->totloop : coarse_mesh->totloop; - - Mesh me_query = blender::dna::shallow_copy(*coarse_mesh); - BKE_id_attribute_copy_domains_temp( - ID_ME, cd_vdata, nullptr, cd_ldata, nullptr, nullptr, &me_query.id); - - const CustomDataLayer *active_color = BKE_id_attributes_active_color_get(&me_query.id); - const CustomDataLayer *render_color = BKE_id_attributes_render_color_get(&me_query.id); - - GPUVertFormat format = {0}; - init_vcol_format( - &format, cache, &coarse_mesh->vdata, &coarse_mesh->ldata, active_color, render_color); - - GPU_vertbuf_init_build_on_device(dst_buffer, &format, subdiv_cache->num_subdiv_loops); - - GPUVertBuf *src_data = GPU_vertbuf_calloc(); - /* Dynamic as we upload and interpolate layers one at a time. */ - GPU_vertbuf_init_with_format_ex(src_data, get_coarse_vcol_format(), GPU_USAGE_DYNAMIC); - - GPU_vertbuf_data_alloc(src_data, totloop); - - gpuMeshVcol *mesh_vcol = (gpuMeshVcol *)GPU_vertbuf_get_data(src_data); - - const uint vcol_layers = cache->cd_used.vcol; - - Vector<VColRef> refs = get_vcol_refs(cd_vdata, cd_ldata, vcol_layers); - - /* Index of the vertex color layer in the compact buffer. Used vertex color layers are stored in - * a single buffer. */ - int pack_layer_index = 0; - for (const VColRef &ref : refs) { - /* Include stride in offset, we use a stride of 2 since colors are packed into 2 uints. */ - const int dst_offset = (int)subdiv_cache->num_subdiv_loops * 2 * pack_layer_index++; - - const CustomData *cdata = ref.domain == ATTR_DOMAIN_POINT ? cd_vdata : cd_ldata; - int layer_i = CustomData_get_named_layer_index(cdata, ref.layer->type, ref.layer->name); - - if (layer_i == -1) { - printf("%s: missing color layer %s\n", __func__, ref.layer->name); - continue; - } - - gpuMeshVcol *vcol = mesh_vcol; - - const bool is_vert = ref.domain == ATTR_DOMAIN_POINT; - - if (extract_bmesh) { - BMesh *bm = coarse_mesh->edit_mesh->bm; - BMIter iter; - BMFace *f; - int cd_ofs = cdata->layers[layer_i].offset; - const bool is_byte = ref.layer->type == CD_PROP_BYTE_COLOR; - - BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { - const BMLoop *l_iter = f->l_first; - - do { - const BMElem *elem = is_vert ? reinterpret_cast<const BMElem *>(l_iter->v) : - reinterpret_cast<const BMElem *>(l_iter); - - if (is_byte) { - const MLoopCol *mcol2 = static_cast<const MLoopCol *>( - BM_ELEM_CD_GET_VOID_P(elem, cd_ofs)); - - vcol->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->r]); - vcol->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->g]); - vcol->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->b]); - vcol->a = unit_float_to_ushort_clamp(mcol2->a * (1.0f / 255.0f)); - } - else { - const MPropCol *pcol2 = static_cast<const MPropCol *>( - BM_ELEM_CD_GET_VOID_P(elem, cd_ofs)); - - vcol->r = unit_float_to_ushort_clamp(pcol2->color[0]); - vcol->g = unit_float_to_ushort_clamp(pcol2->color[1]); - vcol->b = unit_float_to_ushort_clamp(pcol2->color[2]); - vcol->a = unit_float_to_ushort_clamp(pcol2->color[3]); - } - - vcol++; - } while ((l_iter = l_iter->next) != f->l_first); - } - } - else { - const MLoop *ml = coarse_mesh->mloop; - const MLoopCol *mcol = nullptr; - const MPropCol *pcol = nullptr; - - if (ref.layer->type == CD_PROP_COLOR) { - pcol = static_cast<const MPropCol *>(cdata->layers[layer_i].data); - } - else { - mcol = static_cast<const MLoopCol *>(cdata->layers[layer_i].data); - } - - for (int ml_index = 0; ml_index < coarse_mesh->totloop; ml_index++, vcol++, ml++) { - int idx = is_vert ? ml->v : ml_index; - - if (mcol) { - vcol->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[idx].r]); - vcol->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[idx].g]); - vcol->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol[idx].b]); - vcol->a = unit_float_to_ushort_clamp(mcol[idx].a * (1.0f / 255.0f)); - } - else if (pcol) { - vcol->r = unit_float_to_ushort_clamp(pcol[idx].color[0]); - vcol->g = unit_float_to_ushort_clamp(pcol[idx].color[1]); - vcol->b = unit_float_to_ushort_clamp(pcol[idx].color[2]); - vcol->a = unit_float_to_ushort_clamp(pcol[idx].color[3]); - } - } - } - - /* Ensure data is uploaded properly. */ - GPU_vertbuf_tag_dirty(src_data); - draw_subdiv_interp_custom_data(subdiv_cache, src_data, dst_buffer, 4, dst_offset, true); - } - - GPU_vertbuf_discard(src_data); -} - -constexpr MeshExtract create_extractor_vcol() -{ - MeshExtract extractor = {nullptr}; - extractor.init = extract_vcol_init; - extractor.init_subdiv = extract_vcol_init_subdiv; - extractor.data_type = MR_DATA_NONE; - extractor.data_size = 0; - extractor.use_threading = false; - extractor.mesh_buffer_offset = offsetof(MeshBufferList, vbo.vcol); - return extractor; -} - -/** \} */ - -} // namespace blender::draw - -const MeshExtract extract_vcol = blender::draw::create_extractor_vcol(); diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index c0633f0323d..3ca465fa57a 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -131,6 +131,11 @@ typedef void (*GPUCodegenCallbackFn)(void *thunk, GPUMaterial *mat, GPUCodegenOu GPUNodeLink *GPU_constant(const float *num); GPUNodeLink *GPU_uniform(const float *num); GPUNodeLink *GPU_attribute(GPUMaterial *mat, eCustomDataType type, const char *name); +/** + * Add a GPU attribute that refers to the default color attribute on a geometry. + * The name, type, and domain are unknown and do not depend on the material. + */ +GPUNodeLink *GPU_attribute_default_color(GPUMaterial *mat); GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat, eCustomDataType type, const char *name, @@ -266,6 +271,12 @@ typedef struct GPUMaterialAttribute { eGPUDefaultValue default_value; /* Only for volumes attributes. */ int id; int users; + /** + * If true, the corresponding attribute is the specified default color attribute on the mesh, + * if it exists. In that case the type and name data can vary per geometry, so it will not be + * valid here. + */ + bool is_default_color; } GPUMaterialAttribute; typedef struct GPUMaterialTexture { diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c index 1338c5312c2..684070dbdc0 100644 --- a/source/blender/gpu/intern/gpu_node_graph.c +++ b/source/blender/gpu/intern/gpu_node_graph.c @@ -328,13 +328,14 @@ void gpu_node_graph_finalize_uniform_attrs(GPUNodeGraph *graph) /* Attributes and Textures */ -static char attr_prefix_get(eCustomDataType type) +static char attr_prefix_get(GPUMaterialAttribute *attr) { - switch (type) { + if (attr->is_default_color) { + return 'c'; + } + switch (attr->type) { case CD_TANGENT: return 't'; - case CD_MCOL: - return 'c'; case CD_AUTO_FROM_NAME: return 'a'; case CD_HAIRLENGTH: @@ -353,7 +354,7 @@ static void attr_input_name(GPUMaterialAttribute *attr) STRNCPY(attr->input_name, "orco"); } else { - attr->input_name[0] = attr_prefix_get(attr->type); + attr->input_name[0] = attr_prefix_get(attr); attr->input_name[1] = '\0'; if (attr->name[0] != '\0') { /* XXX FIXME: see notes in mesh_render_data_create() */ @@ -365,13 +366,15 @@ static void attr_input_name(GPUMaterialAttribute *attr) /** Add a new varying attribute of given type and name. Returns NULL if out of slots. */ static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph, eCustomDataType type, - const char *name) + const char *name, + const bool is_default_color) { /* Find existing attribute. */ int num_attributes = 0; GPUMaterialAttribute *attr = graph->attributes.first; for (; attr; attr = attr->next) { - if (attr->type == type && STREQ(attr->name, name)) { + if (attr->type == type && STREQ(attr->name, name) && + attr->is_default_color == is_default_color) { break; } num_attributes++; @@ -380,6 +383,7 @@ static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph, /* Add new requested attribute if it's within GPU limits. */ if (attr == NULL) { attr = MEM_callocN(sizeof(*attr), __func__); + attr->is_default_color = is_default_color; attr->type = type; STRNCPY(attr->name, name); attr_input_name(attr); @@ -471,7 +475,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph, GPUNodeLink *GPU_attribute(GPUMaterial *mat, const eCustomDataType type, const char *name) { GPUNodeGraph *graph = gpu_material_node_graph(mat); - GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name); + GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name, false); if (type == CD_ORCO) { /* OPTI: orco might be computed from local positions and needs object infos. */ @@ -490,6 +494,21 @@ GPUNodeLink *GPU_attribute(GPUMaterial *mat, const eCustomDataType type, const c return link; } +GPUNodeLink *GPU_attribute_default_color(GPUMaterial *mat) +{ + GPUNodeGraph *graph = gpu_material_node_graph(mat); + GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, CD_AUTO_FROM_NAME, "", true); + if (attr == NULL) { + static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f}; + return GPU_constant(zero_data); + } + attr->is_default_color = true; + GPUNodeLink *link = gpu_node_link_create(); + link->link_type = GPU_NODE_LINK_ATTR; + link->attr = attr; + return link; +} + GPUNodeLink *GPU_attribute_with_default(GPUMaterial *mat, const eCustomDataType type, const char *name, diff --git a/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc index 830f02d8df1..c636cc976e6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc +++ b/source/blender/nodes/shader/nodes/node_shader_vertex_color.cc @@ -42,9 +42,8 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, GPUNodeStack *out) { NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage; - /* NOTE: using CD_AUTO_FROM_NAME instead of CD_MCOL or CD_PROP_COLOR for named attributes - * as geometry nodes may overwrite data which will also change the eCustomDataType. - * This will also make EEVEE and Cycles + /* NOTE: Using #CD_AUTO_FROM_NAME is necessary because there are multiple color attribute types, + * and the type may change during evaluation anyway. This will also make EEVEE and Cycles * consistent. See T93179. */ GPUNodeLink *vertexColorLink; @@ -53,7 +52,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat, vertexColorLink = GPU_attribute(mat, CD_AUTO_FROM_NAME, vertexColor->layer_name); } else { /* Fall back on active render color attribute. */ - vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name); + vertexColorLink = GPU_attribute_default_color(mat); } return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink); |