Ejemplo n.º 1
0
        public static bool Plane(Plane p, Ray3f r, float tMin, float tMax, out HitRecord hit)
        {
            hit = new HitRecord();

            const float eps = 0.0001f;

            if (math.abs(math.dot(r.direction, p.Normal)) > eps)
            {
                float t = math.dot((p.Center - r.origin), p.Normal) / math.dot(r.direction, p.Normal);
                if (t > eps)
                {
                    hit.t      = t;
                    hit.point  = PointOnRay(r, t);
                    hit.normal = p.Normal;
                    return(true);
                }
            }

            return(false);
        }
Ejemplo n.º 2
0
        // Todo: optimize by splitting the below into boolean intersection funct, and then:
        // dist field
        // color field
        // normal field
        // material field
        // evaluating those for all the intermediate steps is useless
        // basically: https://www.shadertoy.com/view/ldl3zN IQ piano

        private static bool IntersectField(Ray3f r, Scene scene, short maxStep, float maxDist, out HitRecord hit)
        {
            hit = new HitRecord();

            const float eps = 0.001f;

            float3 p = r.origin;

            float totalDist = 0;

            for (int d = 0; d < maxStep; d++)
            {
                float dist = 99999f;

                float3   normal   = new float3(0, 0, 1);
                Material material = new Material();
                HitSphere(p, ref dist, ref normal, ref material);
                HitSpheres(p, ref dist, ref normal, ref material);
                HitFloor(p, ref dist, ref normal, ref material);

                if (dist <= eps)
                {
                    hit.point    = p;
                    hit.normal   = normal;
                    hit.material = material;
                    hit.t        = totalDist;
                    return(true);
                }

                totalDist += dist;
                p         += r.direction * dist;
            }

            return(false);
        }
Ejemplo n.º 3
0
        public static bool Scatter(Ray3f ray, HitRecord hit, ref Random rng, NativeArray <float3> fibs, out Ray3f scattered)
        {
            const float epsEscape = 0.002f;

            const float refIdx = 1.5f;

            switch (hit.material.Type)
            {
            case MaterialType.Dielectric: {
                float3 outwardNormal;
                float  nint;
                float3 reflected = math.reflect(ray.direction, hit.normal);
                float  cosine;

                if (math.dot(ray.direction, hit.normal) > 0f)
                {
                    outwardNormal = -hit.normal;
                    nint          = refIdx;
                    cosine        = refIdx * math.dot(ray.direction, hit.normal);
                }
                else
                {
                    outwardNormal = hit.normal;
                    nint          = 1f / refIdx;
                    cosine        = -math.dot(ray.direction, hit.normal);
                }

                float  reflectProb = 1f;
                float3 refracted;
                if (Trace.Refract(ray.direction, outwardNormal, nint, out refracted))
                {
                    reflectProb = Trace.Schlick(cosine, refIdx);
                }

                bool reflect = rng.NextFloat() < reflectProb;

                scattered = new Ray3f(
                    reflect ? hit.point + outwardNormal * epsEscape : hit.point - outwardNormal * epsEscape,
                    reflect ? reflected : refracted
                    );
                return(true);
            }

            case MaterialType.Metal: {
                float3 transmitted = math.reflect(ray.direction, hit.normal);
                transmitted += fibs[rng.NextInt(0, fibs.Length - 1)] * hit.material.Fuzz;
                transmitted  = math.normalize(transmitted);
                scattered    = new Ray3f(hit.point + hit.normal * epsEscape, transmitted);
                if (math.dot(scattered.direction, hit.normal) > 0)
                {
                    return(true);
                }
                return(false);
            }

            case MaterialType.Lambertian:
            default: {
                float3 target      = hit.normal + fibs[rng.NextInt(0, fibs.Length - 1)];
                float3 transmitted = math.normalize(target - hit.point);
                scattered = new Ray3f(hit.point + hit.normal * epsEscape, transmitted);
                return(true);
            }
            }
        }