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 Spectrum SampleL(Point p, double pEpsilon, LightSample ls, double time, ref Vector wi, ref double pdf, ref VisibilityTester visibility) { Normal ns = new Normal (); Point ps = ShapeSet.Sample (p, ls, ref ns); wi = (ps - p).Normalized; pdf = ShapeSet.Pdf (p, wi); visibility.SetSegment (p, pEpsilon, ps, 0.001, time); Spectrum Ls = L (ps, ns, -wi); return Ls; }
public override Spectrum SampleL(Scene scene, LightSample ls, double u1, double u2, double time, ref Ray ray, ref Normal Ns, ref double pdf) { Point org = ShapeSet.Sample (ls, ref Ns); Vector dir = MonteCarlo.UniformSampleSphere (u1, u2); if ((dir ^ Ns) < 0.0) dir *= -1.0; ray = new Ray (org, dir, 0.001, double.PositiveInfinity, time); pdf = ShapeSet.Pdf (org) * Util.InvTwoPi; Spectrum Ls = L (org, Ns, dir); return Ls; }
public DifferentialGeometry() { p = new Point (); n = new Normal (); dpdu = new Vector (); dpdv = new Vector (); dndu = new Normal (); dndv = new Normal (); dpdx = new Vector (); dpdy = new Vector (); u = v = 0.0; dudx = dudy = dvdx = dvdy = 0.0; Shape = null; }
public DifferentialGeometry(Point p, Vector dpdu, Vector dpdv, Normal dndu, Normal dndv, double u, double v, IShape shape) { this.p = new Point (p); this.dpdu = new Vector (dpdu); this.dpdv = new Vector (dpdv); this.dndu = new Normal (dndu); this.dndv = new Normal (dndv); this.n = new Normal ((dpdu % dpdv).Normalized); this.u = u; this.v = v; dudx = dvdx = dudy = dvdy = 0.0; this.Shape = shape; if (shape != null && (shape.ReverseOrientation ^ shape.TransformSwapsHandedness)) n *= -1.0; }
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 Spectrum SampleL(Scene scene, LightSample ls, double u1, double u2, double time, ref Ray ray, ref Normal Ns, ref double pdf) { // Choose point on disk oriented toward infinite light direction Point worldCenter; double worldRadius; scene.WorldBound.BoundingSphere (out worldCenter, out worldRadius); Vector v1, v2; Util.CoordinateSystem (LightDir, out v1, out v2); double d1 = 0.0, d2 = 0.0; MonteCarlo.ConcentricSampleDisk (ls.uPos[0], ls.uPos[1], ref d1, ref d2); Point Pdisk = worldCenter + worldRadius * (d1 * v1 + d2 * v2); // Set ray origin and direction for infinite light ray ray = new Ray (Pdisk + worldRadius * LightDir, -LightDir, 0.0, double.PositiveInfinity, time); Ns = new Normal (ray.Direction); pdf = 1.0 / (Util.Pi * worldRadius * worldRadius); return L; }
public TriangleMesh(Transform objectToWorld, Transform worldToObject, bool ro, int ntris, int nverts, int[] vptr, Point[] p, Normal[] n, Vector[] s, double[] uv, ITexture<double> atex) : base(objectToWorld, worldToObject, ro) { NumberOfTriangles = ntris; NumberOfVertices = nverts; AlphaTexture = atex; /*VertexIndices = new int[3 * NumberOfTriangles]; vptr.CopyTo (VertexIndices, 0);*/ VertexIndices = vptr; /*if (uv != null) { Uvs = new double[2 * NumberOfVertices]; uv.CopyTo (Uvs, 0); } else Uvs = null;*/ Points = new Point[NumberOfVertices]; Normals = n; Vectors = s; Uvs = uv; /*if (n != null) { Normals = new Normal[NumberOfVertices]; n.CopyTo (Normals, 0); } else Normals = null; if (s != null) { Vectors = new Vector[NumberOfVertices]; s.CopyTo (Vectors, 0); } else Vectors = null;*/ for (int i = 0; i < NumberOfVertices; ++i) Points[i] = objectToWorld.Apply (p[i]); }
public Point Sample(LightSample lightSample, ref Normal Ns) { double temp = 0.0; int sn = AreaDistribution.SampleDiscrete (lightSample.uComponent, ref temp); return Shapes[sn].Sample (lightSample.uPos[0], lightSample.uPos[1], ref Ns); }
public abstract Spectrum L(Point p, Normal n, Vector w);
public BSDF(DifferentialGeometry dgs, Normal ngeom) : this(dgs, ngeom, 1.0) { }
public virtual Point Sample(double u1, double u2, ref Normal Ns) { return new Point (); }
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 Normal(Normal vec) : this(vec.x, vec.y, vec.z) { }
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 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 Spectrum SampleL(Scene scene, LightSample ls, double u1, double u2, double time, ref Ray ray, ref Normal Ns, ref double pdf);
public static double AbsDot(Vector a, Normal b) { return Math.Abs (a ^ b); }
public static double AbsDot(Normal a, Vector b) { return Math.Abs (a ^ b); }
public static Normal FaceForward(Normal a, Normal b) { return ((a ^ b) < 0.0) ? -a : a; }
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; }
public override Spectrum L(Point p, Normal n, Vector w) { return (n ^ w) > 0.0 ? Lemit : new Spectrum (); }
public virtual Point Sample(Point p, double u1, double u2, ref Normal Ns) { return Sample (u1, u2, ref Ns); }
public override Point Sample(double u1, double u2, ref Normal Ns) { Point p1 = Mesh.Points[Vertices[0]]; Point p2 = Mesh.Points[Vertices[1]]; Point p3 = Mesh.Points[Vertices[2]]; double b1, b2; MonteCarlo.UniformSampleTriangle (u1, u2, out b1, out b2); Point p = b1 * p1 + b2 * p2 + (1.0 - b1 - b2) * p3; Normal n = new Normal ((p2 - p1) % (p3 - p1)); Ns = n.Normalized; if (ReverseOrientation) Ns *= -1.0; return p; }
public override Point Sample(double u1, double u2, ref Normal Ns) { Point p = new Point () + Radius * MonteCarlo.UniformSampleSphere (u1, u2); Ns = ObjectToWorld.Apply (new Normal (p.x, p.y, p.z)).Normalized; if (ReverseOrientation) Ns *= -1.0; return ObjectToWorld.Apply (p); }
public Vector(Normal vec) : this(vec.x, vec.y, vec.z) { }
public override Point Sample(double u1, double u2, ref Normal Ns) { Point p = new Point (); MonteCarlo.ConcentricSampleDisk (u1, u2, ref p.x, ref p.y); p.x *= Radius; p.y *= Radius; p.z = Height; Ns = ObjectToWorld.Apply (new Normal (0, 0, 1)).Normalized; if (ReverseOrientation) Ns *= -1.0; return ObjectToWorld.Apply (p); }