Пример #1
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            var s1 = Scale.Evaluate(in si).Clamp();
            var s2 = (Spectrum.One - s1).Clamp();

            M1.ComputeScatteringFunctions(si, arena, mode, allowMultipleLobes);

            var si2 = arena.Create <SurfaceInteraction>().Initialize(in si);

            M2.ComputeScatteringFunctions(si2, arena, mode, allowMultipleLobes);

            var n1 = si.BSDF.NumberOfComponents();
            var n2 = si2.BSDF.NumberOfComponents();

            for (var i = 0; i < n1; ++i)
            {
                var collection = (IBxDFCollection)si.BSDF;
                var bxdf       = arena.Create <ScaledBxDF>().Initialize(collection[i], s1);
                collection.Set(bxdf, i);
            }

            for (var i = 0; i < n2; ++i)
            {
                var collection = (IBxDFCollection)si2.BSDF;
                var bxdf       = arena.Create <ScaledBxDF>().Initialize(collection[i], s2);
                collection.Set(bxdf, i);
            }
        }
Пример #2
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            BumpMap?.Bump(si);
            var bsdf = si.BSDF.Initialize(in si);
            var kd   = Kd.Evaluate(in si).Clamp();

            if (!kd.IsBlack())
            {
                bsdf.Add(arena.Create <LambertianReflection>().Initialize(in kd));
            }

            var ks = Ks.Evaluate(in si).Clamp();

            if (ks.IsBlack())
            {
                return;
            }

            var fresnel = arena.Create <FresnelDielectric>().Initialize(1.5f, 1f);
            var rough   = Roughness.Evaluate(in si);

            if (RemapRoughness)
            {
                rough = TrowbridgeReitzDistribution.RoughnessToAlpha(rough);
            }

            var distribution = arena.Create <TrowbridgeReitzDistribution>().Initialize(rough, rough);

            bsdf.Add(arena.Create <MicrofacetReflection>().Initialize(ks, distribution, fresnel));
        }
Пример #3
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            BumpMap?.Bump(si);

            var bsdf = si.BSDF.Initialize(in si);
            var r    = Kd.Evaluate(in si).Clamp();

            if (r.IsBlack())
            {
                return;
            }

            var sig = Clamp(0, 90, Sigma.Evaluate(in si));

            if (sig == 0f)
            {
                bsdf.Add(arena.Create <LambertianReflection>().Initialize(in r));
            }
            else
            {
                bsdf.Add(arena.Create <OrenNayar>().Initialize(in r, sig));
            }
        }
Пример #4
0
        public bool IntersectTr(Ray ray, Sampler sampler, out SurfaceInteraction isect, out Spectrum transmittance)
        {
            transmittance = Spectrum.Create(1.0);
            while (true)
            {
                bool hitSurface = Intersect(ray, out isect);
                // Accumulate beam transmittance for ray segment
                if (ray.Medium != null)
                {
                    transmittance *= ray.Medium.Tr(ray, sampler);
                }

                // Initialize next ray segment or terminate transmittance computation
                if (!hitSurface)
                {
                    return(false);
                }

                if (isect.Primitive.GetMaterial() != null)
                {
                    return(true);
                }

                ray = isect.SpawnRay(ray.Direction);
            }
        }
