public static void Bump(ITexture<double> d, DifferentialGeometry dgGeom, DifferentialGeometry dgShading, ref DifferentialGeometry dgBump) { DifferentialGeometry dgEval = new DifferentialGeometry (dgShading); double du = 0.5 * (Math.Abs (dgShading.dudx) + Math.Abs (dgShading.dudy)); if (du == 0.0) du = 0.01; dgEval.p = dgShading.p + du * dgShading.dpdu; dgEval.u = dgShading.u + du; dgEval.n = (new Normal(dgShading.dpdu % dgShading.dpdv) + du * dgShading.dndu).Normalized; double uDisplace = d.Evaluate (dgEval); double dv = 0.5 * (Math.Abs (dgShading.dvdx) + Math.Abs (dgShading.dvdy)); if (dv == 0.0) dv = 0.01; dgEval.p = dgShading.p + dv * dgShading.dpdv; dgEval.u = dgShading.u; dgEval.v = dgShading.v + dv; dgEval.n = (new Normal(dgShading.dpdu % dgShading.dpdv) + dv * dgShading.dndv).Normalized; double vDisplace = d.Evaluate (dgEval); double displace = d.Evaluate (dgShading); dgBump = new DifferentialGeometry (dgShading); dgBump.dpdu = dgShading.dpdu + (uDisplace - displace) / du * new Vector (dgShading.n) + displace * new Vector (dgShading.dndu); dgBump.dpdv = dgShading.dpdv + (vDisplace - displace) / dv * new Vector (dgShading.n) + displace * new Vector (dgShading.dndv); dgBump.n = new Normal((dgBump.dpdu % dgBump.dpdv).Normalized); if (dgShading.Shape.ReverseOrientation ^ dgShading.Shape.TransformSwapsHandedness) dgBump.n *= -1.0; dgBump.n = Util.FaceForward (dgBump.n, dgGeom.n); }
public BSDF(DifferentialGeometry dgs, Normal ngeom, double eta) { dgShading = new DifferentialGeometry (dgs); Eta = eta; ng = new Normal (ngeom); nn = new Normal (dgShading.n); sn = dgShading.dpdu.Normalized; tn = nn % sn; nBxDFs = 0; }
public override BSDF GetBsdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading) { BSDF b1 = m1.GetBsdf (dgGeom, dgShading); BSDF b2 = m2.GetBsdf (dgGeom, dgShading); Spectrum s1 = scale.Evaluate (dgShading).Clamp (); Spectrum s2 = (new Spectrum (1.0) - s1).Clamp (); int n1 = b1.NumComponents (), n2 = b2.NumComponents (); for (int i = 0; i < n1; ++i) b1.bxdfs[i] = new ScaledBxDF (b1.bxdfs[i], s1); for (int i = 0; i < n2; ++i) b1.Add (new ScaledBxDF (b2.bxdfs[i], s2)); return b1; }
public override BSDF GetBsdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading) { DifferentialGeometry dgs = new DifferentialGeometry (); if (BumpMap != null) Bump (BumpMap, dgGeom, dgShading, ref dgs); else dgs = new DifferentialGeometry (dgShading); BSDF bsdf = new BSDF (dgs, dgGeom.n); Spectrum R = Kr.Evaluate (dgs).Clamp (); double e = Eta.Evaluate (dgs); if (!R.IsBlack) bsdf.Add (new SpecularReflection (R, new FresnelDielectric (1.0, e))); return bsdf; }
public DifferentialGeometry(DifferentialGeometry dg) { this.p = new Point (dg.p); this.dpdu = new Vector (dg.dpdu); this.dpdv = new Vector (dg.dpdv); this.dndu = new Normal (dg.dndu); this.dndv = new Normal (dg.dndv); this.n = new Normal (dg.n); this.u = dg.u; this.v = dg.v; this.dudx = dg.dudx; this.dvdx = dg.dvdx; this.dudy = dg.dudy; this.dvdy = dg.dvdy; this.Shape = dg.Shape; }
public Point Sample(Point p, LightSample lightSample, ref Normal Ns) { double temp = 0.0; int sn = AreaDistribution.SampleDiscrete (lightSample.uComponent, ref temp); Point pt = Shapes[sn].Sample (p, lightSample.uPos[0], lightSample.uPos[1], ref Ns); // Find closest intersection of ray with shapes in _ShapeSet_ Ray r = new Ray (p, pt - p, 0.001, double.PositiveInfinity); double rayEps = 0.0, thit = 1.0; bool anyHit = false; DifferentialGeometry dg = new DifferentialGeometry (); foreach (IShape shape in Shapes) anyHit |= shape.Intersect (r, ref thit, ref rayEps, ref dg); if (anyHit) Ns = new Normal (dg.n); return r.Apply (thit); }
public override bool Intersect(Ray r, ref double tHit, ref double rayEpsilon, ref DifferentialGeometry dg) { // Transform _Ray_ to object space Ray ray = new Ray (); WorldToObject.Apply (r, ref ray); // Compute plane intersection for disk if (Math.Abs (ray.Direction.z) < 1E-07) return false; double thit = (Height - ray.Origin.z) / ray.Direction.z; if (thit < ray.MinT || thit > ray.MaxT) return false; // See if hit point is inside disk radii and $\phimax$ Point phit = ray.Apply (thit); double dist2 = phit.x * phit.x + phit.y * phit.y; if (dist2 > Radius * Radius || dist2 < InnerRadius * InnerRadius) return false; // Test disk $\phi$ value against $\phimax$ double phi = Math.Atan2 (phit.y, phit.x); if (phi < 0) phi += 2.0 * Util.Pi; if (phi > PhiMax) return false; // Find parametric representation of disk hit double u = phi / PhiMax; double v = 1.0 - ((Math.Sqrt (dist2) - InnerRadius) / (Radius - InnerRadius)); Vector dpdu = new Vector (-PhiMax * phit.y, PhiMax * phit.x, 0.0); Vector dpdv = new Vector (-phit.x / (1 - v), -phit.y / (1 - v), 0.0); dpdu *= PhiMax * Util.InvTwoPi; dpdv *= (Radius - InnerRadius) / Radius; Normal dndu = new Normal (0, 0, 0), dndv = new Normal (0, 0, 0); // Initialize _DifferentialGeometry_ from parametric information dg = new DifferentialGeometry (ObjectToWorld.Apply (phit), ObjectToWorld.Apply (dpdu), ObjectToWorld.Apply (dpdv), ObjectToWorld.Apply (dndu), ObjectToWorld.Apply (dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 0.0005 * tHit; return true; }
public override BSDF GetBsdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading) { DifferentialGeometry dgs = new DifferentialGeometry (); if (BumpMap != null) Bump (BumpMap, dgGeom, dgShading, ref dgs); else dgs = new DifferentialGeometry (dgShading); BSDF bsdf = new BSDF (dgs, dgGeom.n); Spectrum r = Kd.Evaluate (dgs).Clamp (); double sig = Util.Clamp (Sigma.Evaluate (dgs), 0.0, 90.0); if (sig == 0.0) bsdf.Add (new Lambertian (r)); else bsdf.Add (new OrenNayar (r, sig)); return bsdf; }
public virtual BSSRDF GetBssrdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading) { return null; }
public virtual void GetShadingGeometry(Transform objectToWorld, DifferentialGeometry dg, ref DifferentialGeometry dgShading) { dgShading = new DifferentialGeometry (dg); }
public abstract BSDF GetBsdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading);
public virtual bool Intersect(Ray ray, ref double tHit, ref double rayEpsilon, ref DifferentialGeometry dg) { return false; }
public override BSSRDF GetBssrdf(DifferentialGeometry dgGeom, DifferentialGeometry dgShading) { double e = Eta.Evaluate (dgShading); return new BSSRDF (Scale * SigmaA.Evaluate (dgShading), Scale * SigmaPrimeS.Evaluate (dgShading), e); }
public override bool IntersectP(Ray ray) { Point p1 = Mesh.Points[Vertices[0]]; Point p2 = Mesh.Points[Vertices[1]]; Point p3 = Mesh.Points[Vertices[2]]; Vector e1 = p2 - p1; Vector e2 = p3 - p1; Vector s1 = ray.Direction % e2; double divisor = s1 ^ e1; if (divisor == 0.0) return false; double invDivisor = 1.0 / divisor; Vector d = ray.Origin - p1; double b1 = (d ^ s1) * invDivisor; if (b1 < 0.0 || b1 > 1.0) return false; Vector s2 = d % e1; double b2 = (ray.Direction ^ s2) * invDivisor; if (b2 < 0.0 || b1 + b2 > 1.0) return false; double t = (e2 ^ s2) * invDivisor; if (t < ray.MinT || t > ray.MaxT) return false; if (ray.Depth != -1) { Vector dpdu = new Vector (), dpdv = new Vector (); double[] uvs = new double[6]; GetUVs (uvs); double du1 = uvs[0] - uvs[4]; double du2 = uvs[2] - uvs[4]; double dv1 = uvs[1] - uvs[5]; double dv2 = uvs[3] - uvs[5]; Vector dp1 = p1 - p3, dp2 = p2 - p3; double determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.0) Util.CoordinateSystem ((e2 % e1).Normalized, out dpdu, out dpdv); else { double invdet = 1.0 / determinant; dpdu = (dv2 * dp1 - dv1 * dp2) * invdet; dpdv = (-du2 * dp1 - du1 * dp2) * invdet; } double b0 = 1 - b1 - b2; double tu = b0 * uvs[0] + b1 * uvs[2] + b2 * uvs[4]; double tv = b0 * uvs[1] + b1 * uvs[3] + b2 * uvs[5]; DifferentialGeometry dgLocal = new DifferentialGeometry (ray.Apply (t), dpdu, dpdv, new Normal (), new Normal (), tu, tv, this); if (Mesh.AlphaTexture != null && Mesh.AlphaTexture.Evaluate (dgLocal) == 0.0) return false; } return true; }
public override void GetShadingGeometry(Transform objectToWorld, DifferentialGeometry dg, ref DifferentialGeometry dgShading) { if (Mesh.Normals == null && Mesh.Vectors == null) { dgShading = new DifferentialGeometry (dg); return; } // Initialize _Triangle_ shading geometry with _n_ and _s_ // Compute barycentric coordinates for point double[] b = new double[3]; // Initialize _A_ and _C_ matrices for barycentrics double[] uv = new double[6]; GetUVs (uv); double[][] A = new double[][] { new double[] { uv[2] - uv[0], uv[4] - uv[0] }, new double[] { uv[3] - uv[1], uv[5] - uv[1] } }; double[] C = new double[] { dg.u - uv[0], dg.v - uv[1] }; if (!Util.SolveLinearSystem2x2 (A, C[0], C[1], out b[1], out b[2])) { // Handle degenerate parametric mapping b[0] = b[1] = b[2] = 1.0 / 3.0; } else b[0] = 1.0 - b[1] - b[2]; // Use _n_ and _s_ to compute shading tangents for triangle, _ss_ and _ts_ Normal ns; Vector ss, ts; if (Mesh.Normals != null) ns = objectToWorld.Apply (b[0] * Mesh.Normals[Vertices[0]] + b[1] * Mesh.Normals[Vertices[1]] + b[2] * Mesh.Normals[Vertices[2]]).Normalized; else ns = new Normal (dg.n); if (Mesh.Vectors != null) ss = objectToWorld.Apply (b[0] * Mesh.Vectors[Vertices[0]] + b[1] * Mesh.Vectors[Vertices[1]] + b[2] * Mesh.Vectors[Vertices[2]]).Normalized; else ss = dg.dpdu.Normalized; ts = ss % ns; if (ts.SquaredLength > 0.0) { ts = ts.Normalized; ss = ts % ns; } else Util.CoordinateSystem (new Vector (ns), out ss, out ts); Normal dndu, dndv; // Compute $\dndu$ and $\dndv$ for triangle shading geometry if (Mesh.Normals != null) { double[] uvs = new double[6]; GetUVs (uvs); // Compute deltas for triangle partial derivatives of normal double du1 = uvs[0] - uvs[4]; double du2 = uvs[2] - uvs[4]; double dv1 = uvs[1] - uvs[5]; double dv2 = uvs[3] - uvs[5]; Normal dn1 = Mesh.Normals[Vertices[0]] - Mesh.Normals[Vertices[2]]; Normal dn2 = Mesh.Normals[Vertices[1]] - Mesh.Normals[Vertices[2]]; double determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.0) { dndu = new Normal (0, 0, 0); dndv = new Normal (0, 0, 0); } else { double invdet = 1.0 / determinant; dndu = (dv2 * dn1 - dv1 * dn2) * invdet; dndv = (-du2 * dn1 + du1 * dn2) * invdet; } } else { dndu = new Normal (0, 0, 0); dndv = new Normal (0, 0, 0); } dgShading = new DifferentialGeometry (dg.p, ss, ts, ObjectToWorld.Apply (dndu), ObjectToWorld.Apply (dndv), dg.u, dg.v, dg.Shape); dgShading.dudx = dg.dudx; dgShading.dvdx = dg.dvdx; dgShading.dudy = dg.dudy; dgShading.dvdy = dg.dvdy; dgShading.dpdx = new Vector (dg.dpdx); dgShading.dpdy = new Vector (dg.dpdy); }
public abstract BSDF GetBsdf(DifferentialGeometry dg, Transform objectoToWorld);
public abstract BSSRDF GetBssrdf(DifferentialGeometry dg, Transform objectToWorld);
public virtual double Pdf(Point p, Vector wi) { DifferentialGeometry dgLight = new DifferentialGeometry (); Ray ray = new Ray (p, wi, 1e-3); ray.Depth = - 1; double thit = 0.0, rayEpsilon = 0.0; if (!Intersect (ray, ref thit, ref rayEpsilon, ref dgLight)) return 0.0; double pdf = Util.DistanceSquared (p, ray.Apply (thit)) / Util.AbsDot (dgLight.n, -wi) * Area; if (double.IsInfinity (pdf)) pdf = 0.0; return pdf; }
public override Point Sample(Point p, double u1, double u2, ref Normal Ns) { // Compute coordinate system for sphere sampling Point Pcenter = ObjectToWorld.Apply (new Point ()); Vector wc = (Pcenter - p).Normalized; Vector wcX, wcY; Util.CoordinateSystem (wc, out wcX, out wcY); // Sample uniformly on sphere if $\pt{}$ is inside it if (Util.DistanceSquared (p, Pcenter) - Radius * Radius < 0.0001) return Sample (u1, u2, ref Ns); // Sample sphere uniformly inside subtended cone double sinThetaMax2 = Radius * Radius / Util.DistanceSquared (p, Pcenter); double cosThetaMax = Math.Sqrt (Math.Max (0.0, 1.0 - sinThetaMax2)); DifferentialGeometry dgSphere = new DifferentialGeometry (); double thit = 0.0, rayEpsilon = 0.0; Point ps; Ray r = new Ray (p, MonteCarlo.UniformSampleCone (u1, u2, cosThetaMax, wcX, wcY, wc), 0.001); if (!Intersect (r, ref thit, ref rayEpsilon, ref dgSphere)) thit = ((Pcenter - p) ^ r.Direction.Normalized); ps = r.Apply (thit); Ns = new Normal ((ps - Pcenter).Normalized); if (ReverseOrientation) Ns *= -1.0; return ps; }
public BSDF(DifferentialGeometry dgs, Normal ngeom) : this(dgs, ngeom, 1.0) { }
public override BSSRDF GetBssrdf(DifferentialGeometry dg, Transform objectToWorld) { DifferentialGeometry dgs = new DifferentialGeometry (); Shape.GetShadingGeometry (objectToWorld, dg, ref dgs); return Material.GetBssrdf (dg, dgs); }
public override bool Intersect(Ray r, ref double tHit, ref double rayEpsilon, ref DifferentialGeometry dg) { double phi; Point phit; // Transform _Ray_ to object space Ray ray = new Ray (); WorldToObject.Apply (r, ref ray); // Compute quadratic sphere coefficients double A = ray.Direction.x * ray.Direction.x + ray.Direction.y * ray.Direction.y + ray.Direction.z * ray.Direction.z; double B = 2 * (ray.Direction.x * ray.Origin.x + ray.Direction.y * ray.Origin.y + ray.Direction.z * ray.Origin.z); double C = ray.Origin.x * ray.Origin.x + ray.Origin.y * ray.Origin.y + ray.Origin.z * ray.Origin.z - Radius * Radius; // Solve quadratic equation for _t_ values double t0 = 0.0, t1 = 0.0; if (!Util.Quadratic (A, B, C, ref t0, ref t1)) return false; // Compute intersection distance along ray if (t0 > ray.MaxT || t1 < ray.MinT) return false; double thit = t0; if (t0 < ray.MinT) { thit = t1; if (thit > ray.MaxT) return false; } // Compute sphere hit position and $\phi$ phit = ray.Apply (thit); if (phit.x == 0.0 && phit.y == 0.0) phit.x = 1E-5 * Radius; phi = Math.Atan2 (phit.y, phit.x); if (phi < 0.0) phi += 2.0 * Util.Pi; // Test sphere intersection against clipping parameters if ((zMin > -Radius && phit.z < zMin) || (zMax < Radius && phit.z > zMax) || phi > PhiMax) { if (thit == t1) return false; if (t1 > ray.MaxT) return false; thit = t1; // Compute sphere hit position and $\phi$ phit = ray.Apply (thit); if (phit.x == 0.0 && phit.y == 0.0) phit.x = 1E-5f * Radius; phi = Math.Atan2 (phit.y, phit.x); if (phi < 0.0) phi += 2.0 * Util.Pi; if ((zMin > -Radius && phit.z < zMin) || (zMax < Radius && phit.z > zMax) || phi > PhiMax) return false; } // Find parametric representation of sphere hit double u = phi / PhiMax; double theta = Math.Acos (Util.Clamp (phit.z / Radius, -1.0, 1.0)); double v = (theta - ThetaMin) / (ThetaMax - ThetaMin); // Compute sphere $\dpdu$ and $\dpdv$ double zRadius = Math.Sqrt (phit.x * phit.x + phit.y * phit.y); double invzRadius = 1.0 / zRadius; double cosphi = phit.x * invzRadius; double sinphi = phit.y * invzRadius; Vector dpdu = new Vector (-PhiMax * phit.y, PhiMax * phit.x, 0); Vector dpdv = (ThetaMax - ThetaMin) * new Vector (phit.z * cosphi, phit.z * sinphi, -Radius * Math.Sin (theta)); // Compute sphere $\dndu$ and $\dndv$ Vector d2Pduu = -PhiMax * PhiMax * new Vector (phit.x, phit.y, 0); Vector d2Pduv = (ThetaMax - ThetaMin) * phit.z * PhiMax * new Vector (-sinphi, cosphi, 0.0); Vector d2Pdvv = -(ThetaMax - ThetaMin) * (ThetaMax - ThetaMin) * new Vector (phit.x, phit.y, phit.z); // Compute coefficients for fundamental forms double E = (dpdu ^ dpdu); double F = (dpdu ^ dpdv); double G = (dpdv ^ dpdv); Vector N = (dpdu % dpdv).Normalized; double e = (N ^ d2Pduu); double f = (N ^ d2Pduv); double g = (N ^ d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients double invEGF2 = 1.0 / (E * G - F * F); Normal dndu = new Normal ((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); Normal dndv = new Normal ((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information dg = new DifferentialGeometry (ObjectToWorld.Apply (phit), ObjectToWorld.Apply (dpdu), ObjectToWorld.Apply (dpdv), ObjectToWorld.Apply (dndu), ObjectToWorld.Apply (dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 0.0005 * tHit; return true; }