public void ComputeDifferentials(RayDifferential ray) { if (ray.hasDifferentials) { // Estimate screen space change in $\pt{}$ and $(u,v)$ // Compute auxiliary intersection points with plane double d = -Geometry.Dot(nn, new Vector(p.x, p.y, p.z)); Vector rxv = new Vector(ray.rxOrigin.x, ray.rxOrigin.y, ray.rxOrigin.z); double tx = -(Geometry.Dot(nn, rxv) + d) / Geometry.Dot(nn, ray.rxDirection); if (Double.IsNaN(tx)) { dudx = dvdx = 0.0d; dudy = dvdy = 0.0d; dpdx = dpdy = new Vector(0, 0, 0); return; } Point px = ray.rxOrigin + tx * ray.rxDirection; Vector ryv = new Vector(ray.ryOrigin.x, ray.ryOrigin.y, ray.ryOrigin.z); double ty = -(Geometry.Dot(nn, ryv) + d) / Geometry.Dot(nn, ray.ryDirection); if (Double.IsNaN(ty)) { dudx = dvdx = 0.0d; dudy = dvdy = 0.0d; dpdx = dpdy = new Vector(0, 0, 0); return; } Point py = ray.ryOrigin + ty * ray.ryDirection; dpdx = px - p; dpdy = py - p; // Compute $(u,v)$ offsets at auxiliary points // Initialize _A_, _Bx_, and _By_ matrices for offset computation double[,] A = new double[2, 2]; double[] Bx = new double[2]; double[] By = new double[2]; int[] axes = new int[2]; if (Math.Abs(nn.x) > Math.Abs(nn.y) && Math.Abs(nn.x) > Math.Abs(nn.z)) { axes[0] = 1; axes[1] = 2; } else if (Math.Abs(nn.y) > Math.Abs(nn.z)) { axes[0] = 0; axes[1] = 2; } else { axes[0] = 0; axes[1] = 1; } // Initialize matrices for chosen projection plane A[0, 0] = dpdu[axes[0]]; A[0, 1] = dpdv[axes[0]]; A[1, 0] = dpdu[axes[1]]; A[1, 1] = dpdv[axes[1]]; Bx[0] = px[axes[0]] - p[axes[0]]; Bx[1] = px[axes[1]] - p[axes[1]]; By[0] = py[axes[0]] - p[axes[0]]; By[1] = py[axes[1]] - p[axes[1]]; if (!Utility.SolveLinearSystem2x2(A, Bx, out dudx, out dvdx)) { dudx = 0.0d; dvdx = 0.0d; } if (!Utility.SolveLinearSystem2x2(A, By, out dudy, out dvdy)) { dudy = 0.0d; dvdy = 0.0d; } } else { dudx = dvdx = 0.0d; dudy = dvdy = 0.0d; dpdx = dpdy = new Vector(0, 0, 0); } }
public BSSRDF GetBSSRDF(RayDifferential ray) { dg.ComputeDifferentials(ray); BSSRDF bssrdf = primitive.GetBSSRDF(dg, ObjectToWorld); return bssrdf; }