Exemple #1
0
        public ColorF CreateAndTraceSecondaryRays(IntersectInfo info, Ray ray, Scene scene, int depth)
        {
            // calculate ambient light
            ColorF infoColorAtHit = ((IPrimitive)info.ClosestHitObject).GetColor(info);
            ColorF color          = infoColorAtHit * scene.background.Ambience;

            color.alpha = infoColorAtHit.alpha;
            double shininess = Math.Pow(10, ((IPrimitive)info.ClosestHitObject).Material.Gloss + 1);

            foreach (ILight light in scene.lights)
            {
                // calculate diffuse lighting
                Vector3 directiorFromHitToLight           = light.Origin - info.HitPosition;
                double  distanceToLight                   = directiorFromHitToLight.Length;
                Vector3 directiorFromHitToLightNormalized = directiorFromHitToLight.GetNormal();

                if (RenderDiffuse)
                {
                    double l = Vector3Ex.Dot(directiorFromHitToLightNormalized, info.NormalAtHit);
                    if (l > 0.0f)
                    {
                        color += infoColorAtHit * light.Illumination() * l;
                    }
                }

                // this is the max depth of raytracing.
                // increasing depth will calculate more accurate color, however it will
                // also take longer (exponentially)
                if (depth < 3)
                {
                    // calculate reflection ray
                    if (RenderReflection && ((IPrimitive)info.ClosestHitObject).Material.Reflection > 0)
                    {
                        Ray           reflectionRay  = GetReflectionRay(info.HitPosition, info.NormalAtHit, ray.directionNormal);
                        IntersectInfo reflectionInfo = TracePrimaryRay(reflectionRay, scene);
                        ColorF        reflectionColorAtHit;                  // = reflectionInfo.closestHitObject.GetColor(reflectionInfo);
                        if (reflectionInfo.HitType != IntersectionType.None && reflectionInfo.DistanceToHit > 0)
                        {
                            // recursive call, this makes reflections expensive
                            reflectionColorAtHit = CreateAndTraceSecondaryRays(reflectionInfo, reflectionRay, scene, depth + 1);
                        }
                        else                         // does not reflect an object, then reflect background color
                        {
                            reflectionColorAtHit           = scene.background.Color;
                            reflectionColorAtHit.Alpha0To1 = infoColorAtHit.alpha;
                        }

                        color = color.Blend(reflectionColorAtHit, ((IPrimitive)info.ClosestHitObject).Material.Reflection);
                    }

                    // calculate refraction ray
                    if (RenderRefraction && ((IPrimitive)info.ClosestHitObject).Material.Transparency > 0)
                    {
                        var           refractionRay        = new Ray(info.HitPosition, ray.directionNormal, Ray.sameSurfaceOffset, double.MaxValue);         // GetRefractionRay(info.hitPosition, info.normalAtHit, ray.direction, info.closestHit.Material.Refraction);
                        IntersectInfo refractionInfo       = TracePrimaryRay(refractionRay, scene);
                        ColorF        refractionColorAtHit = ((IPrimitive)refractionInfo.ClosestHitObject).GetColor(refractionInfo);
                        if (refractionInfo.HitType != IntersectionType.None && refractionInfo.DistanceToHit > 0)
                        {
                            // recursive call, this makes refractions expensive
                            refractionColorAtHit = CreateAndTraceSecondaryRays(refractionInfo, refractionRay, scene, depth + 1);
                        }
                        else
                        {
                            refractionColorAtHit           = scene.background.Color;
                            refractionColorAtHit.Alpha0To1 = infoColorAtHit.alpha;
                        }

                        color = refractionColorAtHit.Blend(color, ((IPrimitive)info.ClosestHitObject).Material.Transparency);
                    }
                }

                var shadow = new IntersectInfo();
                if (RenderShadow)
                {
                    // calculate shadow, create ray from intersection point to light
                    var shadowRay = new Ray(info.HitPosition, directiorFromHitToLightNormalized, Ray.sameSurfaceOffset, double.MaxValue)
                    {
                        isShadowRay = true
                    };                     // it may be useful to limit the length to the dist to the camera (but I doubt it LBB).

                    // if the normal at the closest hit is away from the shadow it is already it it's own shadow.
                    if (Vector3Ex.Dot(info.NormalAtHit, directiorFromHitToLightNormalized) < 0)
                    {
                        shadow.HitType  = IntersectionType.FrontFace;
                        color          *= 0.5;                // +0.5 * Math.Pow(shadow.closestHit.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount);
                        color.Alpha0To1 = infoColorAtHit.alpha;
                    }
                    else
                    {
                        // find any element in between intersection point and light
                        shadow = TracePrimaryRay(shadowRay, scene);
                        if (shadow.HitType != IntersectionType.None && shadow.ClosestHitObject != info.ClosestHitObject && shadow.DistanceToHit < distanceToLight)
                        {
                            // only cast shadow if the found intersection is another
                            // element than the current element
                            color          *= 0.5;                    // +0.5 * Math.Pow(shadow.closestHit.Material.Transparency, 0.5); // Math.Pow(.5, shadow.HitCount);
                            color.Alpha0To1 = infoColorAtHit.alpha;
                        }
                    }
                }

                // only show highlights if it is not in the shadow of another object
                if (RenderHighlights && shadow.HitType == IntersectionType.None && ((IPrimitive)info.ClosestHitObject).Material.Gloss > 0)
                {
                    // only show Gloss light if it is not in a shadow of another element.
                    // calculate Gloss lighting (Phong)
                    Vector3 lv = (info.HitPosition - light.Origin).GetNormal();
                    Vector3 e  = (ray.origin - info.HitPosition).GetNormal();
                    Vector3 h  = (e - lv).GetNormal();

                    double glossweight = 0.0;
                    glossweight = Math.Pow(Math.Max(Vector3Ex.Dot(info.NormalAtHit, h), 0), shininess);
                    color      += light.Illumination() * glossweight;
                }
            }

            color.Clamp0To1();
            return(color);
        }