Fix T94251: Cycles wrong pointcloud normal for instanced objects

Refactor code a bit also so we need to do fewer matrix transforms for shader
data setup of points and curves.
This commit is contained in:
Brecht Van Lommel 2021-12-20 06:00:38 +01:00
parent e2e7f7ea52
commit edb3ab0617
Notes: blender-bot 2023-02-14 00:20:19 +01:00
Referenced by issue #94251, Cycles: point cloud geometry renders with incorrect normals when object is rotated
3 changed files with 39 additions and 42 deletions

View File

@ -727,8 +727,6 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
const float cosine = safe_sqrtf(1.0f - sine * sine);
sd->N = normalize(sine * bitangent - cosine * normalize(cross(tangent, bitangent)));
sd->Ng = -D;
# if 0
/* This approximates the position and geometric normal of a thick curve too,
* but gives too many issues with wrong self intersections. */
@ -744,25 +742,27 @@ ccl_device_inline void curve_shader_setup(KernelGlobals kg,
/* NOTE: It is possible that P will be the same as P_inside (precision issues, or very small
* radius). In this case use the view direction to approximate the normal. */
const float3 P_inside = float4_to_float3(catmull_rom_basis_eval(P_curve, sd->u));
const float3 Ng = (!isequal_float3(P, P_inside)) ? normalize(P - P_inside) : -sd->I;
const float3 N = (!isequal_float3(P, P_inside)) ? normalize(P - P_inside) : -sd->I;
sd->N = Ng;
sd->Ng = Ng;
sd->N = N;
sd->v = 0.0f;
}
# ifdef __DPDU__
/* dPdu/dPdv */
sd->dPdu = dPdu;
sd->dPdv = cross(dPdu, sd->Ng);
# endif
/* Convert to world space. */
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
const Transform tfm = object_get_transform(kg, sd);
P = transform_point(&tfm, P);
object_position_transform_auto(kg, sd, &P);
object_normal_transform_auto(kg, sd, &sd->N);
object_dir_transform_auto(kg, sd, &sd->dPdu);
}
sd->P = P;
sd->Ng = (sd->type & PRIMITIVE_CURVE_RIBBON) ? sd->I : sd->N;
sd->dPdv = cross(sd->dPdu, sd->Ng);
sd->shader = kernel_tex_fetch(__curves, sd->prim).shader_id;
}

View File

@ -104,17 +104,12 @@ ccl_device_inline void point_shader_setup(KernelGlobals kg,
sd->v = isect->v;
# endif
/* Computer point center for normal. */
/* Compute point center for normal. */
float3 center = float4_to_float3((isect->type & PRIMITIVE_MOTION) ?
motion_point(kg, sd->object, sd->prim, sd->time) :
kernel_tex_fetch(__points, sd->prim));
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
const Transform tfm = object_get_transform(kg, sd);
# ifndef __KERNEL_OPTIX__
center = transform_point(&tfm, center);
# endif
object_position_transform_auto(kg, sd, &center);
}
/* Normal */

View File

@ -82,43 +82,45 @@ ccl_device_inline void shader_setup_from_ray(KernelGlobals kg,
}
else
#endif
if (sd->type == PRIMITIVE_TRIANGLE) {
/* static triangle */
float3 Ng = triangle_normal(kg, sd);
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
{
if (sd->type == PRIMITIVE_TRIANGLE) {
/* static triangle */
float3 Ng = triangle_normal(kg, sd);
sd->shader = kernel_tex_fetch(__tri_shader, sd->prim);
/* vectors */
sd->P = triangle_refine(kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim);
sd->Ng = Ng;
sd->N = Ng;
/* vectors */
sd->P = triangle_refine(kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim);
sd->Ng = Ng;
sd->N = Ng;
/* smooth normal */
if (sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
/* smooth normal */
if (sd->shader & SHADER_SMOOTH_NORMAL)
sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
#ifdef __DPDU__
/* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
/* dPdu/dPdv */
triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
#endif
}
else {
/* motion triangle */
motion_triangle_shader_setup(
kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim, false);
}
}
else {
/* motion triangle */
motion_triangle_shader_setup(
kg, sd, ray->P, ray->D, isect->t, isect->object, isect->prim, false);
}
sd->flag |= kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
/* instance transform */
object_normal_transform_auto(kg, sd, &sd->N);
object_normal_transform_auto(kg, sd, &sd->Ng);
if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
/* instance transform */
object_normal_transform_auto(kg, sd, &sd->N);
object_normal_transform_auto(kg, sd, &sd->Ng);
#ifdef __DPDU__
object_dir_transform_auto(kg, sd, &sd->dPdu);
object_dir_transform_auto(kg, sd, &sd->dPdv);
object_dir_transform_auto(kg, sd, &sd->dPdu);
object_dir_transform_auto(kg, sd, &sd->dPdv);
#endif
}
}
sd->flag = kernel_tex_fetch(__shaders, (sd->shader & SHADER_MASK)).flags;
/* backfacing test */
bool backfacing = (dot(sd->Ng, sd->I) < 0.0f);