@@ -585,7 +585,8 @@ __device__ __forceinline__ float hexagonalDimplePattern_optix(float3 p)
585585 if (ang < dimple_radius)
586586 {
587587 float t = ang / dimple_radius;
588- return -dimple_depth * cosf (t * M_PIf * 0 .5f );
588+ // Full half-period cosine (Hann profile): C1-continuous at boundary, eliminating jump artifacts.
589+ return -dimple_depth * 0 .5f * (1 .0f + cosf (t * M_PIf));
589590 }
590591 return 0 .0f ;
591592}
@@ -645,9 +646,17 @@ extern "C" __global__ void __closesthit__ch()
645646
646647 if (base_disp < -0 .001f )
647648 {
648- float3 helper = fabsf (base_normal.x ) > 0 .8f ? make_float3 (0 , 1 , 0 ) : make_float3 (1 , 0 , 0 );
649- float3 t1 = normalize3 (cross3 (helper, base_normal));
650- float3 t2 = cross3 (base_normal, t1);
649+ // Duff et al. 2017 "Building an Orthonormal Basis, Revisited":
650+ // continuously varying basis — no seam from a sudden helper-vector switch.
651+ float nz_sign = copysignf (1 .0f , base_normal.z );
652+ float nz_a = -1 .0f / (nz_sign + base_normal.z );
653+ float nz_b = base_normal.x * base_normal.y * nz_a;
654+ float3 t1 = make_float3 (1 .0f + nz_sign * base_normal.x * base_normal.x * nz_a,
655+ nz_sign * nz_b,
656+ -nz_sign * base_normal.x );
657+ float3 t2 = make_float3 (nz_b,
658+ nz_sign + base_normal.y * base_normal.y * nz_a,
659+ -base_normal.y );
651660
652661 const float h = 0 .015f ;
653662 float3 p_hat = base_normal;
@@ -660,12 +669,6 @@ extern "C" __global__ void __closesthit__ch()
660669 float3 grad_tan = dd1 * t1 + dd2 * t2;
661670 float3 delta_n = (-displacement_scale) * grad_tan;
662671
663- float3 view_dir = normalize3 (-ray_dir);
664- float ndv = fmaxf (0 .0f , dot3 (base_normal, view_dir));
665- float atten_t = fmaxf (0 .0f , fminf (1 .0f , (ndv - 0 .1f ) / 0 .3f ));
666- float atten = atten_t * atten_t * (3 .0f - 2 .0f * atten_t ); // smoothstep
667- delta_n = atten * delta_n;
668-
669672 float max_len = 0 .4f ;
670673 float len = length3 (delta_n);
671674 if (len > max_len && len > 1e-6f )
0 commit comments