Пример #5
0
        public Spectrum SpecularTransmit(
            RayDifferential ray,
            SurfaceInteraction isect,
            Scene scene,
            Sampler sampler,
            int depth)
        {
            Vector3D wo = isect.Wo;
            double   pdf;
            Point3D  p    = isect.P;
            Normal3D ns   = isect.ShadingN;
            Bsdf     bsdf = isect.Bsdf;
            Spectrum f    = bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out pdf,
                                          out BxdfType sampledType, BxdfType.Transmission | BxdfType.Specular);
            Spectrum L = Spectrum.Create(0.0);

            if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0)
            {
                // Compute ray differential _rd_ for specular transmission
                RayDifferential rd = new RayDifferential(isect.SpawnRay(wi));
                if (ray.HasDifferentials)
                {
                    rd.HasDifferentials = true;
                    rd.RxOrigin         = p + isect.Dpdx.ToPoint3D();
                    rd.RyOrigin         = p + isect.Dpdy.ToPoint3D();

                    double   eta = bsdf.Eta;
                    Vector3D w   = -wo;
                    if (wo.Dot(ns) < 0.0)
                    {
                        eta = 1.0 / eta;
                    }

                    Normal3D dndx = isect.ShadingDndu * isect.Dudx +
                                    isect.ShadingDndv * isect.Dvdx;
                    Normal3D dndy = isect.ShadingDndu * isect.Dudy +
                                    isect.ShadingDndv * isect.Dvdy;

                    Vector3D dwodx = -ray.RxDirection - wo,
                             dwody = -ray.RyDirection - wo;
                    double dDNdx   = dwodx.Dot(ns) + wo.Dot(dndx);
                    double dDNdy   = dwody.Dot(ns) + wo.Dot(dndy);

                    double mu    = eta * w.Dot(ns) - wi.Dot(ns);
                    double dmudx =
                        (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdx;
                    double dmudy =
                        (eta - (eta * eta * w.Dot(ns)) / wi.Dot(ns)) * dDNdy;

                    rd.RxDirection =
                        wi + eta * dwodx - (mu * dndx + dmudx * ns).ToVector3D();
                    rd.RyDirection =
                        wi + eta * dwody - (mu * dndy + dmudy * ns).ToVector3D();
                }
                L = f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) / pdf;
            }
            return(L);
        }
Пример #6
0
        public bool Intersect(ref Ray r, ref SurfaceInteraction si)
        {
            if (_nodes.Length == 0)
            {
                return(false);
            }

            var info = _info.Value.Initialize(in r);

            while (true)
            {
                var node = _nodes[info.CurrentNodeIndex];
                if (node.Bounds.IntersectP(r, info.DirIsNegative))
                {
                    if (node.NPrimitives > 0)
                    {
                        for (var i = 0; i < node.NPrimitives; ++i)
                        {
                            if (_p[node.PrimitivesOffset + i].Intersect(ref r, ref si))
                            {
                                info.Hit = true;
                            }
                        }

                        if (info.ToVisitOffset == 0)
                        {
                            break;
                        }

                        info.CurrentNodeIndex = info.NodesToVisit[--info.ToVisitOffset];
                    }
                    else
                    {
                        if (info.DirIsNegative[node.Axis] == 1)
                        {
                            info.NodesToVisit[info.ToVisitOffset++] = info.CurrentNodeIndex + 1;
                            info.CurrentNodeIndex = node.SecondChildOffset;
                        }
                        else
                        {
                            info.NodesToVisit[info.ToVisitOffset++] = node.SecondChildOffset;
                            info.CurrentNodeIndex += 1;
                        }
                    }
                }
                else
                {
                    if (info.ToVisitOffset == 0)
                    {
                        break;
                    }

                    info.CurrentNodeIndex = info.NodesToVisit[--info.ToVisitOffset];
                }
            }

            return(info.Hit);
        }
Пример #7
0
        // BSDF Public Methods
        public Bsdf(SurfaceInteraction si, double eta = 1.0)
        {
            Eta = eta;

            _ns = si.ShadingN;
            _ng = si.N;
            _ss = si.ShadingDpdu.Normalize();
            _ts = _ns.Cross(_ss);
        }
Пример #8
0
        public void ComputeScatteringFunctions(SurfaceInteraction inter, bool allowMultipleLobes)
        {
            var r = Diffuse.Clamp();

            //TODO sigma -> Oren-Nayar

            inter.Bsdf = new BSDF(inter);
            inter.Bsdf.Add(new LambertianReflection(r));
        }
