Merge branch 'blender-v5.1-release'

This commit is contained in:
Brecht Van Lommel 2026-02-09 23:20:45 +01:00
commit e3145bcc59
19 changed files with 100 additions and 60 deletions

View file

@ -134,7 +134,7 @@ ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg,
/* Interpolate smooth vertex normal from vertices */
ccl_device_forceinline float3 triangle_smooth_normal_unnormalized(
ccl_device_inline float3 triangle_smooth_normal(
KernelGlobals kg, float3 Ng, int object, int object_flag, int prim, float u, float v)
{
const int normal_offset = kernel_data_fetch(objects, object).normal_attr_offset;
@ -152,24 +152,11 @@ ccl_device_forceinline float3 triangle_smooth_normal_unnormalized(
i2 = tri_vindex.z;
}
const float3 N = attribute_data_interpolate_normals(kg, normal_offset, i0, i1, i2, u, v);
const float3 N = safe_normalize(
attribute_data_interpolate_normals(kg, normal_offset, i0, i1, i2, u, v));
return is_zero(N) ? Ng : N;
}
ccl_device_inline float3 triangle_smooth_normal(
KernelGlobals kg, float3 Ng, int object, int object_flag, int prim, float u, float v)
{
return safe_normalize(
triangle_smooth_normal_unnormalized(kg, Ng, object, object_flag, prim, u, v));
}
ccl_device_inline float3 triangle_smooth_normal_unnormalized(KernelGlobals kg,
ccl_private const ShaderData *sd)
{
return triangle_smooth_normal_unnormalized(
kg, sd->Ng, sd->object, sd->object_flag, sd->prim, sd->u, sd->v);
}
/* Compute triangle normals at the hit position, and offsetted positions in x and y direction for
* bump mapping. */
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg,
@ -211,6 +198,40 @@ ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg,
return is_zero(N) ? Ng : N;
}
/* Special variation for normal mapping, where we want to match the unnormalized object
* space interpolation as assumed by normal map baking exactly. An exact match avoids
* discontinuities across UV seams.*/
ccl_device_inline float3 triangle_smooth_normal_unnormalized_object_space(
KernelGlobals kg, ccl_private const ShaderData *sd)
{
const int normal_offset = kernel_data_fetch(objects, sd->object).normal_attr_offset;
int i0, i1, i2;
if (sd->object_flag & SD_OBJECT_HAS_CORNER_NORMALS) {
i0 = sd->prim * 3 + 0;
i1 = sd->prim * 3 + 1;
i2 = sd->prim * 3 + 2;
}
else {
const uint3 tri_vindex = kernel_data_fetch(tri_vindex, sd->prim);
i0 = tri_vindex.x;
i1 = tri_vindex.y;
i2 = tri_vindex.z;
}
float3 n[3];
attribute_data_fetch_normals(kg, normal_offset, i0, i1, i2, n);
if (sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED) {
object_inverse_normal_transform(kg, sd, &n[0]);
object_inverse_normal_transform(kg, sd, &n[1]);
object_inverse_normal_transform(kg, sd, &n[2]);
}
const float3 N = safe_normalize(triangle_interpolate(sd->u, sd->v, n[0], n[1], n[2]));
return is_zero(N) ? sd->Ng : N;
}
/* Ray differentials on triangle */
ccl_device_inline void triangle_dPdudv(KernelGlobals kg,

View file

@ -805,7 +805,7 @@ bool OSLRenderServices::get_object_standard_attribute(ShaderGlobals *globals,
if (desc.offset != ATTR_STD_NOT_FOUND) {
return get_object_attribute(kg, sd, desc, type, derivatives, val);
}
const float3 f = triangle_smooth_normal_unnormalized(kg, sd);
const float3 f = triangle_smooth_normal_unnormalized_object_space(kg, sd);
return set_attribute(f, type, derivatives, val);
}
return false;

View file

@ -884,7 +884,7 @@ ccl_device_inline bool get_object_standard_attribute(KernelGlobals kg,
if (desc.offset != ATTR_STD_NOT_FOUND) {
return get_object_attribute(kg, sd, desc, type, derivatives, val);
}
float3 f = triangle_smooth_normal_unnormalized(kg, sd);
float3 f = triangle_smooth_normal_unnormalized_object_space(kg, sd);
return set_attribute(f, type, derivatives, val);
}
else {

View file

@ -380,7 +380,7 @@ ccl_device_noinline void svm_node_normal_map(KernelGlobals kg,
linear_interpolate_strength = true;
}
else {
normal = triangle_smooth_normal_unnormalized(kg, sd);
normal = triangle_smooth_normal_unnormalized_object_space(kg, sd);
}
}
else {

View file

@ -142,9 +142,6 @@ 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();
@ -152,6 +149,23 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
return false;
}
/* Corner normals can't be preserved through displacement, replace with vertex normals. */
bool need_recompute_vertex_normals = false;
bool need_recompute_all_vertex_normals = false;
if (mesh->attributes.find(ATTR_STD_CORNER_NORMAL) ||
mesh->attributes.find(ATTR_STD_MOTION_CORNER_NORMAL))
{
mesh->attributes.remove(ATTR_STD_CORNER_NORMAL);
mesh->attributes.remove(ATTR_STD_MOTION_CORNER_NORMAL);
need_recompute_vertex_normals = true;
need_recompute_all_vertex_normals = true;
mesh->add_vertex_normals();
}
/* Add undisplaced attributes right before doing displacement. */
mesh->add_undisplaced(scene);
const string msg = string_printf("Computing Displacement %s", mesh->name.c_str());
progress.set_status("Updating Mesh", msg);
@ -184,23 +198,6 @@ bool GeometryManager::displace(Device *device, Scene *scene, Mesh *mesh, Progres
/* For displacement method both, we don't need to recompute the vertex normals
* as bump mapping in the shader will already alter the vertex normal, so we start
* from the non-displaced vertex normals to avoid applying the perturbation twice. */
bool need_recompute_vertex_normals = false;
bool need_recompute_all_vertex_normals = false;
/* Corner normals can't be preserved through displacement. */
if (mesh->attributes.find(ATTR_STD_CORNER_NORMAL)) {
mesh->attributes.remove(ATTR_STD_CORNER_NORMAL);
mesh->attributes.add(ATTR_STD_VERTEX_NORMAL);
need_recompute_vertex_normals = true;
need_recompute_all_vertex_normals = true;
}
if (mesh->attributes.find(ATTR_STD_MOTION_CORNER_NORMAL)) {
mesh->attributes.remove(ATTR_STD_MOTION_CORNER_NORMAL);
mesh->attributes.add(ATTR_STD_MOTION_VERTEX_NORMAL);
need_recompute_vertex_normals = true;
need_recompute_all_vertex_normals = true;
}
for (Node *node : mesh->get_used_shaders()) {
Shader *shader = static_cast<Shader *>(node);
if (shader->has_displacement && shader->get_displacement_method() == DISPLACE_TRUE) {

View file

@ -1686,26 +1686,6 @@ static void icon_preview_endjob(void *customdata)
{
IconPreview *ip = static_cast<IconPreview *>(customdata);
if (ip->id) {
#if 0
if (GS(ip->id->name) == ID_MA) {
Material *ma = (Material *)ip->id;
PreviewImage *prv_img = ma->preview;
int i;
/* signal to gpu texture */
for (i = 0; i < NUM_ICON_SIZES; i++) {
if (prv_img->gputexture[i]) {
GPU_texture_free(prv_img->gputexture[i]);
prv_img->gputexture[i] = nullptr;
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ip->id);
}
}
}
#endif
}
if (ip->owner) {
PreviewImage *prv_img = static_cast<PreviewImage *>(ip->owner);
prv_img->runtime->tag &= ~PRV_TAG_DEFFERED_RENDERING;
@ -1716,9 +1696,10 @@ static void icon_preview_endjob(void *customdata)
}
if (prv_img->runtime->tag & PRV_TAG_DEFFERED_DELETE) {
BLI_assert(prv_img->runtime->deferred_loading_data);
BKE_previewimg_deferred_release(prv_img);
}
ip->owner = nullptr;
}
}
@ -2190,6 +2171,8 @@ void PreviewLoadJob::free_fn(void *customdata)
static void icon_preview_free(void *customdata)
{
icon_preview_endjob(customdata);
IconPreview *ip = static_cast<IconPreview *>(customdata);
if (ip->id_copy) {

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:15eb7fdc7d4c09468efc25989acb19e5e4f9bec0301c3e37b7a0960342941017
size 127416

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9b498a41df26d97f8761b15b7d091afab7de4a1465a3bd1b4eab5e4fe1ee2f90
size 16876

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7f7868948a65a5352179c96ebff97d075022a03be78be976853fb1f0f9f60042
size 15374

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6527a231509136070c34283474a29015002609a10f79a2c4014f2c7b4619f59f
size 8189

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fca07996a4e791222768e316ce580ab900102185b6a32dcd0ad7b4125a380706
size 12188

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:842b176f1c81a21b4e8bf52826fbfaa28858ad7c2eefd971084be1e40b4ac096
size 11057

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc435752e53c7db4009230c6d1444c9c4cf5599816ba81590a55ae2b87d68c26
size 17983

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:43c8c51e78724e2d6b4d33802c8764c9bd122821035754e91b30729a1888eb59
size 18037

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cc21cd8b22cc053a85d10787549f78cb2b3eda9176da4da7ed353ed8a870d030
size 1658239

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f8e81e5ac811d72615c579107fbca8f766ae05cef21ffabc07e8580ef901fde5
size 16750

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2905137591b64dc7b5dc16c33bdbe73ad1d5286cd8764b7a0c2dee52741c6ce8
size 16741

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d4fbe0af5fc1856235751fde3180ee96b55d6e798749766f3ac51189c575b685
size 14760

View file

@ -31,6 +31,7 @@ BLOCKLIST_HYDRA = [
"image.*_float.*.blend",
# Differences between devices/drivers causing this to fail
"image.blend",
"normal_map_transform.blend",
# VDB rendering is incorrect on Metal
"overlapping_octrees.blend",
# No number of sample support, so will not converge to gray as expected
@ -41,6 +42,8 @@ BLOCKLIST_USD = [
# Corrupted output around borders
"image.*_half.*.blend",
"image.*_float.*.blend",
# Differences between devices/drivers causing this to fail
"normal_map_transform.blend",
# Nondeterministic exporting of lights in the scene
"light_tree_node_subtended_angle.blend",
# VDB rendering is incorrect on Metal