Fix #115460: EEVEE-Next: Missing bind when drawing curves #121064

Merged
Jeroen Bakker merged 8 commits from Jeroen-Bakker/blender:eevee/fix/missing-curve-texture-bind into main 2024-05-17 11:16:05 +02:00
2 changed files with 132 additions and 13 deletions

View File

@ -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<eCustomDataType>(gpu_attr->type);
int layer = -1;
std::optional<bke::AttrDomain> 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)) {

View File

@ -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