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_GENERATED_TRANSFORM,
|
||||||
ATTR_STD_POSITION_UNDEFORMED,
|
ATTR_STD_POSITION_UNDEFORMED,
|
||||||
ATTR_STD_POSITION_UNDISPLACED,
|
ATTR_STD_POSITION_UNDISPLACED,
|
||||||
|
ATTR_STD_NORMAL_UNDISPLACED,
|
||||||
ATTR_STD_MOTION_VERTEX_POSITION,
|
ATTR_STD_MOTION_VERTEX_POSITION,
|
||||||
ATTR_STD_MOTION_VERTEX_NORMAL,
|
ATTR_STD_MOTION_VERTEX_NORMAL,
|
||||||
ATTR_STD_PARTICLE,
|
ATTR_STD_PARTICLE,
|
||||||
|
|||||||
@@ -326,6 +326,8 @@ const char *Attribute::standard_name(AttributeStandard std)
|
|||||||
return "undeformed";
|
return "undeformed";
|
||||||
case ATTR_STD_POSITION_UNDISPLACED:
|
case ATTR_STD_POSITION_UNDISPLACED:
|
||||||
return "undisplaced";
|
return "undisplaced";
|
||||||
|
case ATTR_STD_NORMAL_UNDISPLACED:
|
||||||
|
return "undisplaced_N";
|
||||||
case ATTR_STD_MOTION_VERTEX_POSITION:
|
case ATTR_STD_MOTION_VERTEX_POSITION:
|
||||||
return "motion_P";
|
return "motion_P";
|
||||||
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
||||||
@@ -511,6 +513,7 @@ Attribute *AttributeSet::add(AttributeStandard std, ustring name)
|
|||||||
if (geometry->is_mesh()) {
|
if (geometry->is_mesh()) {
|
||||||
switch (std) {
|
switch (std) {
|
||||||
case ATTR_STD_VERTEX_NORMAL:
|
case ATTR_STD_VERTEX_NORMAL:
|
||||||
|
case ATTR_STD_NORMAL_UNDISPLACED:
|
||||||
attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX);
|
attr = add(name, TypeNormal, ATTR_ELEMENT_VERTEX);
|
||||||
break;
|
break;
|
||||||
case ATTR_STD_UV:
|
case ATTR_STD_UV:
|
||||||
|
|||||||
@@ -706,10 +706,6 @@ void GeometryManager::device_update(Device *device,
|
|||||||
if (geom->is_mesh() || geom->is_volume()) {
|
if (geom->is_mesh() || geom->is_volume()) {
|
||||||
Mesh *mesh = static_cast<Mesh *>(geom);
|
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. */
|
/* Test if we need tessellation and setup normals if required. */
|
||||||
if (mesh->need_tesselation()) {
|
if (mesh->need_tesselation()) {
|
||||||
num_tessellation++;
|
num_tessellation++;
|
||||||
|
|||||||
@@ -550,6 +550,13 @@ void GeometryManager::device_update_attributes(Device *device,
|
|||||||
for (AttributeRequest &req : attributes.requests) {
|
for (AttributeRequest &req : attributes.requests) {
|
||||||
Attribute *attr = geom->attributes.find(req);
|
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) {
|
if (attr) {
|
||||||
/* force a copy if we need to reallocate all the data */
|
/* force a copy if we need to reallocate all the data */
|
||||||
attr->modified |= attributes_need_realloc[Attribute::kernel_type(*attr)];
|
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 */
|
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
|
||||||
if (attrs.find(ATTR_STD_POSITION_UNDISPLACED)) {
|
std::copy_n(verts.data(), size, attr->data_float3());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get attribute */
|
/* Keep "N" attribute undisplaced for backwards compatibility in Blender 4.5. */
|
||||||
Attribute *attr = attrs.add(ATTR_STD_POSITION_UNDISPLACED);
|
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();
|
size_t size = attr->buffer_size(this, ATTR_PRIM_GEOMETRY) / sizeof(float3);
|
||||||
|
std::copy_n(attr_N->data_float3(), size, 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ class Mesh : public Geometry {
|
|||||||
void compute_bounds() override;
|
void compute_bounds() override;
|
||||||
void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
|
void apply_transform(const Transform &tfm, const bool apply_to_motion) override;
|
||||||
void add_vertex_normals();
|
void add_vertex_normals();
|
||||||
void add_undisplaced();
|
void add_undisplaced(Scene *scene);
|
||||||
void update_generated(Scene *scene);
|
void update_generated(Scene *scene);
|
||||||
void update_tangents(Scene *scene);
|
void update_tangents(Scene *scene);
|
||||||
|
|
||||||
|
|||||||
@@ -142,6 +142,9 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
|
|||||||
return false;
|
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_verts = mesh->verts.size();
|
||||||
const size_t num_triangles = mesh->num_triangles();
|
const size_t num_triangles = mesh->num_triangles();
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ void SubdAttributeInterpolation::setup()
|
|||||||
|
|
||||||
bool SubdAttributeInterpolation::support_interp_attribute(const Attribute &attr) const
|
bool SubdAttributeInterpolation::support_interp_attribute(const Attribute &attr) const
|
||||||
{
|
{
|
||||||
// TODO: Recompute UV tangent
|
|
||||||
switch (attr.std) {
|
switch (attr.std) {
|
||||||
/* Smooth normals are computed from derivatives, for linear interpolate. */
|
/* Smooth normals are computed from derivatives, for linear interpolate. */
|
||||||
case ATTR_STD_VERTEX_NORMAL:
|
case ATTR_STD_VERTEX_NORMAL:
|
||||||
|
|||||||
Reference in New Issue
Block a user