Пример #9
0
        public void ComputeScatteringFunctions(SurfaceInteraction inter, bool allowMultipleLobes)
        {
            inter.Bsdf = new BSDF(inter);

            if (!Reflectance.IsBlack())
            {
                inter.Bsdf.Add(new SpecularReflection(Reflectance, new FresnelNoOp()));
            }
        }
Пример #10
0
        public override bool Intersect(Ray ray, out float tHit, out SurfaceInteraction inter)
        {
            tHit  = 0f;
            inter = null;

            // Transform the ray from world space to object space
            var rayObj = WorldToObject * ray;

            // Compute intersections with the disk plane
            //
            // We want t such that h = o_z + t d_z
            // Hence t = (h - o_z) / d_z

            if (rayObj.D.Z == 0)
            {
                return(false);
            }

            tHit = (Height - rayObj.O.Z) / rayObj.D.Z;
            if (tHit <= 0 || tHit >= rayObj.Tmax)
            {
                return(false);
            }

            // Check if the intersection point lies in the circle
            var hitPos = rayObj.At(tHit);
            var dist2  = hitPos.X * hitPos.X + hitPos.Y * hitPos.Y;

            if (dist2 > Radius * Radius)
            {
                return(false);
            }

            // Refine the disk intersection point
            hitPos.Z = Height;

            // Compute the parametric representation of the intersection point

            var phi = Math.Atan2(hitPos.Y, hitPos.X);

            if (phi < 0)
            {
                phi += 2 * MathUtils.Pi;
            }

            var rHit = (float)Math.Sqrt(dist2);
            var dpdu = new Vector3 <float>(-MathUtils.TwoPi * hitPos.Y, MathUtils.TwoPi * hitPos.X, 0);
            var dpdv = new Vector3 <float>(hitPos.X, hitPos.Y, 0) * (-Radius / rHit);

            inter = ObjectToWorld * new SurfaceInteraction(
                hitPos, Vector3 <float> .Zero, Point2 <float> .Zero, -rayObj.D,
                dpdu, dpdv, Normal3 <float> .Zero, Normal3 <float> .Zero,
                rayObj.Time, this);

            return(true);
        }
Пример #11
0
        public bool Intersect(ref Ray r, ref SurfaceInteraction si)
        {
            if (!Shape.Intersect(in r, out var tHit, ref si))
            {
                return(false);
            }

            r.TMax       = tHit;
            si.Primitive = this;
            // TODO: Handle medium.
            return(true);
        }
