public static float SinPhi(ref Vector w) { float sintheta = SinTheta(ref w); if (sintheta == 0.0f) return 0.0f; return MathUtility.Clamp(w.Y / sintheta, -1.0f, 1.0f); }
public Spectrum Le(Vector wo) { var areaLight = _primitive.GetAreaLight(); return (areaLight != null) ? areaLight.L(_dg.Point, _dg.Normal, wo) : Spectrum.CreateBlack(); }
public override Spectrum F(Vector wo, Vector wi) { float sinthetai = ReflectionUtilities.SinTheta(ref wi); float sinthetao = ReflectionUtilities.SinTheta(ref wo); // Compute cosine term of Oren-Nayar model float maxcos = 0.0f; if (sinthetai > 1e-4 && sinthetao > 1e-4) { float sinphii = ReflectionUtilities.SinPhi(ref wi); float cosphii = ReflectionUtilities.CosPhi(ref wi); float sinphio = ReflectionUtilities.SinPhi(ref wo); float cosphio = ReflectionUtilities.CosPhi(ref wo); float dcos = cosphii * cosphio + sinphii * sinphio; maxcos = Math.Max(0.0f, dcos); } // Compute sine and tangent terms of Oren-Nayar model float sinalpha, tanbeta; if (ReflectionUtilities.AbsCosTheta(ref wi) > ReflectionUtilities.AbsCosTheta(ref wo)) { sinalpha = sinthetao; tanbeta = sinthetai / ReflectionUtilities.AbsCosTheta(ref wi); } else { sinalpha = sinthetai; tanbeta = sinthetao / ReflectionUtilities.AbsCosTheta(ref wo); } return _reflectance * MathUtility.InvPi * (_a + _b * maxcos * sinalpha * tanbeta); }
public static Vector CosineSampleHemisphere(float u1, float u2) { var ret = new Vector(); ConcentricSampleDisk(u1, u2, out ret.X, out ret.Y); ret.Z = MathUtility.Sqrt(Math.Max(0.0f, 1.0f - ret.X * ret.X - ret.Y * ret.Y)); return ret; }
public Vector TransformVector(ref Vector v) { float x = v.X, y = v.Y, z = v.Z; return new Vector( _m.M[0, 0] * x + _m.M[0, 1] * y + _m.M[0, 2] * z, _m.M[1, 0] * x + _m.M[1, 1] * y + _m.M[1, 2] * z, _m.M[2, 0] * x + _m.M[2, 1] * y + _m.M[2, 2] * z); }
public virtual Spectrum SampleF(Vector wo, out Vector wi, float u1, float u2, out float pdf) { // Cosine-sample the hemisphere, flipping the direction if necessary wi = MonteCarloUtilities.CosineSampleHemisphere(u1, u2); if (wo.Z < 0.0f) wi.Z *= -1.0f; pdf = Pdf(wo, wi); return F(wo, wi); }
public static Vector Cross(Normal v1, Vector v2) { float v1x = v1.X, v1y = v1.Y, v1z = v1.Z; float v2x = v2.X, v2y = v2.Y, v2z = v2.Z; return new Vector( (v1y * v2z) - (v1z * v2y), (v1z * v2x) - (v1x * v2z), (v1x * v2y) - (v1y * v2x)); }
public override Spectrum SampleL(Point p, float pEpsilon, LightSample ls, float time, out Vector wi, out float pdf, out VisibilityTester vis) { wi = _direction; pdf = 1.0f; vis = new VisibilityTester(p, pEpsilon, wi, time); return _radiance; }
public override Spectrum SampleL( Point p, float pEpsilon, LightSample ls, float time, out Vector wi, out float pdf, out VisibilityTester vis) { wi = Vector.Normalize(_lightPosition - p); pdf = 1.0f; vis = new VisibilityTester(p, pEpsilon, _lightPosition, 0.0f, time); return _intensity / Point.DistanceSquared(_lightPosition, p); }
public Bsdf(DifferentialGeometry dgShading, Normal nGeom, float eta = 1.0f) { _dgShading = dgShading; _ng = nGeom; _eta = eta; _nn = dgShading.Normal; _sn = Vector.Normalize(dgShading.DpDu); _tn = Normal.Cross(_nn, _sn); _bxdfs = new List<Bxdf>(); }
public override bool TryIntersect(Ray r, out float tHit, out float rayEpsilon, out DifferentialGeometry dg) { tHit = float.NegativeInfinity; rayEpsilon = 0.0f; dg = null; float phi; Point phit; float thit; if (!DoIntersection(r, out phi, out phit, out thit)) return false; // Find parametric representation of cylinder hit float u = phi / _phiMax; float v = (phit.Z - _zMin) / (_zMax - _zMin); // Compute cylinder $\dpdu$ and $\dpdv$ var dpdu = new Vector(-_phiMax * phit.Y, _phiMax * phit.X, 0); var dpdv = new Vector(0, 0, _zMax - _zMin); // Compute cylinder $\dndu$ and $\dndv$ Vector d2Pduu = -_phiMax * _phiMax * new Vector(phit.X, phit.Y, 0); Vector d2Pduv = Vector.Zero, d2Pdvv = Vector.Zero; // Compute coefficients for fundamental forms float E = Vector.Dot(dpdu, dpdu); float F = Vector.Dot(dpdu, dpdv); float G = Vector.Dot(dpdv, dpdv); Vector N = Vector.Normalize(Vector.Cross(dpdu, dpdv)); float e = Vector.Dot(N, d2Pduu); float f = Vector.Dot(N, d2Pduv); float g = Vector.Dot(N, d2Pdvv); // Compute $\dndu$ and $\dndv$ from fundamental form coefficients float invEGF2 = 1.0f / (E * G - F * F); var dndu = (Normal) ((f * F - e * G) * invEGF2 * dpdu + (e * F - f * E) * invEGF2 * dpdv); var dndv = (Normal) ((g * F - f * G) * invEGF2 * dpdu + (f * F - g * E) * invEGF2 * dpdv); // Initialize _DifferentialGeometry_ from parametric information var o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.TransformPoint(ref phit), o2w.TransformVector(ref dpdu), o2w.TransformVector(ref dpdv), o2w.TransformNormal(ref dndu), o2w.TransformNormal(ref dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4f * tHit; return true; }
public PerspectiveCamera( AnimatedTransform cameraToWorld, float[] screenWindow, float shutterOpen, float shutterClose, float lensRadius, float focalDistance, float fieldOfView, Film film) : base(cameraToWorld, Transform.Perspective(fieldOfView, 1e-2f, 1000.0f), screenWindow, shutterOpen, shutterClose, lensRadius, focalDistance, film) { // Compute differential changes in origin for perspective camera rays _dxCamera = RasterToCamera.TransformPoint(new Point(1, 0, 0)) - RasterToCamera.TransformPoint(new Point(0, 0, 0)); _dyCamera = RasterToCamera.TransformPoint(new Point(0, 1, 0)) - RasterToCamera.TransformPoint(new Point(0, 0, 0)); }
public virtual Spectrum Rho(Vector wo, int numSamples, float[] samples) { Spectrum r = Spectrum.CreateBlack(); for (int i = 0; i < numSamples; ++i) { // Estimate one term of $\rho_\roman{hd}$ Vector wi; float pdf; Spectrum f = SampleF(wo, out wi, samples[2 * i], samples[2 * i + 1], out pdf); if (pdf > 0.0f) r += f * ReflectionUtilities.AbsCosTheta(ref wi) / pdf; } return r / numSamples; }
public virtual float Pdf(Point p, Vector wi) { // Intersect sample ray with area light geometry var ray = new Ray(p, wi, 1e-3f); ray.Depth = -1; // temporary hack to ignore alpha mask float thit, rayEpsilon; DifferentialGeometry dgLight; if (!TryIntersect(ray, out thit, out rayEpsilon, out dgLight)) return 0.0f; // Convert light sample weight to solid angle measure float pdf = Point.DistanceSquared(p, ray.Evaluate(thit)) / (Normal.AbsDot(dgLight.Normal, -wi) * Area); if (float.IsInfinity(pdf)) pdf = 0.0f; return pdf; }
public DifferentialGeometry(Point point, Vector dpdu, Vector dpdv, Normal dndu, Normal dndv, float u, float v, Shape shape) { Point = point; Normal = (Normal) Vector.Normalize(Vector.Cross(dpdu, dpdv)); DpDu = dpdu; DpDv = dpdv; DnDu = dndu; DnDv = dndv; U = u; V = v; Shape = shape; if (shape != null && shape.ReverseOrientation != shape.TransformSwapsHandedness) Normal *= -1.0f; }
private static void Decompose(Matrix4x4 m, out Vector t, out Quaternion r, out Matrix4x4 s) { // Extract translation _T_ from transformation matrix t.X = m.M[0, 3]; t.Y = m.M[1, 3]; t.Z = m.M[2, 3]; // Compute new transformation matrix _M_ without translation Matrix4x4 M = m.Clone(); for (int i = 0; i < 3; ++i) M.M[i, 3] = M.M[3, i] = 0.0f; M.M[3, 3] = 1.0f; // Extract rotation _R_ from transformation matrix float norm; int count = 0; Matrix4x4 R = M.Clone(); do { // Compute next matrix _Rnext_ in series var Rnext = new Matrix4x4(); var Rit = Matrix4x4.Invert(Matrix4x4.Transpose(R)); for (int i = 0; i < 4; ++i) for (int j = 0; j < 4; ++j) Rnext.M[i, j] = 0.5f * (R.M[i, j] + Rit.M[i, j]); // Compute norm of difference between _R_ and _Rnext_ norm = 0.0f; for (int i = 0; i < 3; ++i) { float n = Math.Abs(R.M[i, 0] - Rnext.M[i, 0]) + Math.Abs(R.M[i, 1] - Rnext.M[i, 1]) + Math.Abs(R.M[i, 2] - Rnext.M[i, 2]); norm = Math.Max(norm, n); } R = Rnext; } while (++count < 100 && norm > .0001f); // XXX TODO FIXME deal with flip... r = (Quaternion) new Transform(R); // Compute scale _S_ using rotation and original matrix s = Matrix4x4.Mul(Matrix4x4.Invert(R), M); }
public override bool TryIntersect(Ray r, out float tHit, out float rayEpsilon, out DifferentialGeometry dg) { tHit = float.NegativeInfinity; rayEpsilon = 0.0f; dg = null; float phi, dist2, thit; Point phit; if (!DoIntersection(r, out phi, out dist2, out phit, out thit)) return false; // Find parametric representation of disk hit float u = phi / _phiMax; float oneMinusV = ((MathUtility.Sqrt(dist2) - _innerRadius) / (_radius - _innerRadius)); float invOneMinusV = (oneMinusV > 0.0f) ? (1.0f / oneMinusV) : 0.0f; float v = 1.0f - oneMinusV; var dpdu = new Vector(-_phiMax * phit.Y, _phiMax * phit.X, 0.0f); var dpdv = new Vector(-phit.X * invOneMinusV, -phit.Y * invOneMinusV, 0.0f); dpdu *= _phiMax * MathUtility.InvTwoPi; dpdv *= (_radius - _innerRadius) / _radius; Normal dndu = Normal.Zero, dndv = Normal.Zero; // Initialize _DifferentialGeometry_ from parametric information var o2w = ObjectToWorld; dg = new DifferentialGeometry(o2w.TransformPoint(ref phit), o2w.TransformVector(ref dpdu), o2w.TransformVector(ref dpdv), o2w.TransformNormal(ref dndu), o2w.TransformNormal(ref dndv), u, v, this); // Update _tHit_ for quadric intersection tHit = thit; // Compute _rayEpsilon_ for quadric intersection rayEpsilon = 5e-4f * tHit; return true; }
public override Spectrum L(Point p, Normal n, Vector w) { throw new System.NotImplementedException(); }
public override float Pdf(Point p, Vector wi) { throw new System.NotImplementedException(); }
public override Spectrum SampleL(Point p, float pEpsilon, LightSample ls, float time, out Vector wi, out float pdf, out VisibilityTester vis) { throw new System.NotImplementedException(); }
public static Normal FaceForward(Normal n, Vector v) { return (Dot(n, v) < 0.0f) ? -n : n; }
public static float Dot(Vector v1, Normal v2) { return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z; }
public static float Dot(Normal n1, Vector n2) { return n1.X * n2.X + n1.Y * n2.Y + n1.Z * n2.Z; }
public static Vector SphericalDirection( float sintheta, float costheta, float phi, Vector x, Vector y, Vector z) { return sintheta * MathUtility.Cos(phi) * x + sintheta * MathUtility.Sin(phi) * y + costheta * z; }
public void ComputeDifferentials(RayDifferential ray) { if (ray.HasDifferentials) { // Estimate screen space change in $\pt{}$ and $(u,v)$ // Compute auxiliary intersection points with plane float d = -Normal.Dot(Normal, new Vector(Point.X, Point.Y, Point.Z)); var rxv = new Vector(ray.RxOrigin.X, ray.RxOrigin.Y, ray.RxOrigin.Z); float tx = -(Normal.Dot(Normal, rxv) + d) / Normal.Dot(Normal, ray.RxDirection); if (float.IsNaN(tx)) throw new InvalidOperationException(); Point px = ray.RxOrigin + tx * ray.RxDirection; var ryv = new Vector(ray.RyOrigin.X, ray.RyOrigin.Y, ray.RyOrigin.Z); float ty = -(Normal.Dot(Normal, ryv) + d) / Normal.Dot(Normal, ray.RyDirection); if (float.IsNaN(ty)) throw new InvalidOperationException(); Point py = ray.RyOrigin + ty * ray.RyDirection; DpDx = px - Point; DpDy = py - Point; // Compute $(u,v)$ offsets at auxiliary points // Initialize _A_, _Bx_, and _By_ matrices for offset computation var A = new float[2, 2]; var Bx = new float[2]; var By = new float[2]; var axes = new int[2]; if (Math.Abs(Normal.X) > Math.Abs(Normal.Y) && Math.Abs(Normal.X) > Math.Abs(Normal.Z)) { axes[0] = 1; axes[1] = 2; } else if (Math.Abs(Normal.Y) > Math.Abs(Normal.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]] - Point[axes[0]]; Bx[1] = px[axes[1]] - Point[axes[1]]; By[0] = py[axes[0]] - Point[axes[0]]; By[1] = py[axes[1]] - Point[axes[1]]; if (!Matrix4x4.SolveLinearSystem2x2(A, Bx, out DuDx, out DvDx)) { DuDx = 0.0f; DvDx = 0.0f; } if (!Matrix4x4.SolveLinearSystem2x2(A, By, out DuDy, out DvDy)) { DuDy = 0.0f; DvDy = 0.0f; } } else { DuDx = DvDx = 0.0f; DuDy = DvDy = 0.0f; DpDx = DpDy = Vector.Zero; } }
public static float SphericalTheta(Vector v) { return MathUtility.Acos(MathUtility.Clamp(v.Z, -1.0f, 1.0f)); }
public static Vector UniformSampleCone( float u1, float u2, float costhetamax, ref Vector x, ref Vector y, ref Vector z) { float costheta = MathUtility.Lerp(u1, costhetamax, 1.0f); float sintheta = MathUtility.Sqrt(1.0f - costheta * costheta); float phi = u2 * 2.0f * MathUtility.Pi; return MathUtility.Cos(phi) * sintheta * x + MathUtility.Sin(phi) * sintheta * y + costheta * z; }
public Vector TransformVector(float time, Vector v) { if (!_actuallyAnimated || time <= _startTime) return _startTransform.TransformVector(ref v); if (time >= _endTime) return _endTransform.TransformVector(ref v); Transform t; Interpolate(time, out t); return t.TransformVector(ref v); }
public static float AbsDot(Normal v1, Vector v2) { return Math.Abs(Dot(v1, v2)); }
public static float SphericalPhi(Vector v) { float p = MathUtility.Atan2(v.Y, v.X); return (p < 0.0f) ? p + 2.0f * MathUtility.Pi : p; }