From 3a4f2131c2d2bc30aec6e74bdfe985c1ec498768 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 27 May 2022 15:45:29 +0200 Subject: Fix Cycles not rendering byte precision vertex domain colors Code was not yet updated to use generic attributes for vertex colors. This also makes generic attributes work for adaptive subdivision. --- intern/cycles/blender/mesh.cpp | 234 ++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 134 deletions(-) (limited to 'intern') diff --git a/intern/cycles/blender/mesh.cpp b/intern/cycles/blender/mesh.cpp index de67e27923d..635421d3d61 100644 --- a/intern/cycles/blender/mesh.cpp +++ b/intern/cycles/blender/mesh.cpp @@ -267,75 +267,62 @@ static void mikk_compute_tangents( genTangSpaceDefault(&context); } -/* Create sculpt vertex color attributes. */ -static void attr_create_sculpt_vertex_color(Scene *scene, - Mesh *mesh, - BL::Mesh &b_mesh, - bool subdivision) -{ - for (BL::MeshVertColorLayer &l : b_mesh.sculpt_vertex_colors) { - const bool active_render = l.active_render(); - AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE; - ustring vcol_name = ustring(l.name().c_str()); - - const bool need_vcol = mesh->need_attribute(scene, vcol_name) || - mesh->need_attribute(scene, vcol_std); - - if (!need_vcol) { - continue; - } - - AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes; - Attribute *vcol_attr = attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_VERTEX); - vcol_attr->std = vcol_std; - - float4 *cdata = vcol_attr->data_float4(); - int numverts = b_mesh.vertices.length(); - - for (int i = 0; i < numverts; i++) { - *(cdata++) = get_float4(l.data[i].color()); - } - } -} - template static void fill_generic_attribute(BL::Mesh &b_mesh, TypeInCycles *data, const BL::Attribute::domain_enum b_domain, + const bool subdivision, const GetValueAtIndex &get_value_at_index) { switch (b_domain) { case BL::Attribute::domain_CORNER: { - for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { - const int index = t.index() * 3; - BL::Array loops = t.loops(); - data[index] = get_value_at_index(loops[0]); - data[index + 1] = get_value_at_index(loops[1]); - data[index + 2] = get_value_at_index(loops[2]); + if (subdivision) { + for (BL::MeshPolygon &p : b_mesh.polygons) { + int n = p.loop_total(); + for (int i = 0; i < n; i++) { + *data = get_value_at_index(p.loop_start() + i); + data++; + } + } + } + else { + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + const int index = t.index() * 3; + BL::Array loops = t.loops(); + data[index] = get_value_at_index(loops[0]); + data[index + 1] = get_value_at_index(loops[1]); + data[index + 2] = get_value_at_index(loops[2]); + } } break; } case BL::Attribute::domain_EDGE: { - /* Averge edge attributes at vertices. */ - const size_t num_verts = b_mesh.vertices.length(); - vector count(num_verts, 0); - - for (BL::MeshEdge &e : b_mesh.edges) { - BL::Array vertices = e.vertices(); - TypeInCycles value = get_value_at_index(e.index()); - - data[vertices[0]] += value; - data[vertices[1]] += value; - count[vertices[0]]++; - count[vertices[1]]++; + if constexpr (std::is_same_v) { + /* uchar4 edge attributes do not exist, and averaging in place + * would not work. */ + assert(0); } + else { + /* Averge edge attributes at vertices. */ + const size_t num_verts = b_mesh.vertices.length(); + vector count(num_verts, 0); + + for (BL::MeshEdge &e : b_mesh.edges) { + BL::Array vertices = e.vertices(); + TypeInCycles value = get_value_at_index(e.index()); + + data[vertices[0]] += value; + data[vertices[1]] += value; + count[vertices[0]]++; + count[vertices[1]]++; + } - for (size_t i = 0; i < num_verts; i++) { - if (count[i] > 1) { - data[i] /= (float)count[i]; + for (size_t i = 0; i < num_verts; i++) { + if (count[i] > 1) { + data[i] /= (float)count[i]; + } } } - break; } case BL::Attribute::domain_POINT: { @@ -346,8 +333,16 @@ static void fill_generic_attribute(BL::Mesh &b_mesh, break; } case BL::Attribute::domain_FACE: { - for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { - data[t.index()] = get_value_at_index(t.polygon_index()); + if (subdivision) { + const int num_polygons = b_mesh.polygons.length(); + for (int i = 0; i < num_polygons; i++) { + data[i] = get_value_at_index(i); + } + } + else { + for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { + data[t.index()] = get_value_at_index(t.polygon_index()); + } } break; } @@ -395,21 +390,22 @@ static void attr_create_generic(Scene *scene, const bool need_motion, const float motion_scale) { - if (subdivision) { - /* TODO: Handle subdivision correctly. */ - return; - } - AttributeSet &attributes = mesh->attributes; + AttributeSet &attributes = (subdivision) ? mesh->subd_attributes : mesh->attributes; static const ustring u_velocity("velocity"); + int attribute_index = 0; + int render_color_index = b_mesh.attributes.render_color_index(); + for (BL::Attribute &b_attribute : b_mesh.attributes) { const ustring name{b_attribute.name().c_str()}; + const bool is_render_color = (attribute_index++ == render_color_index); if (need_motion && name == u_velocity) { attr_create_motion(mesh, b_attribute, motion_scale); } - if (!mesh->need_attribute(scene, name)) { + if (!(mesh->need_attribute(scene, name) || + (is_render_color && mesh->need_attribute(scene, ATTR_STD_VERTEX_COLOR)))) { continue; } if (attributes.find(name)) { @@ -445,15 +441,16 @@ static void attr_create_generic(Scene *scene, BL::FloatAttribute b_float_attribute{b_attribute}; Attribute *attr = attributes.add(name, TypeFloat, element); float *data = attr->data_float(); - fill_generic_attribute( - b_mesh, data, b_domain, [&](int i) { return b_float_attribute.data[i].value(); }); + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { + return b_float_attribute.data[i].value(); + }); break; } case BL::Attribute::data_type_BOOLEAN: { BL::BoolAttribute b_bool_attribute{b_attribute}; Attribute *attr = attributes.add(name, TypeFloat, element); float *data = attr->data_float(); - fill_generic_attribute(b_mesh, data, b_domain, [&](int i) { + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { return (float)b_bool_attribute.data[i].value(); }); break; @@ -462,25 +459,59 @@ static void attr_create_generic(Scene *scene, BL::IntAttribute b_int_attribute{b_attribute}; Attribute *attr = attributes.add(name, TypeFloat, element); float *data = attr->data_float(); - fill_generic_attribute( - b_mesh, data, b_domain, [&](int i) { return (float)b_int_attribute.data[i].value(); }); + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { + return (float)b_int_attribute.data[i].value(); + }); break; } case BL::Attribute::data_type_FLOAT_VECTOR: { BL::FloatVectorAttribute b_vector_attribute{b_attribute}; Attribute *attr = attributes.add(name, TypeVector, element); float3 *data = attr->data_float3(); - fill_generic_attribute(b_mesh, data, b_domain, [&](int i) { + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { BL::Array v = b_vector_attribute.data[i].vector(); return make_float3(v[0], v[1], v[2]); }); break; } + case BL::Attribute::data_type_BYTE_COLOR: { + BL::ByteColorAttribute b_color_attribute{b_attribute}; + + if (element == ATTR_ELEMENT_CORNER) { + element = ATTR_ELEMENT_CORNER_BYTE; + } + Attribute *attr = attributes.add(name, TypeRGBA, element); + if (is_render_color) { + attr->std = ATTR_STD_VERTEX_COLOR; + } + + if (element == ATTR_ELEMENT_CORNER_BYTE) { + uchar4 *data = attr->data_uchar4(); + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { + /* Compress/encode vertex color using the sRGB curve. */ + const float4 c = get_float4(b_color_attribute.data[i].color()); + return color_float4_to_uchar4(color_linear_to_srgb_v4(c)); + }); + } + else { + float4 *data = attr->data_float4(); + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { + BL::Array v = b_color_attribute.data[i].color(); + return make_float4(v[0], v[1], v[2], v[3]); + }); + } + break; + } case BL::Attribute::data_type_FLOAT_COLOR: { BL::FloatColorAttribute b_color_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeRGBA, element); + if (is_render_color) { + attr->std = ATTR_STD_VERTEX_COLOR; + } + float4 *data = attr->data_float4(); - fill_generic_attribute(b_mesh, data, b_domain, [&](int i) { + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { BL::Array v = b_color_attribute.data[i].color(); return make_float4(v[0], v[1], v[2], v[3]); }); @@ -490,7 +521,7 @@ static void attr_create_generic(Scene *scene, BL::Float2Attribute b_float2_attribute{b_attribute}; Attribute *attr = attributes.add(name, TypeFloat2, element); float2 *data = attr->data_float2(); - fill_generic_attribute(b_mesh, data, b_domain, [&](int i) { + fill_generic_attribute(b_mesh, data, b_domain, subdivision, [&](int i) { BL::Array v = b_float2_attribute.data[i].vector(); return make_float2(v[0], v[1]); }); @@ -503,69 +534,6 @@ static void attr_create_generic(Scene *scene, } } -/* Create vertex color attributes. */ -static void attr_create_vertex_color(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh, bool subdivision) -{ - for (BL::MeshLoopColorLayer &l : b_mesh.vertex_colors) { - const bool active_render = l.active_render(); - AttributeStandard vcol_std = (active_render) ? ATTR_STD_VERTEX_COLOR : ATTR_STD_NONE; - ustring vcol_name = ustring(l.name().c_str()); - - const bool need_vcol = mesh->need_attribute(scene, vcol_name) || - mesh->need_attribute(scene, vcol_std); - - if (!need_vcol) { - continue; - } - - Attribute *vcol_attr = NULL; - - if (subdivision) { - if (active_render) { - vcol_attr = mesh->subd_attributes.add(vcol_std, vcol_name); - } - else { - vcol_attr = mesh->subd_attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); - } - - uchar4 *cdata = vcol_attr->data_uchar4(); - - for (BL::MeshPolygon &p : b_mesh.polygons) { - int n = p.loop_total(); - for (int i = 0; i < n; i++) { - float4 color = get_float4(l.data[p.loop_start() + i].color()); - /* Compress/encode vertex color using the sRGB curve. */ - *(cdata++) = color_float4_to_uchar4(color); - } - } - } - else { - if (active_render) { - vcol_attr = mesh->attributes.add(vcol_std, vcol_name); - } - else { - vcol_attr = mesh->attributes.add(vcol_name, TypeRGBA, ATTR_ELEMENT_CORNER_BYTE); - } - - uchar4 *cdata = vcol_attr->data_uchar4(); - - for (BL::MeshLoopTriangle &t : b_mesh.loop_triangles) { - int3 li = get_int3(t.loops()); - float4 c1 = get_float4(l.data[li[0]].color()); - float4 c2 = get_float4(l.data[li[1]].color()); - float4 c3 = get_float4(l.data[li[2]].color()); - - /* Compress/encode vertex color using the sRGB curve. */ - cdata[0] = color_float4_to_uchar4(c1); - cdata[1] = color_float4_to_uchar4(c2); - cdata[2] = color_float4_to_uchar4(c3); - - cdata += 3; - } - } - } -} - /* Create uv map attributes. */ static void attr_create_uv_map(Scene *scene, Mesh *mesh, BL::Mesh &b_mesh) { @@ -1029,8 +997,6 @@ static void create_mesh(Scene *scene, * The calculate functions will check whether they're needed or not. */ attr_create_pointiness(scene, mesh, b_mesh, subdivision); - attr_create_vertex_color(scene, mesh, b_mesh, subdivision); - attr_create_sculpt_vertex_color(scene, mesh, b_mesh, subdivision); attr_create_random_per_island(scene, mesh, b_mesh, subdivision); attr_create_generic(scene, mesh, b_mesh, subdivision, need_motion, motion_scale); -- cgit v1.2.3