Пример #12
0
        public override bool Intersect(Ray ray, out SurfaceInteraction inter)
        {
            var hit = false;

            inter = null;

            var invDir = new Vector3 <float>(1.0f / ray.D.X, 1.0f / ray.D.Y, 1.0f / ray.D.Z);

            bool[] dirIsNeg = { invDir.X < 0, invDir.Y < 0, invDir.Z < 0 };

            int toVisitOffset = 0, currentNodeIndex = 0;

            int[] nodesToVisit = new int[64];
            while (true)
            {
                var node = nodes[currentNodeIndex];

                if (node.Bounds.IntersectP(ray, out float t0, out float t1))
                {
                    // Leaf node: intersect ray with primitives
                    if (node.PrimitiveCount > 0)
                    {
                        for (var i = 0; i < node.PrimitiveCount; ++i)
                        {
                            if (allPrimitives[node.PrimitivesOffset + i].Intersect(ray, out inter))
                            {
                                hit = true;
                            }
                        }

                        if (toVisitOffset == 0)
                        {
                            break;
                        }
                        currentNodeIndex = nodesToVisit[--toVisitOffset];
                    }
                    // Interior node: process children
                    else
                    {
                        if (dirIsNeg[node.Axis])
                        {
                            nodesToVisit[toVisitOffset++] = currentNodeIndex + 1;
                            currentNodeIndex = node.SecondChildOffset;
                        }
                        else
                        {
                            nodesToVisit[toVisitOffset++] = node.SecondChildOffset;
                            currentNodeIndex = currentNodeIndex + 1;
                        }
                    }
                }
Пример #13
0
    protected void ProcessCollisions()
    {
        SurfaceInteraction newInteraction = SurfaceInteraction;

        var nulos = Collisions.Where(c => c.Key == null).ToArray();

        foreach (var nulo in nulos)
        {
            Collisions.Remove(nulo.Key);
        }

        if (Collisions.Count > 0)
        {
            float minAngle = float.MaxValue;

            foreach (Collision collision in Collisions.Values)
            {
                foreach (ContactPoint contact in collision.contacts)
                {
                    float angle = Vector3.Angle(contact.normal, Vector3.up);
                    if (angle < minAngle)
                    {
                        minAngle = angle;
                        Surface  = contact;
                    }
                }
            }

            if (minAngle >= 90F)
            {
                newInteraction = SurfaceInteraction.Floating;
            }
            else if (minAngle > slopeAngle)
            {
                newInteraction = SurfaceInteraction.Sliding;
            }
            else
            {
                newInteraction = SurfaceInteraction.Grounded;
            }
        }
        else
        {
            newInteraction = SurfaceInteraction.Floating;
        }

        if (newInteraction != SurfaceInteraction)
        {
            SurfaceInteraction = newInteraction;
        }
    }
Пример #14
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            _bumpMap?.Bump(si);
            si.BSDF.Initialize(si);
            var R = _kr.Evaluate(si).Clamp();

            if (!R.IsBlack())
            {
                si.BSDF.Add(arena.Create <SpecularReflection>().Initialize(R, arena.Create <FresnelNoOp>()));
            }
        }
Пример #15
0
        public override (Spectrum, Vector3, double, Vector3) Sample_Li(SurfaceInteraction source)
        {
            (SurfaceInteraction pShape, double pdf) = sphere.Sample(source);

            if (pdf == 0 || (pShape.Point - source.Point).LengthSquared() < Renderer.Epsilon)
            {
                return(Spectrum.ZeroSpectrum, Vector3.ZeroVector, 0, Vector3.ZeroVector);
            }

            var wi = (pShape.Point - source.Point).Normalize();
            var Li = L(pShape, -wi);

            return(Li, wi, pdf, pShape.Point);
        }
Пример #16
0
        public void ComputeScatteringFunctions(SurfaceInteraction inter, bool allowMultipleLobes)
        {
            inter.Bsdf = new BSDF(inter);

            if (!diffuse.IsBlack())
            {
                inter.Bsdf.Add(new LambertianReflection(diffuse));
            }

            if (!specular.IsBlack())
            {
                var fresnel      = new FresnelDielectric(1.5f, 1.0f);
                var distribution = new TrowbridgeReitzDistribution(roughness);
                inter.Bsdf.Add(new MicrofacetReflection(specular, distribution, fresnel));
            }
        }
Пример #17
0
        public Spectrum SpecularReflect(
            RayDifferential ray,
            SurfaceInteraction isect,
            Scene scene,
            Sampler sampler,
            int depth)
        {
            // Compute specular reflection direction _wi_ and BSDF value
            Vector3D wo   = isect.Wo;
            BxdfType type = BxdfType.Reflection | BxdfType.Specular;
            Spectrum f    = isect.Bsdf.Sample_f(wo, out Vector3D wi, sampler.Get2D(), out double pdf, out BxdfType sampledType, type);

            // Return contribution of specular reflection
            Normal3D ns = isect.ShadingN;

            if (pdf > 0.0 && !f.IsBlack() && wi.AbsDot(ns) != 0.0)
            {
                // Compute ray differential _rd_ for specular reflection
                RayDifferential rd = new RayDifferential(isect.SpawnRay(wi));
                if (ray.HasDifferentials)
                {
                    rd.HasDifferentials = true;
                    rd.RxOrigin         = isect.P + isect.Dpdx.ToPoint3D();
                    rd.RyOrigin         = isect.P + isect.Dpdy.ToPoint3D();
                    // Compute differential reflected directions
                    Normal3D dndx = isect.ShadingDndu * isect.Dudx +
                                    isect.ShadingDndv * isect.Dvdx;
                    Normal3D dndy = isect.ShadingDndu * isect.Dudy +
                                    isect.ShadingDndv * isect.Dvdy;
                    Vector3D dwodx = -ray.RxDirection - wo,
                             dwody = -ray.RyDirection - wo;
                    double dDNdx   = dwodx.Dot(ns) + wo.Dot(dndx);
                    double dDNdy   = dwody.Dot(ns) + wo.Dot(dndy);
                    rd.RxDirection =
                        wi - dwodx + 2.0 * (wo.Dot(ns) * dndx + dDNdx * ns).ToVector3D();
                    rd.RyDirection =
                        wi - dwody + 2.0 * (wo.Dot(ns) * dndy + dDNdy * ns).ToVector3D();
                }
                return(f * Li(rd, scene, sampler, depth + 1) * wi.AbsDot(ns) /
                       pdf);
            }
            else
            {
                return(Spectrum.Create(0.0));
            }
        }
Пример #18
0
        private Spectrum SpecularReflect(RayDifferential ray, SurfaceInteraction inter, Scene scene, Camera camera, Sampler sampler, int depth)
        {
            // Sample a direction with the BSDF
            var type = BxDFType.Reflection | BxDFType.Specular;
            var f    = inter.Bsdf.Sample_f(inter.Wo, out Vector3 <float> wi, sampler.Get2D(), out float pdf, type, out BxDF.BxDFType sampledType);

            // Add the contribution of this reflection
            if (pdf > 0 && !f.IsBlack() && Vector3 <float> .AbsDot(wi, inter.Shading.N) != 0)
            {
                var newRay = inter.SpawnRay(wi).ToDiff();

                if (ray.HasDifferentials)
                {
                    // TODO
                }

                return(f * Li(newRay, scene, camera, sampler, depth + 1) * Vector3 <float> .AbsDot(wi, inter.Shading.N) * (1.0f / pdf));
            }

            return(Spectrum.Zero);
        }
Пример #19
0
        public static void Bump(this ITexture2 <float> d, SurfaceInteraction si)
        {
            var displace = d.Evaluate(si);

            var du = 0.5f * Abs(si.Dudx) + Abs(si.Dudy);

            // Create small du if no differential available.
            if (du == 0f)
            {
                du = 0.0005f;
            }

            si.P  += du * si.ShadingGeometry.Dpdu;
            si.UV += new Vector2(du, 0f);
            si.N   = ((Normal)Vector.Cross(si.ShadingGeometry.Dpdu, si.ShadingGeometry.Dpdv) + du * si.Dndu).Normalize();
            var uDisplace = d.Evaluate(si);

            var dv = 0.5f * Abs(si.Dvdx) + Abs(si.Dvdy);

            // Create small dv if no differential available.
            if (dv == 0f)
            {
                dv = 0.0005f;
            }

            si.P  += dv * si.ShadingGeometry.Dpdv;
            si.UV += new Vector2(0f, dv);
            si.N   = ((Normal)Vector.Cross(si.ShadingGeometry.Dpdu, si.ShadingGeometry.Dpdv) + dv * si.Dndv).Normalize();
            var vDisplace = d.Evaluate(si);

            var dpdu = si.ShadingGeometry.Dpdu +
                       (uDisplace - displace) / du * (Vector)si.ShadingGeometry.N +
                       displace * (Vector)si.ShadingGeometry.Dndu;

            var dpdv = si.ShadingGeometry.Dpdv +
                       (vDisplace - displace) / dv * (Vector)si.ShadingGeometry.N +
                       displace * (Vector)si.ShadingGeometry.Dndv;

            si.SetShadingGeometry(dpdu, dpdv, si.ShadingGeometry.Dndu, si.ShadingGeometry.Dndv, false);
        }
Пример #20
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            _bumpMap?.Bump(si);

            si.BSDF.Initialize(si);

            var uRough = _uRoughness?.Evaluate(si) ?? _roughness.Evaluate(si);
            var vRough = _vRoughness?.Evaluate(si) ?? _roughness.Evaluate(si);

            if (_remapRoughness)
            {
                uRough = TrowbridgeReitzDistribution.RoughnessToAlpha(uRough);
                vRough = TrowbridgeReitzDistribution.RoughnessToAlpha(vRough);
            }

            var fr = arena.Create <FresnelConductor>().Initialize(Spectrum.One, _eta.Evaluate(si), _k.Evaluate(si));

            var dist = arena.Create <TrowbridgeReitzDistribution>().Initialize(uRough, vRough);

            si.BSDF.Add(arena.Create <MicrofacetReflection>().Initialize(Spectrum.One, dist, fr));
        }
