Exemple #1
0
        private ColorVector RenderShadowAndHighlights(ColorVector currentColor, IntersectionInfo intersectionInfo,
                                                      ILight light)
        {
            var v         = (light.Position - intersectionInfo.Position).Normalize();
            var shadowRay = new Ray(intersectionInfo.Position, v);

            var color = currentColor;

            if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape))
            {
                if (RenderData.RenderShadow)
                {
                    var shadowIntersection = TestIntersection(shadowRay, shape.Id);
                    if (shadowIntersection.IsHit)
                    {
                        if (Scene.TryGetShape(shadowIntersection.ElementId, out var shadowShape))
                        {
                            if (shadowShape.Id != shape.Id)
                            {
                                var trans      = shadowShape.GetMaterial().KTransparent;
                                var transPower = Math.Pow(trans, 0.5);
                                color = color * (0.5 + 0.5 * transPower);
                            }
                        }
                    }

                    color = RenderHighlights(color, shape, shadowIntersection, light);
                }
            }

            return(color);
        }
Exemple #2
0
        private ColorVector RenderDiffuse(ColorVector currentColor, IntersectionInfo intersectionInfo, ILight light)
        {
            if (RenderData.RenderDiffuse)
            {
                var v = (light.Position - intersectionInfo.Position).Normalize();
                var l = v.Dot(intersectionInfo.Normal);
                if (l > 0.0)
                {
                    return(currentColor + intersectionInfo.Color * light.Color * l);
                }
            }

            return(currentColor);
        }
Exemple #3
0
        private ColorVector RenderHighlights(ColorVector currentColor, IShape shape, IntersectionInfo shadowIntersection,
                                             ILight light)
        {
            if (RenderData.RenderHighlights && !shadowIntersection.IsHit && shape.GetMaterial().Gloss > 0.0)
            {
                var lv          = (shape.Position - light.Position).Normalize();
                var e           = (Camera.Position - shape.Position).Normalize();
                var h           = (e - lv).Normalize();
                var glossWeight = 0.0; // todo: pow(max(dot(info.Normal, h), 0.0), shininess)
                return(currentColor + light.Color * glossWeight);
            }

            return(currentColor);
        }
Exemple #4
0
        private IntersectionInfo TestIntersectionBasic(Ray ray, int excludeId)
        {
            var bestInfo = new IntersectionInfo();

            foreach (var shape in Scene.Shapes.Where(s => s.Id != excludeId))
            {
                var info = shape.Intersect(ray);
                if (info.IsHit && info.Distance < bestInfo.Distance && info.Distance >= 0.0)
                {
                    bestInfo = info;
                }
            }

            return(bestInfo);
        }
Exemple #5
0
        private ColorVector RayTrace(IntersectionInfo intersectionInfo, Ray ray, int depth)
        {
            var color = intersectionInfo.Color * Scene.Background.Ambience;

            foreach (var light in Scene.Lights)
            {
                color = RenderDiffuse(color, intersectionInfo, light);

                if (depth < RenderData.RayTraceDepth)
                {
                    color = RenderReflection(color, intersectionInfo, ray, depth);
                    color = RenderRefraction(color, intersectionInfo, ray, depth);
                    color = RenderShadowAndHighlights(color, intersectionInfo, light);
                }
            }

            return(color);
        }
Exemple #6
0
        private ColorVector RenderReflection(ColorVector currentColor, IntersectionInfo intersectionInfo, Ray ray,
                                             int depth)
        {
            if (RenderData.RenderReflection)
            {
                if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape))
                {
                    if (shape.GetMaterial().KReflection > 0.0)
                    {
                        var reflectionRay = GetReflectionRay(intersectionInfo.Position, intersectionInfo.Normal, ray.Direction);
                        var refl          = TestIntersection(reflectionRay, shape.Id);
                        var reflColor     = refl.IsHit && refl.Distance > 0.0
              ? RayTrace(refl, reflectionRay, depth + 1)
              : Scene.Background.Color;

                        return(currentColor.Blend(reflColor, shape.GetMaterial().KReflection));
                    }
                }
            }

            return(currentColor);
        }
Exemple #7
0
        private ColorVector RenderRefraction(ColorVector currentColor, IntersectionInfo intersectionInfo, Ray ray,
                                             int depth)
        {
            if (RenderData.RenderRefraction)
            {
                if (Scene.TryGetShape(intersectionInfo.ElementId, out var shape))
                {
                    if (shape.GetMaterial().KTransparent > 0.0)
                    {
                        var refractionRay = GetRefractionRay(intersectionInfo.Position, intersectionInfo.Normal, ray.Direction,
                                                             shape.GetMaterial().Refraction);
                        var refr           = shape.Intersect(refractionRay);
                        var refractedColor = Scene.Background.Color;
                        if (refr.IsHit)
                        {
                            if (Scene.TryGetShape(refr.ElementId, out var refrShape))
                            {
                                var elemRefractionRay = GetRefractionRay(refr.Position, refr.Normal, refractionRay.Direction,
                                                                         refrShape.GetMaterial().Refraction);
                                var secondRefr = TestIntersection(elemRefractionRay, shape.Id);
                                if (secondRefr.IsHit && secondRefr.Distance > 0.0)
                                {
                                    refractedColor = RayTrace(secondRefr, elemRefractionRay, depth + 1);
                                }
                            }
                        }
                        else
                        {
                            refractedColor = Scene.Background.Color;
                        }

                        return(currentColor.Blend(refractedColor, shape.GetMaterial().KTransparent));
                    }
                }
            }

            return(currentColor);
        }
