Esempio n. 1
0
        private Color TraceRay(Ray r, int depth)
        {
            if (depth > MAX_DEPTH)
            {
                return(Color.Black);
            }

            IntersectionInfo info = GetFirstIntersection(r);

            if (info == null)   //луч не пересекает предмет
            {
                return(scene.InfinityColor);
            }

            double R = 0, G = 0, B = 0;
            //луч пересекает предмет

            double IdR = 0, IdG = 0, IdB = 0;
            double IsR = 0, IsG = 0, IsB = 0;
            double pFong = info.Material.FongCoeff;   //

            IEnumerator <Light> lights = scene.Lights;

            lights.Reset();

            while (lights.MoveNext())
            {
                Light    L = lights.Current;
                Vector3D V = new Vector3D(info.CrossPoint, L.Position); //направление на источник L
                V *= (1 / V.Length);

                if (IsVisible(L, info.CrossPoint))
                {
                    double distance    = VectorOperations.Distance(L.Position, info.CrossPoint);
                    double attenuation = 1;          // L.Attenuation(distance);

                    if (info.Material.Diffusion > 0) //для предмета задано свойство диффузного отражения
                    {
                        double cos = VectorOperations.Cos(info.Normal, V);
                        if (cos < 0)
                        {
                            cos = 0;
                        }

                        IdR += L.Color.R * cos / attenuation;
                        IdG += L.Color.G * cos / attenuation;
                        IdB += L.Color.B * cos / attenuation;
                    }

                    if (info.Material.Specularity > 0)  //для предмета задано свойство зеркального отражения
                    {
                        Vector3D reflected;
                        if (VectorOperations.ReflectedVector(info.Normal, r.Direction, out reflected))
                        {
                            double cos = VectorOperations.Cos(V, reflected);
                            if (cos < 0)
                            {
                                cos = 0;
                            }

                            IsR += L.Color.R * Math.Pow(cos, pFong) / attenuation;
                            IsG += L.Color.G * Math.Pow(cos, pFong) / attenuation;
                            IsB += L.Color.B * Math.Pow(cos, pFong) / attenuation;
                        }
                    }
                }
            }

            R += info.Material.Diffusion * IdR * info.Material.Color.R / 255;
            G += info.Material.Diffusion * IdG * info.Material.Color.G / 255;
            B += info.Material.Diffusion * IdB * info.Material.Color.B / 255;

            R += info.Material.Specularity * IsR;
            G += info.Material.Specularity * IsG;
            B += info.Material.Specularity * IsB;

            if (info.Material.Reflection > 0)
            {
                Vector3D reflected;
                if (VectorOperations.ReflectedVector(info.Normal, r.Direction, out reflected))
                {
                    Ray   reflectedRay   = new Ray(info.CrossPoint, reflected);
                    Color reflectedColor = TraceRay(reflectedRay, depth + 1);

                    R += info.Material.Reflection * reflectedColor.R;
                    G += info.Material.Reflection * reflectedColor.G;
                    B += info.Material.Reflection * reflectedColor.B;
                }
            }

            if (info.Material.Transparency > 0)
            {
                double   n12 = info.Material.RefractiveIndex;
                Vector3D refracted;

                if (VectorOperations.RefractedVector(info.Normal, r.Direction, n12, out refracted))
                {
                    Ray   refractedRay   = new Ray(info.CrossPoint, refracted);
                    Color refractedColor = TraceRay(refractedRay, depth + 1);

                    R += info.Material.Transparency * refractedColor.R;
                    G += info.Material.Transparency * refractedColor.G;
                    B += info.Material.Transparency * refractedColor.B;
                }
            }

            R += info.Material.Color.R * scene.Ambient;
            G += info.Material.Color.G * scene.Ambient;
            B += info.Material.Color.B * scene.Ambient;

            return(Color.FromArgb(Math.Min((int)R, 255), Math.Min((int)G, 255), Math.Min((int)B, 255)));
        }