Пример #21
0
 /// <inheritdoc />
 public override void ComputeScatteringFunctions(SurfaceInteraction isect, TransportMode mode, bool allowMultipleLobes)
 {
     throw new InvalidOperationException("Aggregate.ComputeScatteringFunctions() method called; should have gone to GeometricPrimitive");
 }
Пример #22
0
 public abstract bool Intersect(
     Ray ray,
     out double tHit,
     out SurfaceInteraction isect,
     bool testAlphaTexture = true);
Пример #23
0
        public void ComputeScatteringFunctions(SurfaceInteraction si,
                                               IObjectArena arena,
                                               TransportMode mode,
                                               bool allowMultipleLobes)
        {
            BumpMap?.Bump(si);

            si.BSDF.Initialize(si);

            // Diffuse
            var c = Color.Evaluate(si).Clamp();
            var metallicWeight = Metallic.Evaluate(si);
            var e             = Eta.Evaluate(si);
            var strans        = SpecTrans.Evaluate(si);
            var diffuseWeight = (1f - metallicWeight) * (1f - strans);
            var dt            = DiffTrans.Evaluate(si) / 2f;
            var rough         = Roughness.Evaluate(si);
            var lum           = c.YComponent();
            var Ctint         = lum > 0f ? c / lum : Spectrum.One;

            if (diffuseWeight > 0f)
            {
                if (IsThin)
                {
                    var flat = Flatness.Evaluate(si);
                    si.BSDF.Add(arena.Create <DisneyDiffuse>().Initialize(diffuseWeight * (1f - flat) * (1 - dt) * c));
                    si.BSDF.Add(arena.Create <DisneyFakeSS>().Initialize(diffuseWeight * flat * (1f - dt) * c, rough));
                }
                else
                {
                    var sd = ScatterDistance.Evaluate(si);
                    if (sd.IsBlack())
                    {
                        si.BSDF.Add(arena.Create <DisneyDiffuse>().Initialize(diffuseWeight * c));
                    }
                    else
                    {
                        // The line below was the original code but produces some odd results.
                        si.BSDF.Add(arena.Create <SpecularTransmission>().Initialize(Spectrum.One, 1f, e, mode));
                        si.BSSRDF = arena.Create <DisneyBSSRDF>().Initialize(diffuseWeight * c, sd, si, e, this, mode);
                    }
                }

                // Retro-reflection.
                si.BSDF.Add(arena.Create <DisneyRetro>().Initialize(diffuseWeight * c, rough));

                // Sheen
                var sheenWeight = Sheen.Evaluate(si);
                if (sheenWeight > 0f)
                {
                    var stint  = SheenTint.Evaluate(si);
                    var Csheen = Spectrum.Lerp(Spectrum.One, Ctint, stint);
                    si.BSDF.Add(arena.Create <DisneySheen>().Initialize(diffuseWeight * sheenWeight * Csheen));
                }
            }

            // Microfacet distribution
            var aspect = Sqrt(1f - Anisotropic.Evaluate(si) * 0.9f);
            var ax     = Max(0.001f, Sqr(rough) / aspect);
            var ay     = Max(0.001f, Sqr(rough) * aspect);
            var dist   = arena.Create <DisneyMicrofacetDistribution>().Initialize(ax, ay);

            // Specular = Trowbridge-Reitz with modified Fresnel function.
            var specTint = SpecularTint.Evaluate(si);
            var Cspec0   = Spectrum.Lerp(SchlickR0FromEta(e) * Spectrum.Lerp(Spectrum.One, Ctint, specTint), c,
                                         metallicWeight);
            var fresnel = arena.Create <DisneyFresnel>().Initialize(Cspec0, metallicWeight, e);

            si.BSDF.Add(arena.Create <MicrofacetReflection>().Initialize(c, dist, fresnel));

            // Clearcoat
            var cc = Clearcoat.Evaluate(si);

            if (cc > 0f)
            {
                si.BSDF.Add(arena.Create <DisneyClearcoat>()
                            .Initialize(cc, Lerp(0.1f, 0.001f, ClearcoatGloss.Evaluate(si))));
            }

            // BTDF
            if (strans > 0f)
            {
                // Walter et al's model, with the provided transmissive term scaled
                // by sqrt(color), so that after two refractions, we're back to the
                // provided color.
                var T = strans * c.Sqrt();
                if (IsThin)
                {
                    var rScaled    = (0.65f * e - 0.35f) * rough;
                    var atx        = Max(0.001f, Sqr(rScaled) / aspect);
                    var aty        = Max(0.001f, Sqr(rScaled) * aspect);
                    var scaledDist = arena.Create <TrowbridgeReitzDistribution>().Initialize(atx, aty);
                    si.BSDF.Add(arena.Create <MicrofacetTransmission>().Initialize(T, scaledDist, 1f, e, mode));
                }
                else
                {
                    si.BSDF.Add(arena.Create <MicrofacetTransmission>().Initialize(T, dist, 1f, e, mode));
                }
            }

            if (IsThin)
            {
                si.BSDF.Add(arena.Create <LambertianTransmission>().Initialize(dt * c));
            }
        }
