Example #1
0
        // This is where the magic happens! Trace a ray...
        Vector3 Trace(Ray ray, short depth, bool drawDebugLine, bool absorb = false)
        {
            if (depth == maxDepth)
            {
                return(new Vector3());
            }

            // see if the ray hits anything.
            Intersection intersect = scene.Intersect(ray);

            if (intersect == null)
            { // We didn't hit anything. return the background.
                return(GetSkyColor(ray));
            }

            // Draw some debug output.
            if (drawDebugLine)
            {
                Debugger.DrawDebugLine(ray.origin.X, ray.origin.Z,
                                       intersect.intersectionPoint.X,
                                       intersect.intersectionPoint.Z, Color.Green);
            }

            // Magic!
            if (absorb && intersect.GetMaterial().absorbtion.Length() > 0)
            {
                return(intersect.dist
                       * -intersect.GetMaterial().absorbtion
                       + DoFancyColorCalculations(ray, intersect, depth, drawDebugLine));
            }
            else
            {
                return(DoFancyColorCalculations(ray, intersect, depth, drawDebugLine));
            }
        }
Example #2
0
        private float GetSchlickReflection(Intersection intersect, Ray ray)
        {
            float nDotD = Vector3.Dot(intersect.normal, ray.direction);

            float eta1 = 1; // air
            float eta2 = intersect.GetMaterial().refractionIndex;

            if (nDotD < 0)
            {
                nDotD = -nDotD; // we are outside the surface, we want cos(theta) to be positive
            }
            else
            {
                eta1 = eta2; eta2 = 1;
            }

            // Calculate some neccessary variables:
            float r0 = (eta1 - eta2) / (eta1 + eta2);

            r0 *= r0;
            float oneMinusCos = 1 - nDotD; // (1 - cos alpha)

            // Calculate how much light is reflected:
            return(r0 + (1 - r0) * oneMinusCos * oneMinusCos * oneMinusCos * oneMinusCos * oneMinusCos);
        }
Example #3
0
        private Vector3 Refract(Ray ray, Intersection intersect, short depht, bool drawDebugline)
        {
            float nDotD = -Vector3.Dot(intersect.normal, ray.direction);
            float eta1 = 1, eta2 = intersect.GetMaterial().refractionIndex;

            bool absorb = true;

            if (nDotD < 0)
            {
                // we are inside the surface, cos(theta) is already positive but reverse normal direction
                eta1 = eta2; eta2 = 1;
                intersect.InvertNormal();
                absorb = false;
            }

            nDotD = -Vector3.Dot(intersect.normal, ray.direction);
            float eta = eta1 / eta2;
            float c   = eta * eta * (1 - nDotD * nDotD);

            if (c > 1)
            {
                return(new Vector3(0, 0, 0));       // Total internal reflection
            }
            float cosT = (float)Math.Sqrt(1 - c);

            Ray refractRay = new Ray(intersect.intersectionPoint,
                                     eta * ray.direction + (eta * nDotD - cosT) * intersect.normal);

            refractRay.origin += 0.001f * refractRay.direction;  // offset by a small margin

            return(Trace(refractRay, depht, drawDebugline, absorb));
        }
Example #4
0
        // Do we have to pass all these ugly arguments? ='(
        // If we want to multi-thread it: yes.
        private Vector3 DoFancyColorCalculations(Ray ray, Intersection intersect, short depth, bool drawDebugLine)
        {
            depth++; // increment our recursion depth.
            Vector3 color = new Vector3();

            Material material = intersect.GetMaterial();

            if (material.isMirror)
            {
                color = material.reflectiveness * Reflect(ray, intersect, depth, drawDebugLine);
            }
            if (material.isDielectic)
            {
                float reflection = GetSchlickReflection(intersect, ray);

                // Now do the magic:
                color += material.transparency * reflection * Reflect(ray, intersect, depth, drawDebugLine);       // reFLECT
                color += material.transparency * (1 - reflection) * Refract(ray, intersect, depth, drawDebugLine); //reFRACT
            }
            if (material.isShiny)
            {
                // Calculate reflection of shiny object
            }

            color += intersect.primitive.material.diffuseness
                     * scene.DirectIllumination(intersect, drawDebugLine)
                     * intersect.primitive.GetColor(intersect.intersectionPoint);
            return(color);
        }