diff --git a/source/blender/draw/intern/draw_cache_impl_curves.cc b/source/blender/draw/intern/draw_cache_impl_curves.cc index fd69926beed..89f6d1481a3 100644 --- a/source/blender/draw/intern/draw_cache_impl_curves.cc +++ b/source/blender/draw/intern/draw_cache_impl_curves.cc @@ -681,26 +681,111 @@ static bool ensure_attributes(const Curves &curves, CurvesEvalFinalCache &final_cache = cache.eval_cache.final; if (gpu_material) { + /* The following code should be kept in sync with `mesh_cd_calc_used_gpu_layers`. */ DRW_Attributes attrs_needed; drw_attributes_clear(&attrs_needed); ListBase gpu_attrs = GPU_material_attributes(gpu_material); LISTBASE_FOREACH (const GPUMaterialAttribute *, gpu_attr, &gpu_attrs) { const char *name = gpu_attr->name; + eCustomDataType type = static_cast(gpu_attr->type); + int layer = -1; + std::optional domain; - int layer_index; - eCustomDataType type; - bke::AttrDomain domain; - if (drw_custom_data_match_attribute(cd_curve, name, &layer_index, &type)) { - domain = bke::AttrDomain::Curve; - } - else if (drw_custom_data_match_attribute(cd_point, name, &layer_index, &type)) { - domain = bke::AttrDomain::Point; + if (gpu_attr->type == CD_AUTO_FROM_NAME) { + /* We need to deduce what exact layer is used. + * + * We do it based on the specified name. + */ + if (name[0] != '\0') { + layer = CustomData_get_named_layer(cd_curve, CD_PROP_FLOAT2, name); + type = CD_MTFACE; + domain = bke::AttrDomain::Curve; + + if (layer == -1) { + /* Try to match a generic attribute, we use the first attribute domain with a + * matching name. */ + if (drw_custom_data_match_attribute(cd_point, name, &layer, &type)) { + domain = bke::AttrDomain::Point; + } + else if (drw_custom_data_match_attribute(cd_curve, name, &layer, &type)) { + domain = bke::AttrDomain::Curve; + } + else { + domain.reset(); + layer = -1; + } + } + + if (layer == -1) { + continue; + } + } + else { + /* Fall back to the UV layer, which matches old behavior. */ + type = CD_MTFACE; + } } else { - continue; + if (drw_custom_data_match_attribute(cd_curve, name, &layer, &type)) { + domain = bke::AttrDomain::Curve; + } + else if (drw_custom_data_match_attribute(cd_point, name, &layer, &type)) { + domain = bke::AttrDomain::Point; + } } - drw_attributes_add_request(&attrs_needed, name, type, layer_index, domain); + switch (type) { + case CD_MTFACE: { + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_curve, CD_PROP_FLOAT2, name) : + CustomData_get_render_layer(cd_curve, CD_PROP_FLOAT2); + if (layer != -1) { + domain = bke::AttrDomain::Curve; + } + } + if (layer == -1) { + layer = (name[0] != '\0') ? + CustomData_get_named_layer(cd_point, CD_PROP_FLOAT2, name) : + CustomData_get_render_layer(cd_point, CD_PROP_FLOAT2); + if (layer != -1) { + domain = bke::AttrDomain::Point; + } + } + + if (layer != -1 && name[0] == '\0' && domain.has_value()) { + name = CustomData_get_layer_name( + domain == bke::AttrDomain::Curve ? cd_curve : cd_point, CD_PROP_FLOAT2, layer); + } + + if (layer != -1 && domain.has_value()) { + drw_attributes_add_request(&attrs_needed, name, CD_PROP_FLOAT2, layer, *domain); + } + break; + } + + case CD_TANGENT: + case CD_ORCO: + break; + + case CD_PROP_BYTE_COLOR: + case CD_PROP_COLOR: + case CD_PROP_QUATERNION: + case CD_PROP_FLOAT3: + case CD_PROP_BOOL: + case CD_PROP_INT8: + case CD_PROP_INT32: + case CD_PROP_INT32_2D: + case CD_PROP_FLOAT: + case CD_PROP_FLOAT2: { + if (layer != -1 && domain.has_value()) { + drw_attributes_add_request(&attrs_needed, name, type, layer, *domain); + } + break; + } + default: + break; + } } if (!drw_attributes_overlap(&final_cache.attr_used, &attrs_needed)) { diff --git a/source/blender/draw/intern/draw_curves.cc b/source/blender/draw/intern/draw_curves.cc index f7b870808d0..0b9708a4c0c 100644 --- a/source/blender/draw/intern/draw_curves.cc +++ b/source/blender/draw/intern/draw_curves.cc @@ -15,6 +15,7 @@ #include "BKE_attribute.hh" #include "BKE_curves.hh" +#include "BKE_customdata.hh" #include "GPU_batch.hh" #include "GPU_capabilities.hh" @@ -235,6 +236,7 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_buffer_texture(shgrp, "au", g_dummy_vbo); DRW_shgroup_buffer_texture(shgrp, "c", g_dummy_vbo); DRW_shgroup_buffer_texture(shgrp, "ac", g_dummy_vbo); + DRW_shgroup_buffer_texture(shgrp, "a", g_dummy_vbo); /* TODO: Generalize radius implementation for curves data type. */ float hair_rad_shape = 0.0f; @@ -265,10 +267,20 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, DRW_shgroup_buffer_texture(shgrp, "hairLen", curves_cache->proc_length_buf); } + int curve_data_render_uv = 0; + int point_data_render_uv = 0; + if (CustomData_has_layer(&curves_id.geometry.curve_data, CD_PROP_FLOAT2)) { + curve_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.curve_data, + CD_PROP_FLOAT2); + } + if (CustomData_has_layer(&curves_id.geometry.point_data, CD_PROP_FLOAT2)) { + point_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.point_data, + CD_PROP_FLOAT2); + } + const DRW_Attributes &attrs = curves_cache->final.attr_used; for (int i = 0; i < attrs.num_requests; i++) { const DRW_AttributeRequest &request = attrs.requests[i]; - char sampler_name[32]; drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); @@ -276,14 +288,19 @@ DRWShadingGroup *DRW_shgroup_curves_create_sub(Object *object, if (!curves_cache->proc_attributes_buf[i]) { continue; } - DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->proc_attributes_buf[i]); + if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == curve_data_render_uv) { + DRW_shgroup_buffer_texture(shgrp, "a", curves_cache->proc_attributes_buf[i]); + } } else { if (!curves_cache->final.attributes_buf[i]) { continue; } DRW_shgroup_buffer_texture(shgrp, sampler_name, curves_cache->final.attributes_buf[i]); + if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == point_data_render_uv) { + DRW_shgroup_buffer_texture(shgrp, "a", curves_cache->final.attributes_buf[i]); + } } /* Some attributes may not be used in the shader anymore and were not garbage collected yet, so @@ -462,6 +479,7 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps, sub_ps.bind_texture("au", g_dummy_vbo); sub_ps.bind_texture("c", g_dummy_vbo); sub_ps.bind_texture("ac", g_dummy_vbo); + sub_ps.bind_texture("a", g_dummy_vbo); /* TODO: Generalize radius implementation for curves data type. */ float hair_rad_shape = 0.0f; @@ -492,10 +510,20 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps, sub_ps.bind_texture("hairLen", curves_cache->proc_length_buf); } + int curve_data_render_uv = 0; + int point_data_render_uv = 0; + if (CustomData_has_layer(&curves_id.geometry.curve_data, CD_PROP_FLOAT2)) { + curve_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.curve_data, + CD_PROP_FLOAT2); + } + if (CustomData_has_layer(&curves_id.geometry.point_data, CD_PROP_FLOAT2)) { + point_data_render_uv = CustomData_get_render_layer(&curves_id.geometry.point_data, + CD_PROP_FLOAT2); + } + const DRW_Attributes &attrs = curves_cache->final.attr_used; for (int i = 0; i < attrs.num_requests; i++) { const DRW_AttributeRequest &request = attrs.requests[i]; - char sampler_name[32]; drw_curves_get_attribute_sampler_name(request.attribute_name, sampler_name); @@ -504,12 +532,18 @@ gpu::Batch *curves_sub_pass_setup_implementation(PassT &sub_ps, continue; } sub_ps.bind_texture(sampler_name, curves_cache->proc_attributes_buf[i]); + if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == curve_data_render_uv) { + sub_ps.bind_texture("a", curves_cache->proc_attributes_buf[i]); + } } else { if (!curves_cache->final.attributes_buf[i]) { continue; } sub_ps.bind_texture(sampler_name, curves_cache->final.attributes_buf[i]); + if (request.cd_type == CD_PROP_FLOAT2 && request.layer_index == point_data_render_uv) { + sub_ps.bind_texture("a", curves_cache->final.attributes_buf[i]); + } } /* Some attributes may not be used in the shader anymore and were not garbage collected yet, so