Пример #24
0
 public override double Pdf_Li(SurfaceInteraction si, Vector3 wi)
 {
     return(sphere.Pdf(si, wi));
 }
Пример #25
0
 public void ComputeScatteringFunctions(SurfaceInteraction surfaceInteraction,
                                        IObjectArena arena,
                                        TransportMode mode,
                                        in bool allowMultipleLobes)
Пример #26
0
        public override bool Intersect(Ray ray, out float t, out SurfaceInteraction inter)
        {
            t     = 0.0f;
            inter = null;

            // Transform the ray from world space to object space
            var rayObj = WorldToObject * ray;

            // The implicit representation of the sphere is:
            //
            //            x² + y² + z² - r² = 0
            //
            // Subtituting the parametric representation of the ray:
            //
            //  (ox + t dx)² + (oy + t dy)² + (oz + t dz)² = r²
            //
            // Or, with the following coefficients:
            //
            //              a t² + b t + c = 0

            var a = rayObj.D.X * rayObj.D.X + rayObj.D.Y * rayObj.D.Y + rayObj.D.Z * rayObj.D.Z;
            var b = 2 * (rayObj.D.X * rayObj.O.X + rayObj.D.Y * rayObj.O.Y + rayObj.D.Z * rayObj.O.Z);
            var c = rayObj.O.X * rayObj.O.X + rayObj.O.Y * rayObj.O.Y + rayObj.O.Z * rayObj.O.Z - Radius * Radius;

            // Solve the quadration equation for t
            if (!MathUtils.Quadratic(a, b, c, out float t0, out float t1))
            {
                return(false);
            }

            // Look for the nearest intersection

            if (t0 > rayObj.Tmax || t1 <= 0)
            {
                return(false);
            }

            float tHit = t0;

            if (tHit <= 0)
            {
                tHit = t1;
                if (tHit > rayObj.Tmax)
                {
                    return(false);
                }
            }
            t = tHit;

            // Initialize the interaction parameters

            var hitPos = rayObj.At(tHit);

            var hitPhi = MathF.Atan2(hitPos.Y, hitPos.X); // Transform the hit point to polar coordinates

            if (hitPhi < 0)
            {
                hitPhi += 2 * MathF.PI;
            }
            var theta = MathF.Acos(MathUtils.Clamp(hitPos.Z / Radius, -1, 1));

            //var u = hitPhi / (2 * Math.PI);
            //var v = theta / Math.PI;

            var zRadius    = MathF.Sqrt(hitPos.X * hitPos.X + hitPos.Y * hitPos.Y);
            var invZRadius = 1.0f / zRadius;
            var cosPhi     = hitPos.X * invZRadius;
            var sinPhi     = hitPos.Y * invZRadius;
            var dpdu       = new Vector3 <float>(-MathUtils.TwoPi * hitPos.Y, MathUtils.TwoPi * hitPos.X, 0);
            var dpdv       = new Vector3 <float>(hitPos.Z * cosPhi, hitPos.Z * sinPhi, -Radius * MathF.Sin(theta)) * -MathUtils.Pi;

            inter = ObjectToWorld * new SurfaceInteraction(
                hitPos, Vector3 <float> .Zero, Point2 <float> .Zero, -rayObj.D,
                dpdu, dpdv, Normal3 <float> .Zero, Normal3 <float> .Zero,
                rayObj.Time, this);

            return(true);
        }
