Fix #142022: Cycles undisplaced normal not available
Previously with adaptive subdivision this happened to work with the N attribute, but that was not meant to be undisplaced. This adds a new undisplaced_N attribute specifically for this purpose. For backwards compatibility in Blender 4.5, this also keeps N undisplaced. But that will be changed in 5.0. Pull Request: https://projects.blender.org/blender/blender/pulls/142090
This commit is contained in:
committed by
Brecht Van Lommel
parent
97a5e2ea1b
commit
47f9b7a98e
@@ -877,6 +877,7 @@ enum AttributeStandard {
|
||||
ATTR_STD_GENERATED_TRANSFORM,
|
||||
ATTR_STD_POSITION_UNDEFORMED,
|
||||
ATTR_STD_POSITION_UNDISPLACED,
|
||||
ATTR_STD_NORMAL_UNDISPLACED,
|
||||
ATTR_STD_MOTION_VERTEX_POSITION,
|
||||
ATTR_STD_MOTION_VERTEX_NORMAL,
|
||||
ATTR_STD_PARTICLE,
|
||||
|
||||
@@ -326,6 +326,8 @@ const char *Attribute::standard_name(AttributeStandard std)
|
||||
return "undeformed";
|
||||
case ATTR_STD_POSITION_UNDISPLACED:
|
||||
return "undisplaced";
|
||||
case ATTR_STD_NORMAL_UNDISPLACED:
|
||||
return "undisplaced_N";
|
||||
case ATTR_STD_MOTION_VERTEX_POSITION:
|
||||
return "motion_P";
|
||||
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
||||
@@ -511,6 +513,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
||||
if (geometry->is_mesh()) {
|
||||
switch (std) {
|
||||
case ATTR_STD_VERTEX_NORMAL:
|
||||
case ATTR_STD_NORMAL_UNDISPLACED:
|
||||
attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX);
|
||||
break;
|
||||
case ATTR_STD_UV:
|
||||
|
||||
@@ -706,10 +706,6 @@ void GeometryManager::device_update(Device *device,
|
||||
if (geom->is_mesh() || geom->is_volume()) {
|
||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
||||
|
||||
if (mesh->need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED)) {
|
||||
mesh->add_undisplaced();
|
||||
}
|
||||
|
||||
/* Test if we need tessellation and setup normals if required. */
|
||||
if (mesh->need_tesselation()) {
|
||||
num_tessellation++;
|
||||
|
||||
@@ -550,6 +550,13 @@ void GeometryManager::device_update_attributes(Device *device,
|
||||
for (AttributeRequest &req : attributes.requests) {
|
||||
Attribute *attr = geom->attributes.find(req);
|
||||
|
||||
/* Keep "N" attribute undisplaced for backwards compatibility in Blender 4.5. */
|
||||
if (attr && attr->std == ATTR_STD_VERTEX_NORMAL) {
|
||||
if (Attribute *undisplaced_attr = geom->attributes.find(ATTR_STD_NORMAL_UNDISPLACED)) {
|
||||
attr = undisplaced_attr;
|
||||
}
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
/* force a copy if we need to reallocate all the data */
|
||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
||||
|
||||
@@ -742,25 +742,31 @@ void Mesh::add_vertex_normals()
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::add_undisplaced()
|
||||
void Mesh::add_undisplaced(Scene *scene)
|
||||
{
|
||||
AttributeSet &attrs = (subdivision_type == SUBDIVISION_NONE) ? attributes : subd_attributes;
|
||||
if (need_attribute(scene, ATTR_STD_POSITION_UNDISPLACED) &&
|
||||
!attributes.find(ATTR_STD_POSITION_UNDISPLACED))
|
||||
{
|
||||
/* Copy position to attribute. */
|
||||
Attribute *attr = attributes.add(ATTR_STD_POSITION_UNDISPLACED);
|
||||
|
||||
/* don't compute if already there */
|
||||
if (attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
|
||||
return;
|
||||
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
|
||||
std::copy_n(verts.data(), size, attr->data_float3());
|
||||
}
|
||||
|
||||
/* get attribute */
|
||||
Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
|
||||
/* Keep "N" attribute undisplaced for backwards compatibility in Blender 4.5. */
|
||||
if (((need_attribute(scene, ATTR_STD_VERTEX_NORMAL) && has_true_displacement()) ||
|
||||
need_attribute(scene, ATTR_STD_NORMAL_UNDISPLACED)) &&
|
||||
!attributes.find(ATTR_STD_NORMAL_UNDISPLACED))
|
||||
{
|
||||
/* Copy vertex normal to attribute */
|
||||
Attribute *attr_N = attributes.find(ATTR_STD_VERTEX_NORMAL);
|
||||
if (attr_N) {
|
||||
Attribute *attr = attributes.add(ATTR_STD_NORMAL_UNDISPLACED);
|
||||
|
||||
float3 *data = attr->data_float3();
|
||||
|
||||
/* copy verts */
|
||||
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
|
||||
|
||||
if (size) {
|
||||
std::copy_n(verts.data(), size, data);
|
||||
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
|
||||
std::copy_n(attr_N->data_float3(), size, attr->data_float3());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ class Mesh : public Geometry {
|
||||
void compute_bounds() override;
|
||||
void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
|
||||
void add_vertex_normals();
|
||||
void add_undisplaced();
|
||||
void add_undisplaced(Scene *scene);
|
||||
void update_generated(Scene *scene);
|
||||
void update_tangents(Scene *scene);
|
||||
|
||||
|
||||
@@ -142,6 +142,9 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add undisplaced attributes right before doing displacement. */
|
||||
mesh->add_undisplaced(scene);
|
||||
|
||||
const size_t num_verts = mesh->verts.size();
|
||||
const size_t num_triangles = mesh->num_triangles();
|
||||
|
||||
|
||||
@@ -75,7 +75,6 @@ void SubdAttributeInterpolation::setup()
|
||||
|
||||
bool SubdAttributeInterpolation::support_interp_attribute(const Attribute &attr) const
|
||||
{
|
||||
// TODO: Recompute UV tangent
|
||||
switch (attr.std) {
|
||||
/* Smooth normals are computed from derivatives, for linear interpolate. */
|
||||
case ATTR_STD_VERTEX_NORMAL:
|
||||
|
||||
Reference in New Issue
Block a user