Exemple #8
0
        private IntersectionInfo FindIntersectionNode(KdNode node, BoundingBox bbox, Ray ray)
        {
            if (node == null)
            {
                return(new IntersectionInfo());
            }

            if (node.Plane == KdNodePlane.NoPlane)
            {
                // leaf node

                var bestInfo = new IntersectionInfo();

                foreach (var shape in node.Shapes)
                {
                    var info = shape.Intersect(ray);
                    if (info.IsHit)
                    {
                        // if (bbox.IsPointInside(info.Position))
                        {
                            if (info.Distance < bestInfo.Distance && info.Distance >= 0.0)
                            {
                                bestInfo = info;
                            }
                        }
                    }
                }

                if (bestInfo.IsHit)
                {
                    return(bestInfo);
                }
                else
                {
                    return(new IntersectionInfo());
                }
            }

            var(leftIsFront, frontBbox, backBbox) = SplitPlane(node, bbox, ray);

            var frontNode = leftIsFront ? node.Left : node.Right;
            var backNode  = leftIsFront ? node.Right : node.Left;

            if (IsBoundingBoxIntersection(frontBbox, ray))
            {
                var intInfo = FindIntersectionNode(frontNode, frontBbox, ray);
                if (intInfo.IsHit)
                {
                    return(intInfo);
                }
                else
                {
                    if (IsBoundingBoxIntersection(backBbox, ray))
                    {
                        intInfo = FindIntersectionNode(backNode, backBbox, ray);
                        return(intInfo.IsHit ? intInfo : new IntersectionInfo());
                    }
                    else
                    {
                        return(new IntersectionInfo());
                    }
                }
            }
            else
            {
                return(new IntersectionInfo());
            }
        }
Exemple #9
0
        private ColorVector CalculateColor(Ray ray, IntersectionInfo intInfo, double rayIntensity, int depth)
        {
            if (intInfo.IsHit && Scene.TryGetShape(intInfo.ElementId, out IShape shape))
            {
                var material       = shape.GetMaterial();
                var objectColor    = intInfo.Color;
                var ambientColor   = new ColorVector();
                var diffuseColor   = new ColorVector();
                var reflectedColor = new ColorVector();
                var specularColor  = new ColorVector();

                var resultColor = new ColorVector();

                double fogDensity = 0;
                if (Scene.HasFogDensity)
                {
                    fogDensity = Scene.GetFogDensity(intInfo.Distance);
                }

                if (material.KAmbient > double.Epsilon)
                {
                    ambientColor = Scene.Background.Color.Mix(objectColor);
                    resultColor  = resultColor.Mix(ambientColor);
                }

                if (material.KDiffuse > double.Epsilon)
                {
                    diffuseColor = objectColor;
                    if (Scene.HasLights)
                    {
                        diffuseColor = diffuseColor.Mix(GetLightingColor(intInfo.Position, intInfo.Normal));
                    }

                    resultColor = resultColor.Blend(diffuseColor, material.KDiffuse);
                }

                if (material.KSpecular > double.Epsilon)
                {
                    specularColor = Scene.Background.Color;
                    if (Scene.HasLights)
                    {
                        var reflectedRay = ReflectRay(ray, intInfo.Normal);
                        specularColor = GetSpecularColor(reflectedRay, material.Gloss);
                    }

                    resultColor = resultColor.Blend(specularColor, material.KSpecular);
                }

                if (material.KReflection > double.Epsilon)
                {
                    // avoid deep recursion by tracing rays which have intensity greater than threshold
                    // and avoid infinite recursion by limiting number of recursive calls
                    if (rayIntensity > ThresholdRayIntensity && depth < MaxRayRecursionLevel)
                    {
                        var reflectedRay = ReflectRay(ray, intInfo.Normal);
                        reflectedColor = TraceRecursive(
                            reflectedRay,
                            rayIntensity * material.KReflection * (1 - fogDensity),
                            depth + 1);
                    }
                    else
                    {
                        reflectedColor = Scene.Background.Color;
                    }

                    resultColor = resultColor.Blend(reflectedColor, material.KReflection);
                }

                if (Scene.HasFogDensity)
                {
                    resultColor = (Scene.Background.Color * fogDensity) + (resultColor * (1.0 - fogDensity));
                }

                return(resultColor);
            }
            else
            {
                return(Scene.Background.Color);
            }
        }