Пример #27
0
 public abstract bool Intersect(Ray r, out SurfaceInteraction isect);
Пример #28
0
 public bool Intersect(Ray ray, out SurfaceInteraction isect)
 {
     // ++nIntersectionTests;
     // DCHECK_NE(ray.d, Vector3f(0, 0, 0));
     return(_aggregate.Intersect(ray, out isect));
 }
Пример #29
0
        /// <inheritdoc />
        public override bool Intersect(Ray ray, out SurfaceInteraction isect)
        {
            isect = null;

            if (nodes == null)
            {
                return(false);
            }

            //ProfilePhase p(Prof::AccelIntersect);
            bool     hit    = false;
            Vector3D invDir = new Vector3D(1.0 / ray.Direction.X, 1.0 / ray.Direction.Y, 1.0 / ray.Direction.Z);

            bool[] dirIsNeg = new bool[3] {
                invDir.X < 0, invDir.Y < 0, invDir.Z < 0
            };
            // Follow ray through BVH nodes to find primitive intersections
            int toVisitOffset = 0, currentNodeIndex = 0;

            int[] nodesToVisit = new int[64];
            while (true)
            {
                LinearBVHNode node = nodes[currentNodeIndex];
                // Check ray against BVH node
                if (node.bounds.IntersectP(ray, invDir, dirIsNeg))
                {
                    if (node.nPrimitives > 0)
                    {
                        // Intersect ray with primitives in leaf BVH node
                        for (int i = 0; i < node.nPrimitives; ++i)
                        {
                            if (primitives[node.primitivesOffset + i].Intersect(
                                    ray, out isect))
                            {
                                hit = true;
                            }
                        }

                        if (toVisitOffset == 0)
                        {
                            break;
                        }

                        currentNodeIndex = nodesToVisit[--toVisitOffset];
                    }
                    else
                    {
                        // Put far BVH node on _nodesToVisit_ stack, advance to near
                        // node
                        if (dirIsNeg[node.axis])
                        {
                            nodesToVisit[toVisitOffset++] = currentNodeIndex + 1;
                            currentNodeIndex = node.secondChildOffset;
                        }
                        else
                        {
                            nodesToVisit[toVisitOffset++] = node.secondChildOffset;
                            currentNodeIndex = currentNodeIndex + 1;
                        }
                    }
                }
                else
                {
                    if (toVisitOffset == 0)
                    {
                        break;
                    }

                    currentNodeIndex = nodesToVisit[--toVisitOffset];
                }
            }
            return(hit);
        }
Пример #30
0
 public abstract void ComputeScatteringFunctions(
     SurfaceInteraction isect,
     TransportMode mode,
     bool allowMultipleLobes);